From 9a2aee87910c08f32ae71a3cf3ab46c205d6d275 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 3 Sep 2018 20:46:33 -0400 Subject: [PATCH 01/99] working --- x/distribution/handler.go | 8 ++ x/distribution/keeper.go | 91 ----------------------- x/distribution/keeper/keeper.go | 1 + x/distribution/keeper/keeper_test.go | 1 + x/distribution/keeper/key.go | 29 ++++++++ x/distribution/keeper_test.go | 31 -------- x/distribution/movement.go | 72 ------------------ x/distribution/types.go | 107 --------------------------- x/distribution/types/types.go | 35 +++++++++ 9 files changed, 74 insertions(+), 301 deletions(-) create mode 100644 x/distribution/handler.go delete mode 100644 x/distribution/keeper.go create mode 100644 x/distribution/keeper/keeper.go create mode 100644 x/distribution/keeper/keeper_test.go create mode 100644 x/distribution/keeper/key.go delete mode 100644 x/distribution/keeper_test.go delete mode 100644 x/distribution/movement.go delete mode 100644 x/distribution/types.go create mode 100644 x/distribution/types/types.go diff --git a/x/distribution/handler.go b/x/distribution/handler.go new file mode 100644 index 0000000000..da129855e7 --- /dev/null +++ b/x/distribution/handler.go @@ -0,0 +1,8 @@ +package stake + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// burn burn burn +func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} diff --git a/x/distribution/keeper.go b/x/distribution/keeper.go deleted file mode 100644 index aba07eaca1..0000000000 --- a/x/distribution/keeper.go +++ /dev/null @@ -1,91 +0,0 @@ -package stake - -//// keeper of the staking store -//type Keeper struct { -//storeKey sdk.StoreKey -//cdc *wire.Codec -//coinKeeper bank.Keeper - -//// codespace -//codespace sdk.CodespaceType -//} - -//func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { -//keeper := Keeper{ -//storeKey: key, -//cdc: cdc, -//coinKeeper: ck, -//codespace: codespace, -//} -//return keeper -//} - -////_________________________________________________________________________ - -//// cummulative power of the non-absent prevotes -//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Dec { -//store := ctx.KVStore(k.storeKey) - -//// get absent prevote indexes -//absents := ctx.AbsentValidators() - -//TotalPower := sdk.ZeroDec() -//i := int32(0) -//iterator := store.SubspaceIterator(ValidatorsBondedKey) -//for ; iterator.Valid(); iterator.Next() { - -//skip := false -//for j, absentIndex := range absents { -//if absentIndex > i { -//break -//} - -//// if non-voting validator found, skip adding its power -//if absentIndex == i { -//absents = append(absents[:j], absents[j+1:]...) // won't need again -//skip = true -//break -//} -//} -//if skip { -//continue -//} - -//bz := iterator.Value() -//var validator Validator -//k.cdc.MustUnmarshalBinary(bz, &validator) -//TotalPower = TotalPower.Add(validator.Power) -//i++ -//} -//iterator.Close() -//return TotalPower -//} - -////_______________________________________________________________________ - -//// XXX TODO trim functionality - -//// retrieve all the power changes which occur after a height -//func (k Keeper) GetPowerChangesAfterHeight(ctx sdk.Context, earliestHeight int64) (pcs []PowerChange) { -//store := ctx.KVStore(k.storeKey) - -//iterator := store.SubspaceIterator(PowerChangeKey) //smallest to largest -//for ; iterator.Valid(); iterator.Next() { -//pcBytes := iterator.Value() -//var pc PowerChange -//k.cdc.MustUnmarshalBinary(pcBytes, &pc) -//if pc.Height < earliestHeight { -//break -//} -//pcs = append(pcs, pc) -//} -//iterator.Close() -//return -//} - -//// set a power change -//func (k Keeper) setPowerChange(ctx sdk.Context, pc PowerChange) { -//store := ctx.KVStore(k.storeKey) -//b := k.cdc.MustMarshalBinary(pc) -//store.Set(GetPowerChangeKey(pc.Height), b) -//} diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go new file mode 100644 index 0000000000..b55569d4a4 --- /dev/null +++ b/x/distribution/keeper/keeper.go @@ -0,0 +1 @@ +package keeper diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go new file mode 100644 index 0000000000..b55569d4a4 --- /dev/null +++ b/x/distribution/keeper/keeper_test.go @@ -0,0 +1 @@ +package keeper diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go new file mode 100644 index 0000000000..f4cf1e0f9c --- /dev/null +++ b/x/distribution/keeper/key.go @@ -0,0 +1,29 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// keys/key-prefixes +var ( + GlobalKey = []byte{0x00} // key for global distribution state + ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution + DelegatorDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution +) + +// 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.DelegatorDistInfo +func GetDelegationDistInfoKey(delAddr sdk.AccAddress, valOperatorAddr 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(DelegatorDistInfoKey, delAddr.Bytes()...) +} diff --git a/x/distribution/keeper_test.go b/x/distribution/keeper_test.go deleted file mode 100644 index 8902680604..0000000000 --- a/x/distribution/keeper_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package stake - -//// test if is a gotValidator from the last update -//func TestGetTotalPrecommitVotingPower(t *testing.T) { -//ctx, _, keeper := createTestInput(t, false, 0) - -//amts := []int64{10000, 1000, 100, 10, 1} -//var candidatesIn [5]Candidate -//for i, amt := range amts { -//candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{}) -//candidatesIn[i].BondedShares = sdk.NewDec(amt) -//candidatesIn[i].DelegatorShares = sdk.NewDec(amt) -//keeper.setCandidate(ctx, candidatesIn[i]) -//} - -//// test that an empty gotValidator set doesn't have any gotValidators -//gotValidators := keeper.GetValidators(ctx) -//require.Equal(t, 5, len(gotValidators)) - -//totPow := keeper.GetTotalPrecommitVotingPower(ctx) -//exp := sdk.NewDec(11111) -//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow) - -//// set absent gotValidators to be the 1st and 3rd record sorted by pubKey address -//ctx = ctx.WithAbsentValidators([]int32{1, 3}) -//totPow = keeper.GetTotalPrecommitVotingPower(ctx) - -//// XXX verify that this order should infact exclude these two records -//exp = sdk.NewDec(11100) -//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow) -//} diff --git a/x/distribution/movement.go b/x/distribution/movement.go deleted file mode 100644 index 399a25a681..0000000000 --- a/x/distribution/movement.go +++ /dev/null @@ -1,72 +0,0 @@ -package stake - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// burn burn burn -func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} - -//// Handle fee distribution to the validators and delegators -//func (k Keeper) FeeHandler(ctx sdk.Context, collectedFees sdk.Coins) { -//pool := k.GetPool(ctx) -//params := k.GetParams(ctx) - -//// XXX determine -//candidate := NewCandidate(addrs[0], pks[0], Description{}) - -//// calculate the proposer reward -//precommitPower := k.GetTotalPrecommitVotingPower(ctx) -//toProposer := coinsMulRat(collectedFees, (sdk.NewDec(1, 100).Add(sdk.NewDec(4, 100).Mul(precommitPower).Quo(pool.BondedShares)))) -//candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer) - -//toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee) -//pool.FeeReservePool = pool.FeeReservePool.Plus(toReservePool) - -//distributedReward := (collectedFees.Minus(toProposer)).Minus(toReservePool) -//pool.FeePool = pool.FeePool.Plus(distributedReward) -//pool.FeeSumReceived = pool.FeeSumReceived.Plus(distributedReward) -//pool.FeeRecent = distributedReward - -//// lastly update the FeeRecent term -//pool.FeeRecent = collectedFees - -//k.setPool(ctx, pool) -//} - -//func coinsMulRat(coins sdk.Coins, rat sdk.Dec) sdk.Coins { -//var res sdk.Coins -//for _, coin := range coins { -//coinMulAmt := rat.Mul(sdk.NewDec(coin.Amount)).Evaluate() -//coinMul := sdk.Coins{{coin.Denom, coinMulAmt}} -//res = res.Plus(coinMul) -//} -//return res -//} - -////____________________________________________________________________________- - -//// calculate adjustment changes for a candidate at a height -//func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) { - -//heightRat := sdk.NewDec(height) -//lastHeightRat := sdk.NewDec(height - 1) -//candidateFeeCount := candidate.BondedShares.Mul(heightRat) -//poolFeeCount := pool.BondedShares.Mul(heightRat) - -//for i, denom := range denoms { -//poolFeeSumReceived := sdk.NewDec(pool.FeeSumReceived.AmountOf(denom)) -//poolFeeRecent := sdk.NewDec(pool.FeeRecent.AmountOf(denom)) -//// calculate simple and projected pools -//simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived) -//calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent) -//calc2 := candidate.BondedShares.Quo(pool.BondedShares).Mul(poolFeeRecent) -//projectedPool := calc1.Add(calc2) - -//AdjustmentChange := simplePool.Sub(projectedPool) -//candidate.FeeAdjustments[i] = candidate.FeeAdjustments[i].Add(AdjustmentChange) -//pool.FeeAdjustments[i] = pool.FeeAdjustments[i].Add(AdjustmentChange) -//} - -//return candidate, pool -//} diff --git a/x/distribution/types.go b/x/distribution/types.go deleted file mode 100644 index 2234104717..0000000000 --- a/x/distribution/types.go +++ /dev/null @@ -1,107 +0,0 @@ -package stake - -//// GenesisState - all staking state that must be provided at genesis -//type GenesisState struct { -//Pool Pool `json:"pool"` -//Params Params `json:"params"` -//} - -//func NewGenesisState(pool Pool, params Params, candidates []Candidate, bonds []Delegation) GenesisState { -//return GenesisState{ -//Pool: pool, -//Params: params, -//} -//} - -//// get raw genesis raw message for testing -//func DefaultGenesisState() GenesisState { -//return GenesisState{ -//Pool: initialPool(), -//Params: defaultParams(), -//} -//} - -//// fee information for a validator -//type Validator struct { -//Adjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms -//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // total shares of a global hold pools -//} - -////_________________________________________________________________________ - -//// Params defines the high level settings for staking -//type Params struct { -//FeeDenoms []string `json:"fee_denoms"` // accepted fee denoms -//ReservePoolFee sdk.Dec `json:"reserve_pool_fee"` // percent of fees which go to reserve pool -//} - -//func (p Params) equal(p2 Params) bool { -//return p.BondDenom == p2.BondDenom && -//p.ReservePoolFee.Equal(p2.ReservePoolFee) -//} - -//func defaultParams() Params { -//return Params{ -//FeeDenoms: []string{"steak"}, -//ReservePoolFee: sdk.NewDec(5, 100), -//} -//} - -////_________________________________________________________________________ - -//// Pool - dynamic parameters of the current state -//type Pool struct { -//FeeReservePool sdk.Coins `json:"fee_reserve_pool"` // XXX reserve pool of collected fees for use by governance -//FeePool sdk.Coins `json:"fee_pool"` // XXX fee pool for all the fee shares which have already been distributed -//FeeSumReceived sdk.Coins `json:"fee_sum_received"` // XXX sum of all fees received, post reserve pool `json:"fee_sum_received"` -//FeeRecent sdk.Coins `json:"fee_recent"` // XXX most recent fee collected -//FeeAdjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms -//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // XXX last recorded bonded shares -//} - -//func (p Pool) equal(p2 Pool) bool { -//return p.FeeReservePool.IsEqual(p2.FeeReservePool) && -//p.FeePool.IsEqual(p2.FeePool) && -//p.FeeSumReceived.IsEqual(p2.FeeSumReceived) && -//p.FeeRecent.IsEqual(p2.FeeRecent) && -//sdk.DecsEqual(p.FeeAdjustments, p2.FeeAdjustments) && -//p.PrevBondedShares.Equal(p2.PrevBondedShares) -//} - -//// initial pool for testing -//func initialPool() Pool { -//return Pool{ -//FeeReservePool: sdk.Coins(nil), -//FeePool: sdk.Coins(nil), -//FeeSumReceived: sdk.Coins(nil), -//FeeRecent: sdk.Coins(nil), -//FeeAdjustments: []sdk.Dec{sdk.ZeroDec()}, -//PrevBondedShares: sdk.ZeroDec(), -//} -//} - -////_________________________________________________________________________ - -//// Used in calculation of fee shares, added to a queue for each block where a power change occures -//type PowerChange struct { -//Height int64 `json:"height"` // block height at change -//Power sdk.Dec `json:"power"` // total power at change -//PrevPower sdk.Dec `json:"prev_power"` // total power at previous height-1 -//FeesIn sdk.Coins `json:"fees_in"` // fees in at block height -//PrevFeePool sdk.Coins `json:"prev_fee_pool"` // total fees in at previous block height -//} - -////_________________________________________________________________________ -//// KEY MANAGEMENT - -//var ( -//// Keys for store prefixes -//PowerChangeKey = []byte{0x09} // prefix for power change object -//) - -//// get the key for the accumulated update validators -//func GetPowerChangeKey(height int64) []byte { -//heightBytes := make([]byte, binary.MaxVarintLen64) -//binary.BigEndian.PutUint64(heightBytes, ^uint64(height)) // invert height (older validators first) -//return append(PowerChangeKey, heightBytes...) -//} diff --git a/x/distribution/types/types.go b/x/distribution/types/types.go new file mode 100644 index 0000000000..5a4ca9e2c8 --- /dev/null +++ b/x/distribution/types/types.go @@ -0,0 +1,35 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// coins with decimal +type DecCoins []DecCoin + +// Coins which can have additional decimal points +type DecCoin struct { + Amount sdk.Dec + Denom string +} + +// Global state for distribution +type Global 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 + CommunityPool DecCoins // pool for community funds yet to be spent +} + +// distribution info for a particular validator +type ValidatorDistInfo struct { + GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool + Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward) + PoolCommission DecCoins // commission collected by this validator (pending withdrawal) + + TotalDelAccumUpdateHeight int64 // last height which the total delegator accum was updated + TotalDelAccum sdk.Dec // total proposer pool accumulation factor held by delegators +} + +// distribution info for a delegation +type DelegatorDistInfo struct { + WithdrawalHeight int64 // last time this delegation withdrew rewards +} From 48aa9a6ad50c36a3587db92d46043d79fb1347d1 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 4 Sep 2018 16:19:37 -0400 Subject: [PATCH 02/99] working, moved WIP distribution spec to attic --- .../WIP-lamborghini-distribution/README.md | 0 .../WIP-lamborghini-distribution/end_block.md | 0 .../example_sheet/distribution.xlsx | Bin .../future_improvements.md | 0 .../WIP-lamborghini-distribution/overview.md | 0 .../WIP-lamborghini-distribution/state.md | 0 .../transactions.md | 0 .../WIP-lamborghini-distribution/triggers.md | 0 docs/spec/distribution/transactions.md | 6 +- x/distribution/handler.go | 136 ++++++++++++++++++ x/distribution/hooks.go | 28 ++++ x/distribution/keeper/keeper.go | 101 +++++++++++++ x/distribution/keeper/keeper_test.go | 2 + x/distribution/types/delegator_info.go | 30 ++++ x/distribution/types/global.go | 30 ++++ x/distribution/types/types.go | 35 ----- x/distribution/types/validator_info.go | 57 ++++++++ 17 files changed, 387 insertions(+), 38 deletions(-) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/README.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/end_block.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/example_sheet/distribution.xlsx (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/future_improvements.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/overview.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/state.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/transactions.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/triggers.md (100%) create mode 100644 x/distribution/hooks.go create mode 100644 x/distribution/types/delegator_info.go create mode 100644 x/distribution/types/global.go delete mode 100644 x/distribution/types/types.go create mode 100644 x/distribution/types/validator_info.go diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/README.md b/docs/_attic/WIP-lamborghini-distribution/README.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/README.md rename to docs/_attic/WIP-lamborghini-distribution/README.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/end_block.md b/docs/_attic/WIP-lamborghini-distribution/end_block.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/end_block.md rename to docs/_attic/WIP-lamborghini-distribution/end_block.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx b/docs/_attic/WIP-lamborghini-distribution/example_sheet/distribution.xlsx similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx rename to docs/_attic/WIP-lamborghini-distribution/example_sheet/distribution.xlsx diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md b/docs/_attic/WIP-lamborghini-distribution/future_improvements.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md rename to docs/_attic/WIP-lamborghini-distribution/future_improvements.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/overview.md b/docs/_attic/WIP-lamborghini-distribution/overview.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/overview.md rename to docs/_attic/WIP-lamborghini-distribution/overview.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/state.md b/docs/_attic/WIP-lamborghini-distribution/state.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/state.md rename to docs/_attic/WIP-lamborghini-distribution/state.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/transactions.md b/docs/_attic/WIP-lamborghini-distribution/transactions.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/transactions.md rename to docs/_attic/WIP-lamborghini-distribution/transactions.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/triggers.md b/docs/_attic/WIP-lamborghini-distribution/triggers.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/triggers.md rename to docs/_attic/WIP-lamborghini-distribution/triggers.md diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 0b89ae44ee..8616206207 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -148,7 +148,7 @@ 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) ( +func (vi ValidatorDistInfo) TakeGlobalRewards(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) ( vi ValidatorDistInfo, g Global) g.UpdateTotalValAccum(height, totalBondedShares) @@ -180,7 +180,7 @@ func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, di DelegatorDistInfo, g Global, withdrawn DecCoins) vi.UpdateTotalDelAccum(height, totalDelShares) - g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate) + g = vi.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) blocks = height - di.WithdrawalHeight di.WithdrawalHeight = height @@ -204,7 +204,7 @@ func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) ( vi ValidatorDistInfo, g Global, withdrawn DecCoins) - g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate) + g = vi.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) withdrawalTokens := vi.PoolCommission vi.PoolCommission = 0 diff --git a/x/distribution/handler.go b/x/distribution/handler.go index da129855e7..bd317b9c14 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -1,8 +1,144 @@ package stake import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/stake/keeper" ) // burn burn burn func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} + +// Called every block, process inflation, update validator set +func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Validator) { + pool := k.GetPool(ctx) + + // Process provision inflation + blockTime := ctx.BlockHeader().Time + if blockTime.Sub(pool.InflationLastTime) >= time.Hour { + params := k.GetParams(ctx) + pool.InflationLastTime = blockTime + pool = pool.ProcessProvisions(params) + k.SetPool(ctx, pool) + } + + // reset the intra-transaction counter + k.SetIntraTxCounter(ctx, 0) + + // calculate validator set changes + ValidatorUpdates = k.GetTendermintUpdates(ctx) + k.ClearTendermintUpdates(ctx) + return +} + +/* +func AllocateFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution, + sumPowerPrecommitValidators, totalBondedTokens, communityTax, + proposerCommissionRate sdk.Dec) + + feesCollectedDec = MakeDecCoins(feesCollected) + proposerReward = feesCollectedDec * (0.01 + 0.04 + * sumPowerPrecommitValidators / totalBondedTokens) + + commission = proposerReward * proposerCommissionRate + proposer.PoolCommission += commission + proposer.Pool += proposerReward - commission + + communityFunding = feesCollectedDec * communityTax + global.CommunityFund += communityFunding + + poolReceived = feesCollectedDec - proposerReward - communityFunding + global.Pool += poolReceived + global.EverReceivedPool += poolReceived + global.LastReceivedPool = poolReceived + + SetValidatorDistribution(proposer) + SetGlobal(global) + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +type TxWithdrawDelegationRewardsAll struct { + delegatorAddr sdk.AccAddress + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +func WithdrawDelegationRewardsAll(delegatorAddr, withdrawAddr sdk.AccAddress) + height = GetHeight() + withdraw = GetDelegatorRewardsAll(delegatorAddr, height) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) + +func GetDelegatorRewardsAll(delegatorAddr sdk.AccAddress, height int64) DecCoins + + // get all distribution scenarios + delegations = GetDelegations(delegatorAddr) + + // collect all entitled rewards + withdraw = 0 + pool = stake.GetPool() + global = GetGlobal() + 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, + validator.Tokens, validator.DelegatorShares, validator.Commission) + withdraw += diWithdraw + + SetGlobal(global) + return withdraw + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +type TxWithdrawDelegationReward struct { + delegatorAddr sdk.AccAddress + validatorAddr sdk.AccAddress + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress) + height = GetHeight() + + // get all distribution scenarios + pool = stake.GetPool() + global = GetGlobal() + delInfo = GetDelegationDistInfo(delegatorAddr, + validatorAddr) + valInfo = GetValidatorDistInfo(validatorAddr) + validator = GetValidator(validatorAddr) + + global, withdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens, + validator.Tokens, validator.DelegatorShares, validator.Commission) + + SetGlobal(global) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +type TxWithdrawValidatorRewardsAll struct { + operatorAddr sdk.AccAddress // validator address to withdraw from + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +func WithdrawValidatorRewardsAll(operatorAddr, withdrawAddr sdk.AccAddress) + + height = GetHeight() + global = GetGlobal() + pool = GetPool() + ValInfo = GetValidatorDistInfo(delegation.ValidatorAddr) + validator = GetValidator(delegation.ValidatorAddr) + + // withdraw self-delegation + withdraw = GetDelegatorRewardsAll(validator.OperatorAddr, height) + + // withdrawal validator commission rewards + global, commission = valInfo.WithdrawCommission(global, valInfo, height, pool.BondedTokens, + validator.Tokens, validator.Commission) + withdraw += commission + SetGlobal(global) + + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) + +*/ diff --git a/x/distribution/hooks.go b/x/distribution/hooks.go new file mode 100644 index 0000000000..689ffabbf8 --- /dev/null +++ b/x/distribution/hooks.go @@ -0,0 +1,28 @@ +package stake + +/* +## Create or modify delegation distribution + + - triggered-by: `stake.TxDelegate`, `stake.TxBeginRedelegate`, `stake.TxBeginUnbonding` + +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. + +## Commission rate change + + - triggered-by: `stake.TxEditValidator` + +If a validator changes its commission rate, all commission on fees must be +simultaneously withdrawn using the transaction `TxWithdrawValidator`. +Additionally the change and associated height must be recorded in a +`ValidatorUpdate` state record. + +## Change in Validator State + + - triggered-by: `stake.Slash`, `stake.UpdateValidator` + +Whenever a validator is slashed or enters/leaves the validator group all of the +validator entitled reward tokens must be simultaneously withdrawn from +`Global.Pool` and added to `ValidatorDistInfo.Pool`. +*/ diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index b55569d4a4..a5d6459ac5 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -1 +1,102 @@ package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/stake" + wire "github.com/tendermint/go-wire" +) + +// keeper of the stake store +type Keeper struct { + storeKey sdk.StoreKey + cdc *wire.Codec + coinKeeper bank.Keeper + stakeKeeper stake.Keeper + + // codespace + codespace sdk.CodespaceType +} + +func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, + sk stake.Keeper, codespace sdk.CodespaceType) Keeper { + + keeper := Keeper{ + storeKey: key, + cdc: cdc, + coinKeeper: ck, + codespace: codespace, + } + return keeper +} + +//______________________________________________________________________ + +// get the global distribution info +func (k Keeper) GetGlobal(ctx sdk.Context) (global types.Global) { + store := ctx.KVStore(k.storeKey) + + b := store.Get(GlobalKey) + if b == nil { + panic("Stored global should not have been nil") + } + + k.cdc.MustUnmarshalBinary(b, &global) + return +} + +// set the global distribution info +func (k Keeper) SetGlobal(ctx sdk.Context, global types.Global) { + store := ctx.KVStore(k.storeKey) + b := k.cdc.MustMarshalBinary(global) + store.Set(GlobalKey, b) +} + +//______________________________________________________________________ + +// get the delegator distribution info +func (k Keeper) GetDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, + valOperatorAddr sdk.ValAddress) (ddi types.DelegatorDistInfo) { + + 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) SetDelegatorDistInfo(ctx sdk.Context, ddi types.DelegatorDistInfo) { + store := ctx.KVStore(k.storeKey) + b := k.cdc.MustMarshalBinary(ddi) + store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b) +} + +//______________________________________________________________________ + +// 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 delegation-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) +} diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go index b55569d4a4..75200d755d 100644 --- a/x/distribution/keeper/keeper_test.go +++ b/x/distribution/keeper/keeper_test.go @@ -1 +1,3 @@ package keeper + +// XXX TODO diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go new file mode 100644 index 0000000000..55914b59ff --- /dev/null +++ b/x/distribution/types/delegator_info.go @@ -0,0 +1,30 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// distribution info for a delegation +type DelegatorDistInfo struct { + DelegatorAddr sdk.AccAddress + ValOperatorAddr sdk.ValAddress + WithdrawalHeight int64 // last time this delegation withdrew rewards +} + +// withdraw rewards from delegator +func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, + height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) ( + di DelegatorDistInfo, g Global, withdrawn DecCoins) { + + vi.UpdateTotalDelAccum(height, totalDelShares) + g = vi.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) + + blocks = height - di.WithdrawalHeight + di.WithdrawalHeight = height + accum = delegatorShares * blocks + + withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum + vi.TotalDelAccum -= accum + + vi.Pool -= withdrawalTokens + vi.TotalDelAccum -= accum + return di, g, withdrawalTokens +} diff --git a/x/distribution/types/global.go b/x/distribution/types/global.go new file mode 100644 index 0000000000..b3b3e2d60f --- /dev/null +++ b/x/distribution/types/global.go @@ -0,0 +1,30 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// coins with decimal +type DecCoins []DecCoin + +// Coins which can have additional decimal points +type DecCoin struct { + Amount sdk.Dec + Denom string +} + +//___________________________________________________________________________________________ + +// Global state for distribution +type Global 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 + CommunityPool DecCoins // pool for community funds yet to be spent +} + +// update total validator accumulation factor +func (g Global) UpdateTotalValAccum(height int64, totalbondedtokens dec) Global { + blocks := height - g.totalvalaccumupdateheight + g.totalvalaccum += totaldelshares * blocks + g.totalvalaccumupdateheight = height + return g +} diff --git a/x/distribution/types/types.go b/x/distribution/types/types.go deleted file mode 100644 index 5a4ca9e2c8..0000000000 --- a/x/distribution/types/types.go +++ /dev/null @@ -1,35 +0,0 @@ -package types - -import sdk "github.com/cosmos/cosmos-sdk/types" - -// coins with decimal -type DecCoins []DecCoin - -// Coins which can have additional decimal points -type DecCoin struct { - Amount sdk.Dec - Denom string -} - -// Global state for distribution -type Global 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 - CommunityPool DecCoins // pool for community funds yet to be spent -} - -// distribution info for a particular validator -type ValidatorDistInfo struct { - GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool - Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward) - PoolCommission DecCoins // commission collected by this validator (pending withdrawal) - - TotalDelAccumUpdateHeight int64 // last height which the total delegator accum was updated - TotalDelAccum sdk.Dec // total proposer pool accumulation factor held by delegators -} - -// distribution info for a delegation -type DelegatorDistInfo struct { - WithdrawalHeight int64 // last time this delegation withdrew rewards -} diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go new file mode 100644 index 0000000000..8ca532d86f --- /dev/null +++ b/x/distribution/types/validator_info.go @@ -0,0 +1,57 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// distribution info for a particular validator +type ValidatorDistInfo struct { + OperatorAddr sdk.ValAddress + + GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool + Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward) + PoolCommission DecCoins // commission collected by this validator (pending withdrawal) + + TotalDelAccumUpdateHeight int64 // last height which the total delegator accum was updated + TotalDelAccum sdk.Dec // total proposer pool accumulation factor held by delegators +} + +// update total delegator accumululation +func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec) ValidatorDistInfo { + blocks = height - vi.TotalDelAccumUpdateHeight + vi.TotalDelAccum += totalDelShares * blocks + vi.TotalDelAccumUpdateHeight = height + return vi +} + +// move any available accumulated fees in the Global to the validator's pool +func (vi ValidatorDistInfo) TakeGlobalRewards(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) ( + vi ValidatorDistInfo, g Global) { + + g.UpdateTotalValAccum(height, totalBondedShares) + + // update the validators pool + blocks = height - vi.GlobalWithdrawalHeight + vi.GlobalWithdrawalHeight = height + accum = blocks * vdTokens + withdrawalTokens := g.Pool * accum / g.TotalValAccum + commission := withdrawalTokens * commissionRate + + g.TotalValAccum -= accumm + g.Pool -= withdrawalTokens + vi.PoolCommission += commission + vi.PoolCommissionFree += withdrawalTokens - commission + + return vi, g +} + +// withdraw commission rewards +func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64, + totalBonded, vdTokens, commissionRate Dec) ( + vi ValidatorDistInfo, g Global, withdrawn DecCoins) { + + g = vi.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) + + withdrawalTokens := vi.PoolCommission + vi.PoolCommission = 0 + + return vi, g, withdrawalTokens +} From 4ddf6ca08209c241e64535af0637ac95096b17b7 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 4 Sep 2018 17:17:13 -0400 Subject: [PATCH 03/99] undo spec move for PR clarity --- .../WIP-lamborghini-distribution/README.md | 0 .../WIP-lamborghini-distribution/end_block.md | 0 .../example_sheet/distribution.xlsx | Bin .../future_improvements.md | 0 .../WIP-lamborghini-distribution/overview.md | 0 .../WIP-lamborghini-distribution/state.md | 0 .../WIP-lamborghini-distribution/transactions.md | 0 .../WIP-lamborghini-distribution/triggers.md | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename docs/{_attic => spec/distribution}/WIP-lamborghini-distribution/README.md (100%) rename docs/{_attic => spec/distribution}/WIP-lamborghini-distribution/end_block.md (100%) rename docs/{_attic => spec/distribution}/WIP-lamborghini-distribution/example_sheet/distribution.xlsx (100%) rename docs/{_attic => spec/distribution}/WIP-lamborghini-distribution/future_improvements.md (100%) rename docs/{_attic => spec/distribution}/WIP-lamborghini-distribution/overview.md (100%) rename docs/{_attic => spec/distribution}/WIP-lamborghini-distribution/state.md (100%) rename docs/{_attic => spec/distribution}/WIP-lamborghini-distribution/transactions.md (100%) rename docs/{_attic => spec/distribution}/WIP-lamborghini-distribution/triggers.md (100%) diff --git a/docs/_attic/WIP-lamborghini-distribution/README.md b/docs/spec/distribution/WIP-lamborghini-distribution/README.md similarity index 100% rename from docs/_attic/WIP-lamborghini-distribution/README.md rename to docs/spec/distribution/WIP-lamborghini-distribution/README.md diff --git a/docs/_attic/WIP-lamborghini-distribution/end_block.md b/docs/spec/distribution/WIP-lamborghini-distribution/end_block.md similarity index 100% rename from docs/_attic/WIP-lamborghini-distribution/end_block.md rename to docs/spec/distribution/WIP-lamborghini-distribution/end_block.md diff --git a/docs/_attic/WIP-lamborghini-distribution/example_sheet/distribution.xlsx b/docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx similarity index 100% rename from docs/_attic/WIP-lamborghini-distribution/example_sheet/distribution.xlsx rename to docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx diff --git a/docs/_attic/WIP-lamborghini-distribution/future_improvements.md b/docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md similarity index 100% rename from docs/_attic/WIP-lamborghini-distribution/future_improvements.md rename to docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md diff --git a/docs/_attic/WIP-lamborghini-distribution/overview.md b/docs/spec/distribution/WIP-lamborghini-distribution/overview.md similarity index 100% rename from docs/_attic/WIP-lamborghini-distribution/overview.md rename to docs/spec/distribution/WIP-lamborghini-distribution/overview.md diff --git a/docs/_attic/WIP-lamborghini-distribution/state.md b/docs/spec/distribution/WIP-lamborghini-distribution/state.md similarity index 100% rename from docs/_attic/WIP-lamborghini-distribution/state.md rename to docs/spec/distribution/WIP-lamborghini-distribution/state.md diff --git a/docs/_attic/WIP-lamborghini-distribution/transactions.md b/docs/spec/distribution/WIP-lamborghini-distribution/transactions.md similarity index 100% rename from docs/_attic/WIP-lamborghini-distribution/transactions.md rename to docs/spec/distribution/WIP-lamborghini-distribution/transactions.md diff --git a/docs/_attic/WIP-lamborghini-distribution/triggers.md b/docs/spec/distribution/WIP-lamborghini-distribution/triggers.md similarity index 100% rename from docs/_attic/WIP-lamborghini-distribution/triggers.md rename to docs/spec/distribution/WIP-lamborghini-distribution/triggers.md From 43ab06678fe20e48a20d3fc7a34887e7c91f281b Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 4 Sep 2018 17:21:38 -0400 Subject: [PATCH 04/99] move WIP-lamborghini-distribution --- .../WIP-lamborghini-distribution/README.md | 0 .../WIP-lamborghini-distribution/end_block.md | 0 .../example_sheet/distribution.xlsx | Bin .../future_improvements.md | 0 .../WIP-lamborghini-distribution/overview.md | 0 .../WIP-lamborghini-distribution/state.md | 0 .../WIP-lamborghini-distribution/transactions.md | 0 .../WIP-lamborghini-distribution/triggers.md | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/README.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/end_block.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/example_sheet/distribution.xlsx (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/future_improvements.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/overview.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/state.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/transactions.md (100%) rename docs/{spec/distribution => _attic}/WIP-lamborghini-distribution/triggers.md (100%) diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/README.md b/docs/_attic/WIP-lamborghini-distribution/README.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/README.md rename to docs/_attic/WIP-lamborghini-distribution/README.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/end_block.md b/docs/_attic/WIP-lamborghini-distribution/end_block.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/end_block.md rename to docs/_attic/WIP-lamborghini-distribution/end_block.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx b/docs/_attic/WIP-lamborghini-distribution/example_sheet/distribution.xlsx similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/example_sheet/distribution.xlsx rename to docs/_attic/WIP-lamborghini-distribution/example_sheet/distribution.xlsx diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md b/docs/_attic/WIP-lamborghini-distribution/future_improvements.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/future_improvements.md rename to docs/_attic/WIP-lamborghini-distribution/future_improvements.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/overview.md b/docs/_attic/WIP-lamborghini-distribution/overview.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/overview.md rename to docs/_attic/WIP-lamborghini-distribution/overview.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/state.md b/docs/_attic/WIP-lamborghini-distribution/state.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/state.md rename to docs/_attic/WIP-lamborghini-distribution/state.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/transactions.md b/docs/_attic/WIP-lamborghini-distribution/transactions.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/transactions.md rename to docs/_attic/WIP-lamborghini-distribution/transactions.md diff --git a/docs/spec/distribution/WIP-lamborghini-distribution/triggers.md b/docs/_attic/WIP-lamborghini-distribution/triggers.md similarity index 100% rename from docs/spec/distribution/WIP-lamborghini-distribution/triggers.md rename to docs/_attic/WIP-lamborghini-distribution/triggers.md From 53253aa32fe3c47d7371de0645fcb753c1f64cb0 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 5 Sep 2018 02:41:17 -0400 Subject: [PATCH 05/99] working --- x/distribution/client/cli/tx.go | 76 +++++++++++++ x/distribution/handler.go | 142 ++----------------------- x/distribution/keeper/allocation.go | 27 +++++ x/distribution/keeper/delegation.go | 84 +++++++++++++++ x/distribution/keeper/keeper.go | 72 ++----------- x/distribution/keeper/keeper_test.go | 3 - x/distribution/keeper/validator.go | 48 +++++++++ x/distribution/types/fee_pool.go | 41 +++++++ x/distribution/types/global.go | 30 ------ x/distribution/types/keepers.go | 17 +++ x/distribution/types/validator_info.go | 7 +- x/stake/keeper/delegation.go | 18 ++++ 12 files changed, 330 insertions(+), 235 deletions(-) create mode 100644 x/distribution/client/cli/tx.go create mode 100644 x/distribution/keeper/allocation.go create mode 100644 x/distribution/keeper/delegation.go delete mode 100644 x/distribution/keeper/keeper_test.go create mode 100644 x/distribution/keeper/validator.go create mode 100644 x/distribution/types/fee_pool.go delete mode 100644 x/distribution/types/global.go create mode 100644 x/distribution/types/keepers.go diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go new file mode 100644 index 0000000000..771572074d --- /dev/null +++ b/x/distribution/client/cli/tx.go @@ -0,0 +1,76 @@ +// nolint +package cli + +import ( + "os" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/stake" + "github.com/spf13/cobra" + "github.com/spf13/viper" + wire "github.com/tendermint/go-wire" +) + +type TxWithdrawDelegationRewardsAll struct { + delegatorAddr sdk.AccAddress + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +type TxWithdrawDelegationReward struct { + delegatorAddr sdk.AccAddress + validatorAddr sdk.AccAddress + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +type TxWithdrawValidatorRewardsAll struct { + operatorAddr sdk.AccAddress // validator address to withdraw from + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +var ( + flagOnlyFromValidator = "only-from-validator" + flagIsValidator = "is-validator" +) + +// GetCmdDelegate implements the delegate command. +func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "withdraw-rewards [delegator]", + Short: "withdraw rewards from delegation accounts", + RunE: func(cmd *cobra.Command, args []string) error { + txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + cliCtx := context.NewCLIContext(). + WithCodec(cdc). + WithLogger(os.Stdout). + WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) + + amount, err := sdk.ParseCoin(viper.GetString(FlagAmount)) + if err != nil { + return err + } + + delAddr, err := cliCtx.GetFromAddress() + if err != nil { + return err + } + + valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator)) + if err != nil { + return err + } + + msg := stake.NewMsgDelegate(delAddr, valAddr, amount) + + // build and sign the transaction, then broadcast to Tendermint + return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + }, + } + + // TODO add flags for "is-validator", "only-for-validator" + cmd.Flags().String(flagOnlyFromValidator, "", "Only withdraw from this validator address") + cmd.Flags().Bool(flagIsValidator, false, "Also withdraw validator's commission") + + return cmd +} diff --git a/x/distribution/handler.go b/x/distribution/handler.go index bd317b9c14..39371610f4 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -1,144 +1,14 @@ package stake import ( - "time" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/stake/keeper" ) +// distribution fee handler +func DistributionFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) { + +} + +////////////////////////////////////////////////////////////////////////////////// // burn burn burn func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} - -// Called every block, process inflation, update validator set -func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Validator) { - pool := k.GetPool(ctx) - - // Process provision inflation - blockTime := ctx.BlockHeader().Time - if blockTime.Sub(pool.InflationLastTime) >= time.Hour { - params := k.GetParams(ctx) - pool.InflationLastTime = blockTime - pool = pool.ProcessProvisions(params) - k.SetPool(ctx, pool) - } - - // reset the intra-transaction counter - k.SetIntraTxCounter(ctx, 0) - - // calculate validator set changes - ValidatorUpdates = k.GetTendermintUpdates(ctx) - k.ClearTendermintUpdates(ctx) - return -} - -/* -func AllocateFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution, - sumPowerPrecommitValidators, totalBondedTokens, communityTax, - proposerCommissionRate sdk.Dec) - - feesCollectedDec = MakeDecCoins(feesCollected) - proposerReward = feesCollectedDec * (0.01 + 0.04 - * sumPowerPrecommitValidators / totalBondedTokens) - - commission = proposerReward * proposerCommissionRate - proposer.PoolCommission += commission - proposer.Pool += proposerReward - commission - - communityFunding = feesCollectedDec * communityTax - global.CommunityFund += communityFunding - - poolReceived = feesCollectedDec - proposerReward - communityFunding - global.Pool += poolReceived - global.EverReceivedPool += poolReceived - global.LastReceivedPool = poolReceived - - SetValidatorDistribution(proposer) - SetGlobal(global) - -///////////////////////////////////////////////////////////////////////////////////////////////////////// - -type TxWithdrawDelegationRewardsAll struct { - delegatorAddr sdk.AccAddress - withdrawAddr sdk.AccAddress // address to make the withdrawal to -} - -func WithdrawDelegationRewardsAll(delegatorAddr, withdrawAddr sdk.AccAddress) - height = GetHeight() - withdraw = GetDelegatorRewardsAll(delegatorAddr, height) - AddCoins(withdrawAddr, withdraw.TruncateDecimal()) - -func GetDelegatorRewardsAll(delegatorAddr sdk.AccAddress, height int64) DecCoins - - // get all distribution scenarios - delegations = GetDelegations(delegatorAddr) - - // collect all entitled rewards - withdraw = 0 - pool = stake.GetPool() - global = GetGlobal() - 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, - validator.Tokens, validator.DelegatorShares, validator.Commission) - withdraw += diWithdraw - - SetGlobal(global) - return withdraw - -///////////////////////////////////////////////////////////////////////////////////////////////////////// - -type TxWithdrawDelegationReward struct { - delegatorAddr sdk.AccAddress - validatorAddr sdk.AccAddress - withdrawAddr sdk.AccAddress // address to make the withdrawal to -} - -func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress) - height = GetHeight() - - // get all distribution scenarios - pool = stake.GetPool() - global = GetGlobal() - delInfo = GetDelegationDistInfo(delegatorAddr, - validatorAddr) - valInfo = GetValidatorDistInfo(validatorAddr) - validator = GetValidator(validatorAddr) - - global, withdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens, - validator.Tokens, validator.DelegatorShares, validator.Commission) - - SetGlobal(global) - AddCoins(withdrawAddr, withdraw.TruncateDecimal()) - -///////////////////////////////////////////////////////////////////////////////////////////////////////// - -type TxWithdrawValidatorRewardsAll struct { - operatorAddr sdk.AccAddress // validator address to withdraw from - withdrawAddr sdk.AccAddress // address to make the withdrawal to -} - -func WithdrawValidatorRewardsAll(operatorAddr, withdrawAddr sdk.AccAddress) - - height = GetHeight() - global = GetGlobal() - pool = GetPool() - ValInfo = GetValidatorDistInfo(delegation.ValidatorAddr) - validator = GetValidator(delegation.ValidatorAddr) - - // withdraw self-delegation - withdraw = GetDelegatorRewardsAll(validator.OperatorAddr, height) - - // withdrawal validator commission rewards - global, commission = valInfo.WithdrawCommission(global, valInfo, height, pool.BondedTokens, - validator.Tokens, validator.Commission) - withdraw += commission - SetGlobal(global) - - AddCoins(withdrawAddr, withdraw.TruncateDecimal()) - -*/ diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go new file mode 100644 index 0000000000..ce111b559c --- /dev/null +++ b/x/distribution/keeper/allocation.go @@ -0,0 +1,27 @@ +package keeper + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// XXX TODO +func AllocateFees(feesCollected sdk.Coins, feePool FeePool, proposer ValidatorDistribution, + sumPowerPrecommitValidators, totalBondedTokens, communityTax, + proposerCommissionRate sdk.Dec) { + + feesCollectedDec = MakeDecCoins(feesCollected) + proposerReward = feesCollectedDec * (0.01 + 0.04*sumPowerPrecommitValidators/totalBondedTokens) + + commission = proposerReward * proposerCommissionRate + proposer.PoolCommission += commission + proposer.Pool += proposerReward - commission + + communityFunding = feesCollectedDec * communityTax + feePool.CommunityFund += communityFunding + + poolReceived = feesCollectedDec - proposerReward - communityFunding + feePool.Pool += poolReceived + feePool.EverReceivedPool += poolReceived + feePool.LastReceivedPool = poolReceived + + SetValidatorDistribution(proposer) + SetFeePool(feePool) +} diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go new file mode 100644 index 0000000000..72e96715b3 --- /dev/null +++ b/x/distribution/keeper/delegation.go @@ -0,0 +1,84 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/stake" +) + +// get the delegator distribution info +func (k Keeper) GetDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, + valOperatorAddr sdk.ValAddress) (ddi types.DelegatorDistInfo) { + + 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) SetDelegatorDistInfo(ctx sdk.Context, ddi types.DelegatorDistInfo) { + store := ctx.KVStore(k.storeKey) + b := k.cdc.MustMarshalBinary(ddi) + store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b) +} + +//___________________________________________________________________________________________ + +// XXX TODO +func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress) { + height = ctx.BlockHeight() + + // get all distribution scenarios + pool = stake.GetPool() + feePool = GetFeePool() + delInfo = GetDelegationDistInfo(delegatorAddr, + validatorAddr) + valInfo = GetValidatorDistInfo(validatorAddr) + validator = GetValidator(validatorAddr) + + feePool, withdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, + validator.Tokens, validator.DelegatorShares, validator.Commission) + + SetFeePool(feePool) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) +} + +/////////////////////////////////////////////////////////////////////////////////////// + +// XXX TODO +func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr, withdrawAddr sdk.AccAddress) { + height = ctx.BlockHeight() + withdraw = GetDelegatorRewardsAll(delegatorAddr, height) + k.coinsKeeper.AddCoins(withdrawAddr, withdraw.Amount.TruncateDecimal()) +} + +// XXX TODO +func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) DecCoins { + + // collect all entitled rewards + withdraw = 0 + pool = stake.GetPool() + feePool = GetFeePool() + + // iterate over all the delegations + operationAtDelegation := func(_ int64, del types.Delegation) (stop bool) { + delInfo = GetDelegationDistInfo(delAddr, del.ValidatorAddr) + valInfo = GetValidatorDistInfo(del.ValidatorAddr) + validator = GetValidator(del.ValidatorAddr) + + feePool, diWithdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, + validator.Tokens, validator.DelegatorShares, validator.Commission) + withdraw += diWithdraw + return false + } + k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation) + + SetFeePool(feePool) + return withdraw +} diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index a5d6459ac5..c0bf48cea5 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -2,9 +2,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/distribution/types" - "github.com/cosmos/cosmos-sdk/x/stake" wire "github.com/tendermint/go-wire" ) @@ -12,15 +10,15 @@ import ( type Keeper struct { storeKey sdk.StoreKey cdc *wire.Codec - coinKeeper bank.Keeper - stakeKeeper stake.Keeper + coinKeeper types.CoinKeeper + stakeKeeper types.StakeKeeper // codespace codespace sdk.CodespaceType } -func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, - sk stake.Keeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck types.CoinKeeper, + sk types.StakeKeeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ storeKey: key, @@ -33,70 +31,22 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, //______________________________________________________________________ -// get the global distribution info -func (k Keeper) GetGlobal(ctx sdk.Context) (global types.Global) { +// get the global fee pool distribution info +func (k Keeper) GetFeePool(ctx sdk.Context) (feePool types.Global) { store := ctx.KVStore(k.storeKey) b := store.Get(GlobalKey) if b == nil { - panic("Stored global should not have been nil") + panic("Stored fee pool should not have been nil") } - k.cdc.MustUnmarshalBinary(b, &global) + k.cdc.MustUnmarshalBinary(b, &feePool) return } -// set the global distribution info -func (k Keeper) SetGlobal(ctx sdk.Context, global types.Global) { +// set the global fee pool distribution info +func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.Global) { store := ctx.KVStore(k.storeKey) - b := k.cdc.MustMarshalBinary(global) + b := k.cdc.MustMarshalBinary(feePool) store.Set(GlobalKey, b) } - -//______________________________________________________________________ - -// get the delegator distribution info -func (k Keeper) GetDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, - valOperatorAddr sdk.ValAddress) (ddi types.DelegatorDistInfo) { - - 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) SetDelegatorDistInfo(ctx sdk.Context, ddi types.DelegatorDistInfo) { - store := ctx.KVStore(k.storeKey) - b := k.cdc.MustMarshalBinary(ddi) - store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b) -} - -//______________________________________________________________________ - -// 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 delegation-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) -} diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go deleted file mode 100644 index 75200d755d..0000000000 --- a/x/distribution/keeper/keeper_test.go +++ /dev/null @@ -1,3 +0,0 @@ -package keeper - -// XXX TODO diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go new file mode 100644 index 0000000000..9a057b85b9 --- /dev/null +++ b/x/distribution/keeper/validator.go @@ -0,0 +1,48 @@ +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 delegation-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) +} + +// XXX TODO +func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr, withdrawAddr sdk.AccAddress) { + height = ctx.BlockHeight() + feePool = k.GetFeePool(ctx) + pool = k.stakeKeeper.GetPool(ctx) + ValInfo = k.GetValidatorDistInfo(delegation.ValidatorAddr) + validator = k.GetValidator(delegation.ValidatorAddr) + + // withdraw self-delegation + withdraw = k.GetDelegatorRewardsAll(validator.OperatorAddr, height) + + // withdrawal validator commission rewards + feePool, commission = valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens, + validator.Tokens, validator.Commission) + withdraw += commission + SetFeePool(feePool) + + k.coinKeeper.AddCoins(withdrawAddr, withdraw.TruncateDecimal()) +} diff --git a/x/distribution/types/fee_pool.go b/x/distribution/types/fee_pool.go new file mode 100644 index 0000000000..23e1584884 --- /dev/null +++ b/x/distribution/types/fee_pool.go @@ -0,0 +1,41 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// coins with decimal +type DecCoins []DecCoin + +// Coins which can have additional decimal points +type DecCoin struct { + Amount sdk.Dec `json:"amount"` + Denom string `json:"denom"` +} + +// total accumulation tracker +type TotalAccum struct { + UpdateHeight int64 `json:"update_height"` + Accum sdk.Dec `json:"accum"` +} + +// update total validator accumulation factor +func (ta TotalAccum) Update(height int64, accumCreatedPerBlock sdk.Dec) TotalAccum { + blocks := height - ta.UpdateHeight + f.Accum += accumCreatedPerBlock.Mul(sdk.NewDec(blocks)) + ta.UpdateHeight = height + return ta +} + +//___________________________________________________________________________________________ + +// global fee pool for distribution +type FeePool struct { + ValAccum TotalAccum `json:"val_accum"` // total valdator accum held by validators + Pool DecCoins `json:"pool"` // funds for all validators which have yet to be withdrawn + CommunityPool DecCoins `json:"community_pool"` // pool for community funds yet to be spent} +} + +// update total validator accumulation factor +func (f FeePool) UpdateTotalValAccum(height int64, totalBondedTokens Dec) FeePool { + f.ValAccum = f.ValAccum.Update(height, totalBondedTokens) + return f +} diff --git a/x/distribution/types/global.go b/x/distribution/types/global.go deleted file mode 100644 index b3b3e2d60f..0000000000 --- a/x/distribution/types/global.go +++ /dev/null @@ -1,30 +0,0 @@ -package types - -import sdk "github.com/cosmos/cosmos-sdk/types" - -// coins with decimal -type DecCoins []DecCoin - -// Coins which can have additional decimal points -type DecCoin struct { - Amount sdk.Dec - Denom string -} - -//___________________________________________________________________________________________ - -// Global state for distribution -type Global 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 - CommunityPool DecCoins // pool for community funds yet to be spent -} - -// update total validator accumulation factor -func (g Global) UpdateTotalValAccum(height int64, totalbondedtokens dec) Global { - blocks := height - g.totalvalaccumupdateheight - g.totalvalaccum += totaldelshares * blocks - g.totalvalaccumupdateheight = height - return g -} diff --git a/x/distribution/types/keepers.go b/x/distribution/types/keepers.go new file mode 100644 index 0000000000..15a1377185 --- /dev/null +++ b/x/distribution/types/keepers.go @@ -0,0 +1,17 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// expected stake keeper +type StakeKeeper interface { + IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, + fn func(index int64, del types.Delegation) (stop bool)) + GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress) + GetValidator(ctx sdk.Context, valAddr sdk.AccAddress) + GetPool(ctx sdk.Context) +} + +// expected coin keeper +type CoinKeeper interface { + AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) +} diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 8ca532d86f..4a1b1f86d0 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -10,15 +10,12 @@ type ValidatorDistInfo struct { Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward) PoolCommission DecCoins // commission collected by this validator (pending withdrawal) - TotalDelAccumUpdateHeight int64 // last height which the total delegator accum was updated - TotalDelAccum sdk.Dec // total proposer pool accumulation factor held by delegators + DelAccum TotalAccum `json:"dek_accum"` // total proposer pool accumulation factor held by delegators } // update total delegator accumululation func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec) ValidatorDistInfo { - blocks = height - vi.TotalDelAccumUpdateHeight - vi.TotalDelAccum += totalDelShares * blocks - vi.TotalDelAccumUpdateHeight = height + vi.DelAccum = vi.DelAccum.Update(height, totalDelShares) return vi } diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 9a596ffbce..e4ec199efd 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -64,6 +64,24 @@ func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.AccAddress, return delegations[:i] // trim } +// iterate through all of the delegations from a delegator +func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, + fn func(index int64, del types.Delegation) (stop bool)) { + + store := ctx.KVStore(k.storeKey) + delegatorPrefixKey := GetDelegationsKey(delAddr) + iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest + for i := int64(0); iterator.Valid(); iterator.Next() { + del := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) + stop := fn(i, del) + if stop { + break + } + i++ + } + iterator.Close() +} + // set the delegation func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { store := ctx.KVStore(k.storeKey) From aebd36fef8fbbfdc0693931fdae509d0c1c9e751 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 5 Sep 2018 18:29:20 -0400 Subject: [PATCH 06/99] ... --- x/distribution/handler.go | 1 + x/distribution/keeper/allocation.go | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/x/distribution/handler.go b/x/distribution/handler.go index 39371610f4..02fb1c3ed6 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -7,6 +7,7 @@ import ( // distribution fee handler func DistributionFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) { + k. } ////////////////////////////////////////////////////////////////////////////////// diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index ce111b559c..43a99dfdb6 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -3,10 +3,14 @@ package keeper import sdk "github.com/cosmos/cosmos-sdk/types" // XXX TODO -func AllocateFees(feesCollected sdk.Coins, feePool FeePool, proposer ValidatorDistribution, +func (k Keeper) AllocateFees(ctx sdk.Context, feesCollected sdk.Coins, proposerAddr ValidatorDistribution, sumPowerPrecommitValidators, totalBondedTokens, communityTax, proposerCommissionRate sdk.Dec) { + feePool := k.GetFeePool() + proposerOpAddr := Stake.Get + proposer := GetFeeDistribution() + feesCollectedDec = MakeDecCoins(feesCollected) proposerReward = feesCollectedDec * (0.01 + 0.04*sumPowerPrecommitValidators/totalBondedTokens) From e2b5b9b73b1287119a6f66895a2936b38fe0802e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 5 Sep 2018 18:46:09 -0400 Subject: [PATCH 07/99] ... --- x/distribution/keeper/allocation.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 43a99dfdb6..597be2adb7 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -3,16 +3,16 @@ package keeper import sdk "github.com/cosmos/cosmos-sdk/types" // XXX TODO -func (k Keeper) AllocateFees(ctx sdk.Context, feesCollected sdk.Coins, proposerAddr ValidatorDistribution, - sumPowerPrecommitValidators, totalBondedTokens, communityTax, - proposerCommissionRate sdk.Dec) { +func (k Keeper) AllocateFees(ctx sdk.Context, feesCollected sdk.Coins, proposerAddr sdk.ConsAddrs, + sumPowerPrecommitValidators, totalBondedTokens, communityTax, proposerCommissionRate sdk.Dec) { feePool := k.GetFeePool() - proposerOpAddr := Stake.Get - proposer := GetFeeDistribution() + validator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, + proposerOpAddr := Stake.GetValidator + proposer := k.GetFeeDistribution(ctx, proposerOpAddr) feesCollectedDec = MakeDecCoins(feesCollected) - proposerReward = feesCollectedDec * (0.01 + 0.04*sumPowerPrecommitValidators/totalBondedTokens) + proposerReward = feesCollectedDec.Mul(sdk.NewDecWithPrec(1, 2) + sdk.NewDecWithPrec(1, 2).Mul(sumPowerPrecommitValidators)/totalBondedTokens) commission = proposerReward * proposerCommissionRate proposer.PoolCommission += commission From b40909906d7176101a97e05ade8fdff416f8cd47 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 5 Sep 2018 19:15:15 -0400 Subject: [PATCH 08/99] update spec --- docs/spec/distribution/end_block.md | 12 +++----- docs/spec/distribution/overview.md | 2 +- docs/spec/distribution/state.md | 10 +++--- docs/spec/distribution/transactions.md | 42 +++++++++++++------------- x/distribution/keeper/allocation.go | 27 ++++++++--------- x/distribution/keeper/keeper.go | 4 +-- x/distribution/types/dec_coin.go | 27 +++++++++++++++++ x/distribution/types/fee_pool.go | 9 ------ 8 files changed, 74 insertions(+), 59 deletions(-) create mode 100644 x/distribution/types/dec_coin.go diff --git a/docs/spec/distribution/end_block.md b/docs/spec/distribution/end_block.md index 952d1832ac..2b74cd3e90 100644 --- a/docs/spec/distribution/end_block.md +++ b/docs/spec/distribution/end_block.md @@ -1,7 +1,7 @@ # End Block At each endblock, the fees received are allocated to the proposer, community fund, -and global pool. When the validator is the proposer of the round, that +and pool. When the validator is the proposer of the round, that validator (and their delegators) receives between 1% and 5% of fee rewards, the reserve community tax is then charged, then the remainder is distributed proportionally by voting power to all bonded validators independent of whether @@ -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) ``` diff --git a/docs/spec/distribution/overview.md b/docs/spec/distribution/overview.md index 13a4ea3f14..28b1bbeddf 100644 --- a/docs/spec/distribution/overview.md +++ b/docs/spec/distribution/overview.md @@ -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 diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index 3e3669789a..e5c0d47d02 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -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 + FewPoolWithdrawalHeight 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) diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 8616206207..47b11165a0 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -26,18 +26,18 @@ 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 ``` @@ -58,16 +58,16 @@ 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()) ``` @@ -90,7 +90,7 @@ type TxWithdrawValidatorRewardsAll struct { func WithdrawValidatorRewardsAll(operatorAddr, withdrawAddr sdk.AccAddress) height = GetHeight() - global = GetGlobal() + feePool = GetFeePool() pool = GetPool() ValInfo = GetValidatorDistInfo(delegation.ValidatorAddr) validator = GetValidator(delegation.ValidatorAddr) @@ -99,10 +99,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 +117,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 +140,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 +148,14 @@ from the passive global pool to their own pool. It is at this point that the commission is withdrawn ``` -func (vi ValidatorDistInfo) TakeGlobalRewards(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 +175,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 DelegatorDistInfo) WithdrawRewards(g FeePool, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) ( - di DelegatorDistInfo, g Global, withdrawn DecCoins) + di DelegatorDistInfo, g FeePool, withdrawn DecCoins) vi.UpdateTotalDelAccum(height, totalDelShares) - g = vi.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) + g = vi.TakeFeePoolRewards(g, height, totalBonded, vdTokens, commissionRate) blocks = height - di.WithdrawalHeight di.WithdrawalHeight = height @@ -200,11 +200,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.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) + g = vi.TakeFeePoolRewards(g, height, totalBonded, vdTokens, commissionRate) withdrawalTokens := vi.PoolCommission vi.PoolCommission = 0 diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 597be2adb7..9f54b700e5 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -3,28 +3,27 @@ package keeper import sdk "github.com/cosmos/cosmos-sdk/types" // XXX TODO -func (k Keeper) AllocateFees(ctx sdk.Context, feesCollected sdk.Coins, proposerAddr sdk.ConsAddrs, +func (k Keeper) AllocateFees(ctx sdk.Context, feesCollected sdk.Coins, proposerAddr sdk.ConsAddress, sumPowerPrecommitValidators, totalBondedTokens, communityTax, proposerCommissionRate sdk.Dec) { feePool := k.GetFeePool() - validator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, - proposerOpAddr := Stake.GetValidator - proposer := k.GetFeeDistribution(ctx, proposerOpAddr) + proserValidator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, proposerAddr) + proposer := k.GetFeeDistribution(ctx, proserValidator.OperatorAddr) - feesCollectedDec = MakeDecCoins(feesCollected) - proposerReward = feesCollectedDec.Mul(sdk.NewDecWithPrec(1, 2) + sdk.NewDecWithPrec(1, 2).Mul(sumPowerPrecommitValidators)/totalBondedTokens) + feesCollectedDec := NewDecCoins(feesCollected) + proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( + sumPowerPrecommitValidators).Div(totalBondedTokens)) + proposerReward := feesCollectedDec.Mul(proposerMultiplier) - commission = proposerReward * proposerCommissionRate - proposer.PoolCommission += commission - proposer.Pool += proposerReward - commission + commission := proposerReward.Mul(proposerCommissionRate) + proposer.PoolCommission = proposer.PoolCommission.Add(commission) + proposer.Pool = proposer.Pool.Add(proposerReward.Sub(commission)) - communityFunding = feesCollectedDec * communityTax - feePool.CommunityFund += communityFunding + communityFunding := feesCollectedDec.Mul(communityTax) + feePool.CommunityFund = feePool.CommunityFund.Add(communityFunding) poolReceived = feesCollectedDec - proposerReward - communityFunding - feePool.Pool += poolReceived - feePool.EverReceivedPool += poolReceived - feePool.LastReceivedPool = poolReceived + feePool.Pool = feePool.Pool.Add(poolReceived) SetValidatorDistribution(proposer) SetFeePool(feePool) diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index c0bf48cea5..741e3aa9aa 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -32,7 +32,7 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck types.CoinKeeper, //______________________________________________________________________ // get the global fee pool distribution info -func (k Keeper) GetFeePool(ctx sdk.Context) (feePool types.Global) { +func (k Keeper) GetFeePool(ctx sdk.Context) (feePool types.FeePool) { store := ctx.KVStore(k.storeKey) b := store.Get(GlobalKey) @@ -45,7 +45,7 @@ func (k Keeper) GetFeePool(ctx sdk.Context) (feePool types.Global) { } // set the global fee pool distribution info -func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.Global) { +func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.FeePool) { store := ctx.KVStore(k.storeKey) b := k.cdc.MustMarshalBinary(feePool) store.Set(GlobalKey, b) diff --git a/x/distribution/types/dec_coin.go b/x/distribution/types/dec_coin.go new file mode 100644 index 0000000000..1bc803530a --- /dev/null +++ b/x/distribution/types/dec_coin.go @@ -0,0 +1,27 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// coins with decimal +type DecCoins []DecCoin + +// Coins which can have additional decimal points +type DecCoin struct { + Amount sdk.Dec `json:"amount"` + Denom string `json:"denom"` +} + +func NewDecCoin(coin sdk.Coin) DecCoin { + return DecCoins{ + Amount: sdk.NewDec(coin.Amount), + Denom: coin.Denom, + } +} + +func NewDecCoins(coins sdk.Coins) DecCoins { + + dcs := make(DecCoins, len(coins)) + for i, coin := range coins { + dcs[i] = NewDecCoin(coin) + } +} diff --git a/x/distribution/types/fee_pool.go b/x/distribution/types/fee_pool.go index 23e1584884..1058db77c7 100644 --- a/x/distribution/types/fee_pool.go +++ b/x/distribution/types/fee_pool.go @@ -2,15 +2,6 @@ package types import sdk "github.com/cosmos/cosmos-sdk/types" -// coins with decimal -type DecCoins []DecCoin - -// Coins which can have additional decimal points -type DecCoin struct { - Amount sdk.Dec `json:"amount"` - Denom string `json:"denom"` -} - // total accumulation tracker type TotalAccum struct { UpdateHeight int64 `json:"update_height"` From cbb5a504d588d681bf14f326f5b0161a2dd788db Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 5 Sep 2018 19:28:18 -0400 Subject: [PATCH 09/99] work on allocate fees --- x/distribution/keeper/allocation.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 9f54b700e5..76cee338ba 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -2,29 +2,33 @@ package keeper import sdk "github.com/cosmos/cosmos-sdk/types" -// XXX TODO -func (k Keeper) AllocateFees(ctx sdk.Context, feesCollected sdk.Coins, proposerAddr sdk.ConsAddress, - sumPowerPrecommitValidators, totalBondedTokens, communityTax, proposerCommissionRate sdk.Dec) { +// Allocate fees handles distribution of the collected fees +func (k Keeper) AllocateFees(ctx sdk.Context, feesCollected sdk.Coins, proposerAddr sdk.ConsAddress) { + + sumPowerPrecommitValidators := sdk.NewDec(1) // XXX TODO actually calculate this + communityTax := sdk.NewDecWithPrec(1, 2) // XXX TODO get from global params store + + feePool := k.GetFeePool(ctx) + stakePool := k.stakeKeeper.GetPool(ctx) - feePool := k.GetFeePool() proserValidator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, proposerAddr) - proposer := k.GetFeeDistribution(ctx, proserValidator.OperatorAddr) + proposerDist := k.GetFeeDistribution(ctx, proserValidator.OperatorAddr) feesCollectedDec := NewDecCoins(feesCollected) proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( - sumPowerPrecommitValidators).Div(totalBondedTokens)) + sumPowerPrecommitValidators).Div(stakePool.BondedTokens)) proposerReward := feesCollectedDec.Mul(proposerMultiplier) - commission := proposerReward.Mul(proposerCommissionRate) - proposer.PoolCommission = proposer.PoolCommission.Add(commission) - proposer.Pool = proposer.Pool.Add(proposerReward.Sub(commission)) + commission := proposerReward.Mul(proserValidator.Commission) + proposerDist.PoolCommission = proposerDist.PoolCommission.Add(commission) + proposerDist.Pool = proposerDist.Pool.Add(proposerReward.Sub(commission)) communityFunding := feesCollectedDec.Mul(communityTax) feePool.CommunityFund = feePool.CommunityFund.Add(communityFunding) - poolReceived = feesCollectedDec - proposerReward - communityFunding + poolReceived := feesCollectedDec.Sub(proposerReward).Sub(communityFunding) feePool.Pool = feePool.Pool.Add(poolReceived) - SetValidatorDistribution(proposer) + SetValidatorDistribution(proposerDist) SetFeePool(feePool) } From e498d43d03569dc8dbd7cc19c0e95844c9b31988 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 10 Sep 2018 18:37:58 -0400 Subject: [PATCH 10/99] dec coins, refactoring distr --- types/decimal.go | 26 +++++++++++ types/decimal_test.go | 26 +++++++++++ x/distribution/client/cli/tx.go | 6 +-- x/distribution/handler.go | 1 - x/distribution/keeper/delegation.go | 47 +++++++++---------- x/distribution/keeper/validator.go | 21 +++++---- x/distribution/types/dec_coin.go | 72 +++++++++++++++++++++++++++-- 7 files changed, 156 insertions(+), 43 deletions(-) diff --git a/types/decimal.go b/types/decimal.go index 8e7db1340b..d6c93f617a 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -323,6 +323,32 @@ func (d Dec) RoundInt() Int { //___________________________________________________________________________________ +// similar to chopPrecisionAndRound, but always rounds down +func chopPrecisionAndTruncate(d *big.Int) *big.Int { + return d.Quo(d, precisionReuse) +} + +func chopPrecisionAndTruncateNonMutative(d *big.Int) *big.Int { + tmp := new(big.Int).Set(d) + return chopPrecisionAndTruncate(tmp) +} + +// RoundInt64 rounds the decimal using bankers rounding +func (d Dec) TruncateInt64() int64 { + chopped := chopPrecisionAndTruncateNonMutative(d.Int) + if !chopped.IsInt64() { + panic("Int64() out of bound") + } + return chopped.Int64() +} + +// RoundInt round the decimal using bankers rounding +func (d Dec) TruncateInt() Int { + return NewIntFromBigInt(chopPrecisionAndTruncateNonMutative(d.Int)) +} + +//___________________________________________________________________________________ + // reuse nil values var ( nilAmino string diff --git a/types/decimal_test.go b/types/decimal_test.go index 115eeacb01..b3e10b5101 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -202,6 +202,32 @@ func TestBankerRoundChop(t *testing.T) { } } +func TestTruncate(t *testing.T) { + tests := []struct { + d1 Dec + exp int64 + }{ + {mustNewDecFromStr(t, "0"), 0}, + {mustNewDecFromStr(t, "0.25"), 0}, + {mustNewDecFromStr(t, "0.75"), 0}, + {mustNewDecFromStr(t, "1"), 1}, + {mustNewDecFromStr(t, "1.5"), 1}, + {mustNewDecFromStr(t, "7.5"), 7}, + {mustNewDecFromStr(t, "7.6"), 7}, + {mustNewDecFromStr(t, "7.4"), 7}, + {mustNewDecFromStr(t, "100.1"), 100}, + {mustNewDecFromStr(t, "1000.1"), 1000}, + } + + for tcIndex, tc := range tests { + resNeg := tc.d1.Neg().TruncateInt64() + require.Equal(t, -1*tc.exp, resNeg, "negative tc %d", tcIndex) + + resPos := tc.d1.TruncateInt64() + require.Equal(t, tc.exp, resPos, "positive tc %d", tcIndex) + } +} + func TestToLeftPadded(t *testing.T) { tests := []struct { dec Dec diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 771572074d..b794d08cb4 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/utils" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/stake" + distr "github.com/cosmos/cosmos-sdk/x/distribution" "github.com/spf13/cobra" "github.com/spf13/viper" wire "github.com/tendermint/go-wire" @@ -38,7 +38,7 @@ var ( func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "withdraw-rewards [delegator]", - Short: "withdraw rewards from delegation accounts", + Short: "withdraw rewards for all delegations", RunE: func(cmd *cobra.Command, args []string) error { txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). @@ -61,7 +61,7 @@ func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { return err } - msg := stake.NewMsgDelegate(delAddr, valAddr, amount) + msg := distr.NewMsgDelegate(delAddr, valAddr, amount) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) diff --git a/x/distribution/handler.go b/x/distribution/handler.go index 02fb1c3ed6..39371610f4 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -7,7 +7,6 @@ import ( // distribution fee handler func DistributionFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) { - k. } ////////////////////////////////////////////////////////////////////////////////// diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 72e96715b3..4c0939aa3c 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -30,19 +30,18 @@ func (k Keeper) SetDelegatorDistInfo(ctx sdk.Context, ddi types.DelegatorDistInf //___________________________________________________________________________________________ -// XXX TODO -func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress) { - height = ctx.BlockHeight() +// withdraw all the rewards for a single delegation +func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr, + withdrawAddr sdk.AccAddress, validatorAddr sdk.ValAddress) { - // get all distribution scenarios - pool = stake.GetPool() - feePool = GetFeePool() - delInfo = GetDelegationDistInfo(delegatorAddr, - validatorAddr) - valInfo = GetValidatorDistInfo(validatorAddr) - validator = GetValidator(validatorAddr) + height := ctx.BlockHeight() + pool := stake.GetPool() + feePool := GetFeePool() + delInfo := GetDelegationDistInfo(delegatorAddr, validatorAddr) + valInfo := GetValidatorDistInfo(validatorAddr) + validator := GetValidator(validatorAddr) - feePool, withdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, + feePool, withdraw := delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) SetFeePool(feePool) @@ -51,30 +50,30 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr, validat /////////////////////////////////////////////////////////////////////////////////////// -// XXX TODO +// return all rewards for all delegations of a delegator func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr, withdrawAddr sdk.AccAddress) { - height = ctx.BlockHeight() - withdraw = GetDelegatorRewardsAll(delegatorAddr, height) + height := ctx.BlockHeight() + withdraw = GetDelegatorRewardsAll(ctx, delegatorAddr, height) k.coinsKeeper.AddCoins(withdrawAddr, withdraw.Amount.TruncateDecimal()) } -// XXX TODO +// return all rewards for all delegations of a delegator func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) DecCoins { - // collect all entitled rewards - withdraw = 0 - pool = stake.GetPool() - feePool = GetFeePool() + withdraw := sdk.NewDec(0) + pool := stake.GetPool() + feePool := GetFeePool() // iterate over all the delegations operationAtDelegation := func(_ int64, del types.Delegation) (stop bool) { - delInfo = GetDelegationDistInfo(delAddr, del.ValidatorAddr) - valInfo = GetValidatorDistInfo(del.ValidatorAddr) - validator = GetValidator(del.ValidatorAddr) + delInfo := GetDelegationDistInfo(delAddr, del.ValidatorAddr) + valInfo := GetValidatorDistInfo(del.ValidatorAddr) + validator := GetValidator(del.ValidatorAddr) - feePool, diWithdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, + feePool, diWithdraw := delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) - withdraw += diWithdraw + withdraw = withdraw.Add(diWithdraw) + SetFeePool(feePool) return false } k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation) diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 9a057b85b9..7643dd834b 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -28,21 +28,22 @@ func (k Keeper) SetValidatorDistInfo(ctx sdk.Context, vdi types.ValidatorDistInf } // XXX TODO -func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr, withdrawAddr sdk.AccAddress) { - height = ctx.BlockHeight() - feePool = k.GetFeePool(ctx) - pool = k.stakeKeeper.GetPool(ctx) - ValInfo = k.GetValidatorDistInfo(delegation.ValidatorAddr) - validator = k.GetValidator(delegation.ValidatorAddr) +func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, + operatorAddr sdk.ValAddress, withdrawAddr sdk.AccAddress) { // withdraw self-delegation - withdraw = k.GetDelegatorRewardsAll(validator.OperatorAddr, height) + height := ctx.BlockHeight() + validator := k.GetValidator(operatorAddr) + withdraw := k.GetDelegatorRewardsAll(validator.OperatorAddr, height) // withdrawal validator commission rewards - feePool, commission = valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens, + pool := k.stakeKeeper.GetPool(ctx) + valInfo := k.GetValidatorDistInfo(operatorAddr) + feePool := k.GetFeePool(ctx) + feePool, commission := valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens, validator.Tokens, validator.Commission) - withdraw += commission - SetFeePool(feePool) + withdraw = withdraw.Add(commission) + k.SetFeePool(feePool) k.coinKeeper.AddCoins(withdrawAddr, withdraw.TruncateDecimal()) } diff --git a/x/distribution/types/dec_coin.go b/x/distribution/types/dec_coin.go index 1bc803530a..70fd4a5820 100644 --- a/x/distribution/types/dec_coin.go +++ b/x/distribution/types/dec_coin.go @@ -1,23 +1,42 @@ package types -import sdk "github.com/cosmos/cosmos-sdk/types" +import ( + "strings" -// coins with decimal -type DecCoins []DecCoin + sdk "github.com/cosmos/cosmos-sdk/types" +) // Coins which can have additional decimal points type DecCoin struct { - Amount sdk.Dec `json:"amount"` Denom string `json:"denom"` + Amount sdk.Dec `json:"amount"` } func NewDecCoin(coin sdk.Coin) DecCoin { return DecCoins{ - Amount: sdk.NewDec(coin.Amount), Denom: coin.Denom, + Amount: sdk.NewDec(coin.Amount), } } +// Adds amounts of two coins with same denom +func (coin DecCoin) Plus(coinB DecCoin) DecCoin { + if !(coin.Denom == coinB.Denom) { + return coin + } + return Coin{coin.Denom, coin.Amount.Add(coinB.Amount)} +} + +// return the decimal coins with trunctated decimals +func (coin DecCoin) TruncateDecimal() sdk.Coin { + return sdk.NewCoin(coin.Denom, coin.Amount.TruncateInt()) +} + +//_______________________________________________________________________ + +// coins with decimal +type DecCoins []DecCoin + func NewDecCoins(coins sdk.Coins) DecCoins { dcs := make(DecCoins, len(coins)) @@ -25,3 +44,46 @@ func NewDecCoins(coins sdk.Coins) DecCoins { dcs[i] = NewDecCoin(coin) } } + +// return the decimal coins with trunctated decimals +func (coins DecCoins) TruncateDecimal() sdk.Coins { + out := make(DecCoins, len(coins)) + for i, coin := range coins { + out[i] = coin.TruncateDecimal() + } +} + +// Plus combines two sets of coins +// CONTRACT: Plus will never return Coins where one Coin has a 0 amount. +func (coins DecCoins) Plus(coinsB DecCoins) DecCoins { + sum := ([]DecCoin)(nil) + indexA, indexB := 0, 0 + lenA, lenB := len(coins), len(coinsB) + for { + if indexA == lenA { + if indexB == lenB { + return sum + } + return append(sum, coinsB[indexB:]...) + } else if indexB == lenB { + return append(sum, coins[indexA:]...) + } + coinA, coinB := coins[indexA], coinsB[indexB] + switch strings.Compare(coinA.Denom, coinB.Denom) { + case -1: + sum = append(sum, coinA) + indexA++ + case 0: + if coinA.Amount.Add(coinB.Amount).IsZero() { + // ignore 0 sum coin type + } else { + sum = append(sum, coinA.Plus(coinB)) + } + indexA++ + indexB++ + case 1: + sum = append(sum, coinB) + indexB++ + } + } +} From 922eb5e7ce9d63b91761a203bca42af1f1c189d6 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 10 Sep 2018 22:00:51 -0400 Subject: [PATCH 11/99] ... --- x/distribution/handler.go | 13 ------------- x/distribution/keeper/allocation.go | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/x/distribution/handler.go b/x/distribution/handler.go index 39371610f4..c602948488 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -1,14 +1 @@ package stake - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// distribution fee handler -func DistributionFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) { - -} - -////////////////////////////////////////////////////////////////////////////////// -// burn burn burn -func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 76cee338ba..19d4e2e163 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -3,7 +3,7 @@ package keeper import sdk "github.com/cosmos/cosmos-sdk/types" // Allocate fees handles distribution of the collected fees -func (k Keeper) AllocateFees(ctx sdk.Context, feesCollected sdk.Coins, proposerAddr sdk.ConsAddress) { +func (k Keeper) AllocateFees(ctx sdk.Context, _ sdk.Tx, feesCollected sdk.Coins, proposerAddr sdk.ConsAddress) { sumPowerPrecommitValidators := sdk.NewDec(1) // XXX TODO actually calculate this communityTax := sdk.NewDecWithPrec(1, 2) // XXX TODO get from global params store From a1530880736534c48d812fa5165d38937a59b532 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 11 Sep 2018 13:35:47 -0400 Subject: [PATCH 12/99] ... --- x/auth/ante.go | 3 --- x/auth/feekeeper.go | 7 ++----- x/distribution/begin_block.go | 9 +++++++++ x/distribution/keeper/allocation.go | 30 +++++++++++++++++++++-------- x/distribution/types/keepers.go | 8 +++++++- 5 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 x/distribution/begin_block.go diff --git a/x/auth/ante.go b/x/auth/ante.go index 5b2cdb1559..46daf39dd8 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -255,6 +255,3 @@ func deductFees(acc Account, fee StdFee) (Account, sdk.Result) { } return acc, sdk.Result{} } - -// BurnFeeHandler burns all fees (decreasing total supply) -func BurnFeeHandler(_ sdk.Context, _ sdk.Tx, _ sdk.Coins) {} diff --git a/x/auth/feekeeper.go b/x/auth/feekeeper.go index 3e03a81aa2..ef8754809d 100644 --- a/x/auth/feekeeper.go +++ b/x/auth/feekeeper.go @@ -20,7 +20,6 @@ type FeeCollectionKeeper struct { cdc *wire.Codec } -// NewFeeKeeper returns a new FeeKeeper func NewFeeCollectionKeeper(cdc *wire.Codec, key sdk.StoreKey) FeeCollectionKeeper { return FeeCollectionKeeper{ key: key, @@ -28,7 +27,7 @@ func NewFeeCollectionKeeper(cdc *wire.Codec, key sdk.StoreKey) FeeCollectionKeep } } -// 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{}) } diff --git a/x/distribution/begin_block.go b/x/distribution/begin_block.go new file mode 100644 index 0000000000..7edfc2cf03 --- /dev/null +++ b/x/distribution/begin_block.go @@ -0,0 +1,9 @@ +package distribution + +import "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + +// slashing begin block functionality +func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, dk keeper.Keeper) (tags sdk.Tags) { + + return +} diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 19d4e2e163..662d848b43 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -1,34 +1,48 @@ package keeper -import sdk "github.com/cosmos/cosmos-sdk/types" +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) // Allocate fees handles distribution of the collected fees -func (k Keeper) AllocateFees(ctx sdk.Context, _ sdk.Tx, feesCollected sdk.Coins, proposerAddr sdk.ConsAddress) { - - sumPowerPrecommitValidators := sdk.NewDec(1) // XXX TODO actually calculate this - communityTax := sdk.NewDecWithPrec(1, 2) // XXX TODO get from global params store - - feePool := k.GetFeePool(ctx) - stakePool := k.stakeKeeper.GetPool(ctx) +func (k Keeper) AllocateFees(ctx sdk.Context, req abci.RequestBeginBlock) { + // get the proposer of this block + proposerAddr := req.Header.Proposer.PubKey // XXX use address? proserValidator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, proposerAddr) proposerDist := k.GetFeeDistribution(ctx, proserValidator.OperatorAddr) + // get the fees which have been getting collected through all the + // transactions in the block + feesCollected := k.FeeCollectionKeeper.GetCollectedFees(ctx) feesCollectedDec := NewDecCoins(feesCollected) + + // allocated rewards to proposer + stakePool := k.stakeKeeper.GetPool(ctx) + sumPowerPrecommitValidators := sdk.NewDec(1) // XXX TODO actually calculate this proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( sumPowerPrecommitValidators).Div(stakePool.BondedTokens)) proposerReward := feesCollectedDec.Mul(proposerMultiplier) + // apply commission commission := proposerReward.Mul(proserValidator.Commission) proposerDist.PoolCommission = proposerDist.PoolCommission.Add(commission) proposerDist.Pool = proposerDist.Pool.Add(proposerReward.Sub(commission)) + // allocate community funding + communityTax := sdk.NewDecWithPrec(1, 2) // XXX TODO get from global params store communityFunding := feesCollectedDec.Mul(communityTax) + feePool := k.GetFeePool(ctx) feePool.CommunityFund = feePool.CommunityFund.Add(communityFunding) + // set the global pool within the distribution module poolReceived := feesCollectedDec.Sub(proposerReward).Sub(communityFunding) feePool.Pool = feePool.Pool.Add(poolReceived) SetValidatorDistribution(proposerDist) SetFeePool(feePool) + + // clear the now distributed fees + k.FeeCollectionKeeper.ClearCollectedFees(ctx) } diff --git a/x/distribution/types/keepers.go b/x/distribution/types/keepers.go index 15a1377185..7b05392167 100644 --- a/x/distribution/types/keepers.go +++ b/x/distribution/types/keepers.go @@ -12,6 +12,12 @@ type StakeKeeper interface { } // expected coin keeper -type CoinKeeper interface { +type BankKeeper interface { AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) } + +// from ante handler +type FeeCollectionKeeper interface { + GetCollectedFees(ctx sdk.Context) sdk.Coins + ClearCollectedFees(ctx sdk.Context) +} From dae32a3d65f100da2b65b466f6a043ca4730612a Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 13 Sep 2018 03:03:30 -0400 Subject: [PATCH 13/99] ... --- x/distribution/keeper/keeper.go | 17 ++++++++++++++--- x/distribution/keeper/key.go | 5 ++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 741e3aa9aa..7cc2c1290f 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -9,6 +9,7 @@ import ( // keeper of the stake store type Keeper struct { storeKey sdk.StoreKey + storeTKey sdk.StoreKey cdc *wire.Codec coinKeeper types.CoinKeeper stakeKeeper types.StakeKeeper @@ -17,11 +18,12 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck types.CoinKeeper, +func NewKeeper(cdc *wire.Codec, key, tkey sdk.StoreKey, ck types.CoinKeeper, sk types.StakeKeeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ storeKey: key, + storeTKey: tkey, cdc: cdc, coinKeeper: ck, codespace: codespace, @@ -35,7 +37,7 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck types.CoinKeeper, func (k Keeper) GetFeePool(ctx sdk.Context) (feePool types.FeePool) { store := ctx.KVStore(k.storeKey) - b := store.Get(GlobalKey) + b := store.Get(FeePoolKey) if b == nil { panic("Stored fee pool should not have been nil") } @@ -48,5 +50,14 @@ func (k Keeper) GetFeePool(ctx sdk.Context) (feePool types.FeePool) { func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.FeePool) { store := ctx.KVStore(k.storeKey) b := k.cdc.MustMarshalBinary(feePool) - store.Set(GlobalKey, b) + store.Set(FeePoolKey, b) +} + +//______________________________________________________________________ + +// set the global fee pool distribution info +func (k Keeper) GetFeePool(ctx sdk.Context, proposerPK sdk.PubKey) { + store := ctx.KVStore(k.storeKey) + b := k.cdc.MustMarshalBinary(proposerPK) + store.Set(ProposerKey, b) } diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index f4cf1e0f9c..2b09573ad7 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -6,9 +6,12 @@ import ( // keys/key-prefixes var ( - GlobalKey = []byte{0x00} // key for global distribution state + FeePoolKey = []byte{0x00} // key for global distribution state ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution DelegatorDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution + + // transient + ProposerKey = []byte{0x00} // key for storing the proposer operator address ) // gets the key for the validator distribution info from address From d60f620787663bf496fb00ef696e2d2895a59472 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 14 Sep 2018 02:35:02 -0400 Subject: [PATCH 14/99] working --- x/distribution/abci_app.go | 17 ++++++++++++++++ x/distribution/begin_block.go | 9 --------- x/distribution/hooks.go | 26 +++++++++++++++++++++++++ x/distribution/keeper/allocation.go | 7 +++---- x/distribution/keeper/delegation.go | 27 +++++++++++++------------- x/distribution/keeper/keeper.go | 22 +++++++++++++++++---- x/distribution/keeper/validator.go | 10 +++++----- x/distribution/types/dec_coin.go | 13 +++++++++++++ x/distribution/types/delegator_info.go | 13 ++++++------- x/distribution/types/fee_pool.go | 2 +- x/stake/keeper/key.go | 8 +++----- x/stake/keeper/validator.go | 5 +++-- 12 files changed, 108 insertions(+), 51 deletions(-) create mode 100644 x/distribution/abci_app.go delete mode 100644 x/distribution/begin_block.go diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go new file mode 100644 index 0000000000..e70252a8de --- /dev/null +++ b/x/distribution/abci_app.go @@ -0,0 +1,17 @@ +package distribution + +import ( + "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + abci "github.com/tendermint/tendermint/abci/types" +) + +// set the proposer for determining distribution during endblock +func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) { + consAddr := sdk.ConsAddress{req.Header.Proposer.Address} + k.SetProposerConsAddr(consAddr) +} + +// allocate fees +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + k.AllocateFees(ctx) +} diff --git a/x/distribution/begin_block.go b/x/distribution/begin_block.go deleted file mode 100644 index 7edfc2cf03..0000000000 --- a/x/distribution/begin_block.go +++ /dev/null @@ -1,9 +0,0 @@ -package distribution - -import "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - -// slashing begin block functionality -func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, dk keeper.Keeper) (tags sdk.Tags) { - - return -} diff --git a/x/distribution/hooks.go b/x/distribution/hooks.go index 689ffabbf8..75f6be6d85 100644 --- a/x/distribution/hooks.go +++ b/x/distribution/hooks.go @@ -26,3 +26,29 @@ Whenever a validator is slashed or enters/leaves the validator group all of the validator entitled reward tokens must be simultaneously withdrawn from `Global.Pool` and added to `ValidatorDistInfo.Pool`. */ + +// Create a new validator distribution record +func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { + slashingPeriod := ValidatorSlashingPeriod{ + ValidatorAddr: address, + StartHeight: ctx.BlockHeight(), + EndHeight: 0, + SlashedSoFar: sdk.ZeroDec(), + } + k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) +} + +//_________________________________________________________________________________________ + +// Wrapper struct for sdk.ValidatorHooks +type ValidatorHooks struct { + k Keeper +} + +var _ sdk.ValidatorHooks = ValidatorHooks{} + +// nolint +func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { return ValidatorHooks{k} } +func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { + v.k.onValidatorBonded(ctx, address) +} diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 662d848b43..922d609897 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -2,15 +2,14 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - abci "github.com/tendermint/tendermint/abci/types" ) // Allocate fees handles distribution of the collected fees -func (k Keeper) AllocateFees(ctx sdk.Context, req abci.RequestBeginBlock) { +func (k Keeper) AllocateFees(ctx sdk.Context) { // get the proposer of this block - proposerAddr := req.Header.Proposer.PubKey // XXX use address? - proserValidator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, proposerAddr) + proposerConsAddr := k.GetProposerConsAddr(ctx) + proserValidator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, proposerConsAddr) proposerDist := k.GetFeeDistribution(ctx, proserValidator.OperatorAddr) // get the fees which have been getting collected through all the diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 4c0939aa3c..d3f0602b96 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -3,7 +3,6 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" - "github.com/cosmos/cosmos-sdk/x/stake" ) // get the delegator distribution info @@ -35,17 +34,17 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr, withdrawAddr sdk.AccAddress, validatorAddr sdk.ValAddress) { height := ctx.BlockHeight() - pool := stake.GetPool() - feePool := GetFeePool() - delInfo := GetDelegationDistInfo(delegatorAddr, validatorAddr) - valInfo := GetValidatorDistInfo(validatorAddr) - validator := GetValidator(validatorAddr) + pool := k.sk.GetPool(ctx) + feePool := k.GetFeePool(ctx) + delInfo := k.GetDelegationDistInfo(ctx, delegatorAddr, validatorAddr) + valInfo := k.GetValidatorDistInfo(ctx, validatorAddr) + validator := k.GetValidator(ctx, validatorAddr) feePool, withdraw := delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) - SetFeePool(feePool) - AddCoins(withdrawAddr, withdraw.TruncateDecimal()) + k.SetFeePool(ctx, feePool) + k.ck.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) } /////////////////////////////////////////////////////////////////////////////////////// @@ -61,14 +60,14 @@ func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr, wit func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) DecCoins { withdraw := sdk.NewDec(0) - pool := stake.GetPool() - feePool := GetFeePool() + pool := k.sk.GetPool(ctx) + feePool := k.GetFeePool(ctx) // iterate over all the delegations operationAtDelegation := func(_ int64, del types.Delegation) (stop bool) { - delInfo := GetDelegationDistInfo(delAddr, del.ValidatorAddr) - valInfo := GetValidatorDistInfo(del.ValidatorAddr) - validator := GetValidator(del.ValidatorAddr) + delInfo := k.GetDelegationDistInfo(ctx, delAddr, del.ValidatorAddr) + valInfo := k.GetValidatorDistInfo(ctx, del.ValidatorAddr) + validator := k.sk.GetValidator(ctx, del.ValidatorAddr) feePool, diWithdraw := delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) @@ -78,6 +77,6 @@ func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, } k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation) - SetFeePool(feePool) + k.SetFeePool(ctx, feePool) return withdraw } diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 7cc2c1290f..13c5a0b734 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -1,9 +1,10 @@ package keeper import ( + wire "github.com/tendermint/go-wire" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" - wire "github.com/tendermint/go-wire" ) // keeper of the stake store @@ -55,9 +56,22 @@ func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.FeePool) { //______________________________________________________________________ -// set the global fee pool distribution info -func (k Keeper) GetFeePool(ctx sdk.Context, proposerPK sdk.PubKey) { +// set the proposer public key for this block +func (k Keeper) GetProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress) { store := ctx.KVStore(k.storeKey) - b := k.cdc.MustMarshalBinary(proposerPK) + + b := store.Get(ProposerKey) + if b == nil { + panic("Stored fee pool should not have been nil") + } + + k.cdc.MustUnmarshalBinary(b, &consAddr) + return +} + +// get the proposer public key for this block +func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { + store := ctx.KVStore(k.storeKey) + b := k.cdc.MustMarshalBinary(consAddr) store.Set(ProposerKey, b) } diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 7643dd834b..5df5bb8f7f 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -11,7 +11,7 @@ func (k Keeper) GetValidatorDistInfo(ctx sdk.Context, store := ctx.KVStore(k.storeKey) - b := store.Get(GetValidatorDistInfoKey(operatorAddr)) + b := store.Get(GetValidatorDistInfoKey(ctx, operatorAddr)) if b == nil { panic("Stored delegation-distribution info should not have been nil") } @@ -24,7 +24,7 @@ func (k Keeper) GetValidatorDistInfo(ctx sdk.Context, 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) + store.Set(GetValidatorDistInfoKey(ctx, vdi.OperatorAddr), b) } // XXX TODO @@ -33,12 +33,12 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, // withdraw self-delegation height := ctx.BlockHeight() - validator := k.GetValidator(operatorAddr) - withdraw := k.GetDelegatorRewardsAll(validator.OperatorAddr, height) + validator := k.GetValidator(ctx, operatorAddr) + withdraw := k.GetDelegatorRewardsAll(ctx, validator.OperatorAddr, height) // withdrawal validator commission rewards pool := k.stakeKeeper.GetPool(ctx) - valInfo := k.GetValidatorDistInfo(operatorAddr) + valInfo := k.GetValidatorDistInfo(ctx, operatorAddr) feePool := k.GetFeePool(ctx) feePool, commission := valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens, validator.Tokens, validator.Commission) diff --git a/x/distribution/types/dec_coin.go b/x/distribution/types/dec_coin.go index 70fd4a5820..4e6a4cfc3c 100644 --- a/x/distribution/types/dec_coin.go +++ b/x/distribution/types/dec_coin.go @@ -87,3 +87,16 @@ func (coins DecCoins) Plus(coinsB DecCoins) DecCoins { } } } + +// multiply all the coins by a multiple +func (coins DecCoins) Mul(multiple sdk.Dec) DecCoins { + products := make([]DecCoin, len(coins)) + for i, coin := range coins { + product := DecCoins{ + Denom: coin.Denom, + Amount: coin.Amount.Mul(multiple), + } + products[i] = product + } + return products +} diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index 55914b59ff..1fda6dba71 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -11,20 +11,19 @@ type DelegatorDistInfo struct { // withdraw rewards from delegator func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, - height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) ( - di DelegatorDistInfo, g Global, withdrawn DecCoins) { + height int64, totalBonded, vdTokens, totalDelShares, delegatorShares, + commissionRate Dec) (di DelegatorDistInfo, g Global, withdrawn DecCoins) { vi.UpdateTotalDelAccum(height, totalDelShares) g = vi.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) blocks = height - di.WithdrawalHeight di.WithdrawalHeight = height - accum = delegatorShares * blocks + accum := delegatorShares.Mul(sdk.NewDec(blocks)) + withdrawalTokens := vi.Pool.Mul(accum.Quo(vi.TotalDelAccum)) - withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum - vi.TotalDelAccum -= accum + vi.Pool = vi.Pool.Sub(withdrawalTokens) + vi.TotalDelAccum = vi.TotalDelAccum.sub(accum) - vi.Pool -= withdrawalTokens - vi.TotalDelAccum -= accum return di, g, withdrawalTokens } diff --git a/x/distribution/types/fee_pool.go b/x/distribution/types/fee_pool.go index 1058db77c7..072acb44db 100644 --- a/x/distribution/types/fee_pool.go +++ b/x/distribution/types/fee_pool.go @@ -11,7 +11,7 @@ type TotalAccum struct { // update total validator accumulation factor func (ta TotalAccum) Update(height int64, accumCreatedPerBlock sdk.Dec) TotalAccum { blocks := height - ta.UpdateHeight - f.Accum += accumCreatedPerBlock.Mul(sdk.NewDec(blocks)) + f.Accum = f.Accum.Add(accumCreatedPerBlock.Mul(sdk.NewDec(blocks))) ta.UpdateHeight = height return ta } diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index c445e25524..91e6a69708 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -3,8 +3,6 @@ package keeper import ( "encoding/binary" - "github.com/tendermint/tendermint/crypto" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" ) @@ -17,7 +15,7 @@ var ( ParamKey = []byte{0x00} // key for parameters relating to staking PoolKey = []byte{0x01} // key for the staking pools ValidatorsKey = []byte{0x02} // prefix for each key to a validator - ValidatorsByPubKeyIndexKey = []byte{0x03} // prefix for each key to a validator index, by pubkey + ValidatorsByConsAddrKey = []byte{0x03} // prefix for each key to a validator index, by pubkey ValidatorsBondedIndexKey = []byte{0x04} // prefix for each key to a validator index, for bonded validators ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator @@ -44,8 +42,8 @@ func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { // gets the key for the validator with pubkey // VALUE: validator operator address ([]byte) -func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte { - return append(ValidatorsByPubKeyIndexKey, pubkey.Bytes()...) +func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { + return append(ValidatorsByConsAddrKey, addr.Bytes()...) } // gets the key for the current validator group diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 1f65aaa957..d651b04944 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -76,9 +76,10 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { } // validator index -func (k Keeper) SetValidatorByPubKeyIndex(ctx sdk.Context, validator types.Validator) { +func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorByPubKeyIndexKey(validator.ConsPubKey), validator.OperatorAddr) + consAddr := sdk.consAddress{validator.Address()} + store.Set(GetValidatorByPubKeyIndexKey(consAddr), validator.OperatorAddr) } // validator index From 431fdb869572cc75e8ae0f509414516104753802 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 17 Sep 2018 23:02:15 -0400 Subject: [PATCH 15/99] hook, genesis, and withdraw address --- cmd/gaia/app/app.go | 14 ++++ types/stake.go | 24 +++++-- x/distribution/codec.go | 10 +++ x/distribution/genesis.go | 46 +++++++++++++ x/distribution/handler.go | 2 +- x/distribution/hooks.go | 74 +++++++++++++++++++-- x/distribution/keeper.go | 91 -------------------------- x/distribution/keeper/delegation.go | 45 +++++++++++-- x/distribution/keeper/genesis.go | 51 +++++++++++++++ x/distribution/keeper/key.go | 12 +++- x/distribution/keeper/validator.go | 8 ++- x/distribution/types/delegator_info.go | 14 +++- x/distribution/types/fee_pool.go | 16 +++++ x/distribution/types/genesis.go | 26 ++++++++ x/distribution/types/validator_info.go | 10 +-- 15 files changed, 325 insertions(+), 118 deletions(-) create mode 100644 x/distribution/codec.go create mode 100644 x/distribution/genesis.go delete mode 100644 x/distribution/keeper.go create mode 100644 x/distribution/keeper/genesis.go create mode 100644 x/distribution/types/genesis.go diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index da79a055a4..39cb596946 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -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/ibc" "github.com/cosmos/cosmos-sdk/x/params" @@ -45,6 +46,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 @@ -57,6 +60,7 @@ type GaiaApp struct { ibcMapper ibc.Mapper stakeKeeper stake.Keeper slashingKeeper slashing.Keeper + distrKeeper distr.Keeper govKeeper gov.Keeper paramsKeeper params.Keeper } @@ -76,6 +80,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio keyIBC: sdk.NewKVStoreKey("ibc"), 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"), @@ -95,6 +101,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.distrKeeper = distr.NewKeeper(app.cdc, app.keyDistr, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks()) app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) @@ -105,6 +112,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio AddRoute("bank", bank.NewHandler(app.bankKeeper)). AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.bankKeeper)). AddRoute("stake", stake.NewHandler(app.stakeKeeper)). + AddRoute("distr", stake.NewHandler(app.distrKeeper)). AddRoute("slashing", slashing.NewHandler(app.slashingKeeper)). AddRoute("gov", gov.NewHandler(app.govKeeper)) @@ -134,6 +142,7 @@ func MakeCodec() *codec.Codec { ibc.RegisterCodec(cdc) bank.RegisterCodec(cdc) stake.RegisterCodec(cdc) + distr.RegisterCodec(cdc) slashing.RegisterCodec(cdc) gov.RegisterCodec(cdc) auth.RegisterCodec(cdc) @@ -145,6 +154,7 @@ func MakeCodec() *codec.Codec { // application updates every end block func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper) + distr.BeginBlocker(ctx, req, app.distrKeeper) return abci.ResponseBeginBlock{ Tags: tags.ToKVPairs(), @@ -156,6 +166,10 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { tags := gov.EndBlocker(ctx, app.govKeeper) validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) + + // distribute rewards + distr.EndBlocker(ctx, app.distrKeeper) + // Add these new validators to the addr -> pubkey map. app.slashingKeeper.AddValidators(ctx, validatorUpdates) return abci.ResponseEndBlock{ diff --git a/types/stake.go b/types/stake.go index 0b9f32b4b8..54fd564afd 100644 --- a/types/stake.go +++ b/types/stake.go @@ -100,12 +100,26 @@ type DelegationSet interface { fn func(index int64, delegation Delegation) (stop bool)) } -// validator event hooks -// These can be utilized to communicate between a staking keeper -// and another keeper which must take particular actions when -// validators are bonded and unbonded. The second keeper must implement -// this interface, which then the staking keeper can call. +//_______________________________________________________________________________ +// Event Hooks +// These can be utilized to communicate between a staking keeper and another +// keeper which must take particular actions when validators/delegators change +// state. The second keeper must implement this interface, which then the +// staking keeper can call. + +// event hooks for staking validator object type ValidatorHooks interface { + OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created + OnValidatorBondModified(ctx Context, address ValAddress) // Must be called when a validator's bond amount is modified + OnValidatorRemoved(ctx Context, address ValAddress) // Must be called when a validator is deleted + OnValidatorBonded(ctx Context, address ConsAddress) // Must be called when a validator is bonded OnValidatorBeginUnbonding(ctx Context, address ConsAddress) // Must be called when a validator begins unbonding } + +// event hooks for staking delegator object +type DelegatorHooks interface { + OnDelegationCreated(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is created + OnDelegationSharesModified(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation's shares are modified + OnDelegationRemoved(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is removed +} diff --git a/x/distribution/codec.go b/x/distribution/codec.go new file mode 100644 index 0000000000..e3bf8d49ae --- /dev/null +++ b/x/distribution/codec.go @@ -0,0 +1,10 @@ +package distribution + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +// XXX TODO +// Register concrete types on codec codec +func RegisterCodec(cdc *codec.Codec) { +} diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go new file mode 100644 index 0000000000..1ff4a06d6f --- /dev/null +++ b/x/distribution/genesis.go @@ -0,0 +1,46 @@ +package distribution + +import ( + abci "github.com/tendermint/tendermint/abci/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/stake/types" +) + +// InitGenesis sets the pool and parameters for the provided keeper and +// initializes the IntraTxCounter. For each validator in data, it sets that +// validator in the keeper along with manually setting the indexes. In +// addition, it also sets any delegations found in data. Finally, it updates +// the bonded validators. +// Returns final validator set after applying all declaration and delegations +func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res []abci.Validator, err error) { + keeper.SetFeePool(ctx, data.FeePool) + + for _, vdi := range data.ValidatorDistInfos { + keeper.SetValidatorDistInfo(ctx, vdi) + } + for _, ddi := range data.DelegatorDistInfos { + keeper.SetDelegatorDistInfo(ctx, ddi) + } + for _, dw := range data.DelegatorWithdrawAddrs { + keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr) + } + + return +} + +// 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) + vdis := keeper.GetAllVDIs(ctx) + ddis := keeper.GetAllDDIs(ctx) + dws := keeper.GetAllDWs(ctx) + + return GenesisState{ + FeePool: feePool, + ValidatorDistInfos: vdis, + DelegatorDistInfos: ddis, + DelegatorWithdrawAddrs: dws, + } +} diff --git a/x/distribution/handler.go b/x/distribution/handler.go index c602948488..d2ef538fb1 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -1 +1 @@ -package stake +package distribution diff --git a/x/distribution/hooks.go b/x/distribution/hooks.go index 75f6be6d85..9a6f7cfbf9 100644 --- a/x/distribution/hooks.go +++ b/x/distribution/hooks.go @@ -1,4 +1,6 @@ -package stake +package distribution + +import "github.com/cosmos/cosmos-sdk/x/distribution/types" /* ## Create or modify delegation distribution @@ -28,7 +30,39 @@ validator entitled reward tokens must be simultaneously withdrawn from */ // Create a new validator distribution record -func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { +func (k Keeper) onValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { + + height := ctx.BlockHeight() + vdi := types.ValidatorDistInfo{ + OperatorAddr: addr, + GlobalWithdrawalHeight: height, + Pool: DecCoins{}, + PoolCommission: DecCoins{}, + DelAccum: NewTotalAccum(height), + } + k.SetValidatorDistInfo(ctx, vdi) +} + +// Withdrawal all distubution rewards // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX +func (k Keeper) onValidatorBondModified(ctx sdk.Context, addr sdk.ValAddress) { + slashingPeriod := ValidatorSlashingPeriod{ + ValidatorAddr: address, + StartHeight: ctx.BlockHeight(), + EndHeight: 0, + SlashedSoFar: sdk.ZeroDec(), + } + k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) +} + +// 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 validator distribution record +func (k Keeper) onDelegationCreated(ctx sdk.Context, address sdk.ConsAddress) { slashingPeriod := ValidatorSlashingPeriod{ ValidatorAddr: address, StartHeight: ctx.BlockHeight(), @@ -49,6 +83,38 @@ var _ sdk.ValidatorHooks = ValidatorHooks{} // nolint func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { return ValidatorHooks{k} } -func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { - v.k.onValidatorBonded(ctx, address) +func (v ValidatorHooks) OnValidatorCreated(ctx sdk.Context, addr sdk.VlAddress) { + v.k.OnValidatorCreated(ctx, address) +} +func (v ValidatorHooks) OnValidatorBondModified(ctx sdk.Context, addr sdk.ValAddress) { + v.k.OnValidatorBondModified(ctx, address) +} +func (v ValidatorHooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { + v.k.OnValidatorRemoved(ctx, address) +} +func (v ValidatorHooks) OnValidatorBonded(_ sdk.Context, _ sdk.ConsAddress) {} +func (v ValidatorHooks) OnValidatorBeginBonded(_ sdk.Context, _ sdk.ConsAddress) {} + +//_________________________________________________________________________________________ + +// Wrapper struct for sdk.DelegationHooks +type DelegationHooks struct { + k Keeper +} + +var _ sdk.DelegationHooks = DelegationHooks{} + +// nolint +func (k Keeper) DelegationHooks() sdk.DelegationHooks { return DelegationHooks{k} } +func (d DelegationHooks) OnDelegatoinCreated(ctx sdk.Context, + delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + d.k.OnDelegatoinCreated(ctx, address) +} +func (d DelegationHooks) OnDelegationSharesModified(ctx sdk.Context, + delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + d.k.OnDelegationSharesModified(ctx, address) +} +func (d DelegationHooks) OnDelegationRemoved(ctx sdk.Context, + delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + d.k.OnDelegationRemoved(ctx, address) } diff --git a/x/distribution/keeper.go b/x/distribution/keeper.go deleted file mode 100644 index 937a4674cf..0000000000 --- a/x/distribution/keeper.go +++ /dev/null @@ -1,91 +0,0 @@ -package stake - -//// keeper of the staking store -//type Keeper struct { -//storeKey sdk.StoreKey -//cdc *codec.Codec -//bankKeeper bank.Keeper - -//// codespace -//codespace sdk.CodespaceType -//} - -//func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { -//keeper := Keeper{ -//storeKey: key, -//cdc: cdc, -//bankKeeper: ck, -//codespace: codespace, -//} -//return keeper -//} - -////_________________________________________________________________________ - -//// cummulative power of the non-absent prevotes -//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Dec { -//store := ctx.KVStore(k.storeKey) - -//// get absent prevote indexes -//absents := ctx.AbsentValidators() - -//TotalPower := sdk.ZeroDec() -//i := int32(0) -//iterator := store.SubspaceIterator(ValidatorsBondedKey) -//for ; iterator.Valid(); iterator.Next() { - -//skip := false -//for j, absentIndex := range absents { -//if absentIndex > i { -//break -//} - -//// if non-voting validator found, skip adding its power -//if absentIndex == i { -//absents = append(absents[:j], absents[j+1:]...) // won't need again -//skip = true -//break -//} -//} -//if skip { -//continue -//} - -//bz := iterator.Value() -//var validator Validator -//k.cdc.MustUnmarshalBinary(bz, &validator) -//TotalPower = TotalPower.Add(validator.Power) -//i++ -//} -//iterator.Close() -//return TotalPower -//} - -////_______________________________________________________________________ - -//// XXX TODO trim functionality - -//// retrieve all the power changes which occur after a height -//func (k Keeper) GetPowerChangesAfterHeight(ctx sdk.Context, earliestHeight int64) (pcs []PowerChange) { -//store := ctx.KVStore(k.storeKey) - -//iterator := store.SubspaceIterator(PowerChangeKey) //smallest to largest -//for ; iterator.Valid(); iterator.Next() { -//pcBytes := iterator.Value() -//var pc PowerChange -//k.cdc.MustUnmarshalBinary(pcBytes, &pc) -//if pc.Height < earliestHeight { -//break -//} -//pcs = append(pcs, pc) -//} -//iterator.Close() -//return -//} - -//// set a power change -//func (k Keeper) setPowerChange(ctx sdk.Context, pc PowerChange) { -//store := ctx.KVStore(k.storeKey) -//b := k.cdc.MustMarshalBinary(pc) -//store.Set(GetPowerChangeKey(pc.Height), b) -//} diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index d3f0602b96..5bf6793f19 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -27,11 +27,44 @@ func (k Keeper) SetDelegatorDistInfo(ctx sdk.Context, ddi types.DelegatorDistInf store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b) } +// remove a delegator distribution info +func (k Keeper) RemoveDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, + valOperatorAddr sdk.ValAddress) { + + store := ctx.KVStore(k.storeKey) + store.Delete(GetDelegationDistInfoKey(DelegatorAddr, 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(ddi.DelegatorAddr), 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, - withdrawAddr sdk.AccAddress, validatorAddr sdk.ValAddress) { +func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccAddress, + validatorAddr sdk.ValAddress) { height := ctx.BlockHeight() pool := k.sk.GetPool(ctx) @@ -44,15 +77,17 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr, validator.Tokens, validator.DelegatorShares, validator.Commission) k.SetFeePool(ctx, feePool) + withdrawAddr := k.GetDelegatorWithdrawAddr(delegatorAddr) k.ck.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) } -/////////////////////////////////////////////////////////////////////////////////////// +//___________________________________________________________________________________________ // return all rewards for all delegations of a delegator -func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr, withdrawAddr sdk.AccAddress) { +func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr sdk.AccAddress) { height := ctx.BlockHeight() - withdraw = GetDelegatorRewardsAll(ctx, delegatorAddr, height) + withdraw = k.GetDelegatorRewardsAll(ctx, delegatorAddr, height) + withdrawAddr := k.GetDelegatorWithdrawAddr(delegatorAddr) k.coinsKeeper.AddCoins(withdrawAddr, withdraw.Amount.TruncateDecimal()) } diff --git a/x/distribution/keeper/genesis.go b/x/distribution/keeper/genesis.go new file mode 100644 index 0000000000..dfc6109240 --- /dev/null +++ b/x/distribution/keeper/genesis.go @@ -0,0 +1,51 @@ +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) GetAllVDIs(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) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegatorDistInfo) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, DelegatorDistInfoKey) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var ddi types.DelegatorDistInfo + 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) GetAllDWs(ctx sdk.Context) (dws []types.DelegatorWithdrawInfo) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, DelegatorDistInfoKey) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + addr := iterator.Key()[1:] + dw := types.DelegatorWithdrawInfo{ + DelegatorAddr: sdk.AccAddress{iterator.Key()}, + WithdrawAddr: sdk.AccAddress{iterator.Value()}, + } + dws = append(dws, dw) + } + return dws +} diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index 2b09573ad7..f6f93464f6 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -6,9 +6,10 @@ import ( // keys/key-prefixes var ( - FeePoolKey = []byte{0x00} // key for global distribution state - ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution - DelegatorDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution + FeePoolKey = []byte{0x00} // key for global distribution state + ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution + DelegatorDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution + DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info // transient ProposerKey = []byte{0x00} // key for storing the proposer operator address @@ -30,3 +31,8 @@ func GetDelegationDistInfoKey(delAddr sdk.AccAddress, valOperatorAddr sdk.ValAdd func GetDelegationDistInfosKey(delAddr sdk.AccAddress) []byte { return append(DelegatorDistInfoKey, delAddr.Bytes()...) } + +// gets the prefix for a delegator's withdraw info +func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte { + return append(DelegatorWithdrawInfoKey, delAddr.Bytes()...) +} diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 5df5bb8f7f..7de71300cd 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -27,7 +27,13 @@ func (k Keeper) SetValidatorDistInfo(ctx sdk.Context, vdi types.ValidatorDistInf store.Set(GetValidatorDistInfoKey(ctx, vdi.OperatorAddr), b) } -// XXX TODO +// remove a validator distribution info +func (k Keeper) RemoveValidatorDistInfo(ctx sdk.Context, valAddr sdk.ValAddress) { + store := ctx.KVStore(k.storeKey) + store.Delete(GetValidatorDistInfoKey(ctx, vdi.OperatorAddr)) +} + +// withdrawal all the validator rewards including the commission func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.ValAddress, withdrawAddr sdk.AccAddress) { diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index 1fda6dba71..c34fad0772 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -4,9 +4,9 @@ import sdk "github.com/cosmos/cosmos-sdk/types" // distribution info for a delegation type DelegatorDistInfo struct { - DelegatorAddr sdk.AccAddress - ValOperatorAddr sdk.ValAddress - WithdrawalHeight int64 // last time this delegation withdrew rewards + DelegatorAddr sdk.AccAddress `json:"delegator_addr"` + ValOperatorAddr sdk.ValAddress `json:"val_operator_addr"` + WithdrawalHeight int64 `json:"withdrawal_height"` // last time this delegation withdrew rewards } // withdraw rewards from delegator @@ -27,3 +27,11 @@ func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, return di, g, withdrawalTokens } + +//_____________________________________________________________________ + +// withdraw address for the delegation rewards +type DelegatorWithdrawInfo struct { + DelegatorAddr sdk.AccAddress `json:"delegator_addr"` + WithdrawAddr sdk.AccAddress `json:"withdraw_addr"` +} diff --git a/x/distribution/types/fee_pool.go b/x/distribution/types/fee_pool.go index 072acb44db..14744689df 100644 --- a/x/distribution/types/fee_pool.go +++ b/x/distribution/types/fee_pool.go @@ -8,6 +8,13 @@ type TotalAccum struct { Accum sdk.Dec `json:"accum"` } +func NewTotalAccum(height int64) TotalAccum { + return TotalAccum{ + UpdateHeight: height, + Accum: sdk.ZeroDec(), + } +} + // update total validator accumulation factor func (ta TotalAccum) Update(height int64, accumCreatedPerBlock sdk.Dec) TotalAccum { blocks := height - ta.UpdateHeight @@ -30,3 +37,12 @@ func (f FeePool) UpdateTotalValAccum(height int64, totalBondedTokens Dec) FeePoo f.ValAccum = f.ValAccum.Update(height, totalBondedTokens) return f } + +// zero fee pool +func InitialFeePool() FeePool { + return FeePool{ + ValAccum: NewwTotalAccum(0), + Pool: DecCoins{}, + CommunityPool: DecCoins{}, + } +} diff --git a/x/distribution/types/genesis.go b/x/distribution/types/genesis.go new file mode 100644 index 0000000000..782f54ade0 --- /dev/null +++ b/x/distribution/types/genesis.go @@ -0,0 +1,26 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// GenesisState - all distribution state that must be provided at genesis +type GenesisState struct { + FeePool FeePool `json:"fee_pool"` + ValidatorDistInfos []ValidatorDistInfo `json:"validator_dist_infos"` + DelegatorDistInfos []DelegatorDistInfo `json:"delegator_dist_infos"` + DelegatorDistInfos []sdk.AccAddress `json:"delegator_dist_infos"` +} + +func NewGenesisState(feePool FeePool, vdis []ValidatorDistInfo, ddis []DelegatorDistInfo) GenesisState { + return GenesisState{ + FeePool: feePool, + ValidatorDistInfos: vdis, + DelegatorDistInfos: ddis, + } +} + +// get raw genesis raw message for testing +func DefaultGenesisState() GenesisState { + return GenesisState{ + FeePool: InitialFeePool(), + } +} diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 4a1b1f86d0..8ca4c03872 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -4,13 +4,13 @@ import sdk "github.com/cosmos/cosmos-sdk/types" // distribution info for a particular validator type ValidatorDistInfo struct { - OperatorAddr sdk.ValAddress + OperatorAddr sdk.ValAddress `json:"operator_addr"` - GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool - Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward) - PoolCommission DecCoins // commission collected by this validator (pending withdrawal) + GlobalWithdrawalHeight int64 `json:"global_withdrawal_height"` // last height this validator withdrew from the global pool + Pool DecCoins `json:"pool"` // rewards owed to delegators, commission has already been charged (includes proposer reward) + PoolCommission DecCoins `json:"pool_commission"` // commission collected by this validator (pending withdrawal) - DelAccum TotalAccum `json:"dek_accum"` // total proposer pool accumulation factor held by delegators + DelAccum TotalAccum `json:"del_accum"` // total proposer pool accumulation factor held by delegators } // update total delegator accumululation From 24e43b9869bea32a919fbf31a0af61c1a119cc58 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 18 Sep 2018 12:46:04 -0400 Subject: [PATCH 16/99] hookwork --- cmd/gaia/app/app.go | 40 ++++++++++++- cmd/gaia/app/genesis.go | 3 + types/stake.go | 13 ++-- x/distribution/genesis.go | 6 +- x/distribution/hooks.go | 95 ++++++++++++++---------------- x/distribution/keeper/validator.go | 6 +- x/stake/keeper/keeper.go | 16 ++--- 7 files changed, 105 insertions(+), 74 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 39cb596946..3213029e04 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -96,7 +96,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio auth.ProtoBaseAccount, // prototype ) - // add handlers + // add handlers and hooks app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) @@ -208,6 +208,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci slashing.InitGenesis(ctx, app.slashingKeeper, 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 @@ -235,6 +236,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) @@ -244,3 +246,39 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val validators = stake.WriteValidators(ctx, app.stakeKeeper) return appState, validators, nil } + +//______________________________________________________________________________________________ + +// Combine Staking Hooks +type Hooks struct { + dh distr.Hooks + sh slashing.Hooks +} + +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) OnValidatorBeginBonded(ctx sdk.Context, addr sdk.ConsAddress) { + h.sh.OnValidatorBeginBonding(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) +} diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 84f0ea7fa7..d2a567fa4b 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/stake" + distr "github.com/cosmos/cosmos-sdk/x/stake" stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/spf13/pflag" @@ -34,6 +35,7 @@ var ( type GenesisState struct { Accounts []GenesisAccount `json:"accounts"` StakeData stake.GenesisState `json:"stake"` + DistrData distr.GenesisState `json:"distr_data"` GovData gov.GenesisState `json:"gov"` } @@ -194,6 +196,7 @@ func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisStat genesisState = GenesisState{ Accounts: genaccs, StakeData: stakeData, + DistrData: distr.DefaultGenesisState(), GovData: gov.DefaultGenesisState(), } return diff --git a/types/stake.go b/types/stake.go index 54fd564afd..68257689d2 100644 --- a/types/stake.go +++ b/types/stake.go @@ -107,18 +107,17 @@ type DelegationSet interface { // state. The second keeper must implement this interface, which then the // staking keeper can call. +// TODO refactor event hooks out to the receiver modules + // event hooks for staking validator object -type ValidatorHooks interface { - OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created - OnValidatorBondModified(ctx Context, address ValAddress) // Must be called when a validator's bond amount is modified - OnValidatorRemoved(ctx Context, address ValAddress) // Must be called when a validator is deleted +type StakingHooks interface { + OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created + OnValidatorCommissionChange(ctx Context, address ValAddress) // Must be called when a validator's commission is modified + OnValidatorRemoved(ctx Context, address ValAddress) // Must be called when a validator is deleted OnValidatorBonded(ctx Context, address ConsAddress) // Must be called when a validator is bonded OnValidatorBeginUnbonding(ctx Context, address ConsAddress) // Must be called when a validator begins unbonding -} -// event hooks for staking delegator object -type DelegatorHooks interface { OnDelegationCreated(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is created OnDelegationSharesModified(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation's shares are modified OnDelegationRemoved(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is removed diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index 1ff4a06d6f..f377750f8e 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -1,8 +1,6 @@ package distribution import ( - abci "github.com/tendermint/tendermint/abci/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" ) @@ -13,7 +11,7 @@ import ( // addition, it also sets any delegations found in data. Finally, it updates // the bonded validators. // Returns final validator set after applying all declaration and delegations -func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res []abci.Validator, err error) { +func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { keeper.SetFeePool(ctx, data.FeePool) for _, vdi := range data.ValidatorDistInfos { @@ -25,8 +23,6 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ for _, dw := range data.DelegatorWithdrawAddrs { keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr) } - - return } // WriteGenesis returns a GenesisState for a given context and keeper. The diff --git a/x/distribution/hooks.go b/x/distribution/hooks.go index 9a6f7cfbf9..3a4d8fbd2d 100644 --- a/x/distribution/hooks.go +++ b/x/distribution/hooks.go @@ -1,6 +1,9 @@ package distribution -import "github.com/cosmos/cosmos-sdk/x/distribution/types" +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution/types" +) /* ## Create or modify delegation distribution @@ -43,15 +46,9 @@ func (k Keeper) onValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { k.SetValidatorDistInfo(ctx, vdi) } -// Withdrawal all distubution rewards // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX -func (k Keeper) onValidatorBondModified(ctx sdk.Context, addr sdk.ValAddress) { - slashingPeriod := ValidatorSlashingPeriod{ - ValidatorAddr: address, - StartHeight: ctx.BlockHeight(), - EndHeight: 0, - SlashedSoFar: sdk.ZeroDec(), - } - k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) +// 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 @@ -61,60 +58,56 @@ func (k Keeper) onValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { //_________________________________________________________________________________________ -// Create a new validator distribution record -func (k Keeper) onDelegationCreated(ctx sdk.Context, address sdk.ConsAddress) { - slashingPeriod := ValidatorSlashingPeriod{ - ValidatorAddr: address, - StartHeight: ctx.BlockHeight(), - EndHeight: 0, - SlashedSoFar: sdk.ZeroDec(), +// Create a new delegator distribution record +func (k Keeper) onDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, + valAddr sdk.ValAddress) { + + ddi := types.DelegatorDistInfo{ + DelegatorAddr: delAddr, + ValOperatorAddr: valAddr, + WithdrawalHeight: ctx.BlockHeight(), } - k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) + k.SetDelegatorDistInfo(ctx, 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.RemoveDelegatorDistInfo(ctx, delAddr, valAddr) } //_________________________________________________________________________________________ -// Wrapper struct for sdk.ValidatorHooks -type ValidatorHooks struct { +// Wrapper struct +type Hooks struct { k Keeper } -var _ sdk.ValidatorHooks = ValidatorHooks{} - // nolint func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { return ValidatorHooks{k} } -func (v ValidatorHooks) OnValidatorCreated(ctx sdk.Context, addr sdk.VlAddress) { - v.k.OnValidatorCreated(ctx, address) +func (h Hooks) OnValidatorCreated(ctx sdk.Context, addr sdk.VlAddress) { + v.k.onValidatorCreated(ctx, address) } -func (v ValidatorHooks) OnValidatorBondModified(ctx sdk.Context, addr sdk.ValAddress) { - v.k.OnValidatorBondModified(ctx, address) +func (h Hooks) OnValidatorCommissionChange(ctx sdk.Context, addr sdk.ValAddress) { + v.k.onValidatorCommissionChange(ctx, address) } -func (v ValidatorHooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { - v.k.OnValidatorRemoved(ctx, address) +func (h Hooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { + v.k.onValidatorRemoved(ctx, address) } -func (v ValidatorHooks) OnValidatorBonded(_ sdk.Context, _ sdk.ConsAddress) {} -func (v ValidatorHooks) OnValidatorBeginBonded(_ sdk.Context, _ sdk.ConsAddress) {} - -//_________________________________________________________________________________________ - -// Wrapper struct for sdk.DelegationHooks -type DelegationHooks struct { - k Keeper +func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + h.k.onDelegationCreated(ctx, delAddr, valAddr) } - -var _ sdk.DelegationHooks = DelegationHooks{} - -// nolint -func (k Keeper) DelegationHooks() sdk.DelegationHooks { return DelegationHooks{k} } -func (d DelegationHooks) OnDelegatoinCreated(ctx sdk.Context, - delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - d.k.OnDelegatoinCreated(ctx, address) +func (h Hooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + d.k.onDelegationSharesModified(ctx, delAddr, valAddr) } -func (d DelegationHooks) OnDelegationSharesModified(ctx sdk.Context, - delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - d.k.OnDelegationSharesModified(ctx, address) -} -func (d DelegationHooks) OnDelegationRemoved(ctx sdk.Context, - delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - d.k.OnDelegationRemoved(ctx, address) +func (h Hooks) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + h.k.onDelegationRemoved(ctx, delAddr, valAddr) } diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 7de71300cd..ce73b22719 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -35,12 +35,13 @@ func (k Keeper) RemoveValidatorDistInfo(ctx sdk.Context, valAddr sdk.ValAddress) // withdrawal all the validator rewards including the commission func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, - operatorAddr sdk.ValAddress, withdrawAddr sdk.AccAddress) { + operatorAddr sdk.ValAddress) { // withdraw self-delegation height := ctx.BlockHeight() validator := k.GetValidator(ctx, operatorAddr) - withdraw := k.GetDelegatorRewardsAll(ctx, validator.OperatorAddr, height) + accAddr := sdk.AccAddress{operatorAddr.Bytes()} + withdraw := k.GetDelegatorRewardsAll(ctx, accAddr, height) // withdrawal validator commission rewards pool := k.stakeKeeper.GetPool(ctx) @@ -51,5 +52,6 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, withdraw = withdraw.Add(commission) k.SetFeePool(feePool) + withdrawAddr := k.GetDelegatorWithdrawAddr(accAddr) k.coinKeeper.AddCoins(withdrawAddr, withdraw.TruncateDecimal()) } diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index a3754f7504..b9db3cbfb1 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -10,11 +10,11 @@ import ( // keeper of the stake store type Keeper struct { - storeKey sdk.StoreKey - storeTKey sdk.StoreKey - cdc *codec.Codec - bankKeeper bank.Keeper - validatorHooks sdk.ValidatorHooks + storeKey sdk.StoreKey + storeTKey sdk.StoreKey + cdc *codec.Codec + bankKeeper bank.Keeper + hooks sdk.StakingHooks // codespace codespace sdk.CodespaceType @@ -33,11 +33,11 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespa } // Set the validator hooks -func (k Keeper) WithValidatorHooks(v sdk.ValidatorHooks) Keeper { - if k.validatorHooks != nil { +func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { + if k.stakingHooks != nil { panic("cannot set validator hooks twice") } - k.validatorHooks = v + k.validatorHooks = sh return k } From bb9e647f9539bef05b82162100ab1d772b0274a7 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 18 Sep 2018 17:54:28 -0400 Subject: [PATCH 17/99] add in basic commission stuff --- cmd/gaia/app/app.go | 14 +++++++++---- x/distribution/hooks.go | 31 +++------------------------- x/slashing/hooks.go | 23 ++++++++++----------- x/stake/keeper/validator.go | 40 +++++++++++++++++++++++++++++++++++++ x/stake/types/errors.go | 8 ++++++++ 5 files changed, 72 insertions(+), 44 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 3213029e04..5b1dbd6722 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -96,17 +96,19 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio auth.ProtoBaseAccount, // prototype ) - // add handlers and hooks + // add handlers app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.distrKeeper = distr.NewKeeper(app.cdc, app.keyDistr, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) - app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks()) app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) + // register the staking hooks + app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(NewHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks())) + // register message routes app.Router(). AddRoute("bank", bank.NewHandler(app.bankKeeper)). @@ -249,10 +251,14 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val //______________________________________________________________________________________________ -// Combine Staking Hooks +// Combined Staking Hooks type Hooks struct { dh distr.Hooks - sh slashing.Hooks + sh slashing.ValidatorHooks +} + +func NewHooks(dh distr.Hooks, sh slashing.ValidatorHooks) Hooks { + return Hooks{dh, sh} } var _ sdk.StakingHooks = Hooks{} diff --git a/x/distribution/hooks.go b/x/distribution/hooks.go index 3a4d8fbd2d..97be985f29 100644 --- a/x/distribution/hooks.go +++ b/x/distribution/hooks.go @@ -5,33 +5,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/distribution/types" ) -/* -## Create or modify delegation distribution - - - triggered-by: `stake.TxDelegate`, `stake.TxBeginRedelegate`, `stake.TxBeginUnbonding` - -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. - -## Commission rate change - - - triggered-by: `stake.TxEditValidator` - -If a validator changes its commission rate, all commission on fees must be -simultaneously withdrawn using the transaction `TxWithdrawValidator`. -Additionally the change and associated height must be recorded in a -`ValidatorUpdate` state record. - -## Change in Validator State - - - triggered-by: `stake.Slash`, `stake.UpdateValidator` - -Whenever a validator is slashed or enters/leaves the validator group all of the -validator entitled reward tokens must be simultaneously withdrawn from -`Global.Pool` and added to `ValidatorDistInfo.Pool`. -*/ - // Create a new validator distribution record func (k Keeper) onValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { @@ -91,8 +64,10 @@ type Hooks struct { k Keeper } +// New Validator Hooks +func (k Keeper) ValidatorHooks() Hooks { return Hooks{k} } + // nolint -func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { return ValidatorHooks{k} } func (h Hooks) OnValidatorCreated(ctx sdk.Context, addr sdk.VlAddress) { v.k.onValidatorCreated(ctx, address) } diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index f5f3cc48c3..8d519c7945 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -22,25 +22,24 @@ func (k Keeper) onValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddre k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) } -// Wrapper struct for sdk.ValidatorHooks -type ValidatorHooks struct { +//_________________________________________________________________________________________ + +// Wrapper struct +type Hooks struct { k Keeper } -// Assert implementation -var _ sdk.ValidatorHooks = ValidatorHooks{} - -// Return a sdk.ValidatorHooks interface over the wrapper struct -func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { - return ValidatorHooks{k} +// Return the wrapper struct +func (k Keeper) Hooks() Hooks { + return Hooks{k} } // Implements sdk.ValidatorHooks -func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { - v.k.onValidatorBonded(ctx, address) +func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { + h.k.onValidatorBonded(ctx, address) } // Implements sdk.ValidatorHooks -func (v ValidatorHooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { - v.k.onValidatorBeginUnbonding(ctx, address) +func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { + h.k.onValidatorBeginUnbonding(ctx, address) } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index bef723c4da..2e5191b2dd 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -669,6 +669,11 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // remove the validator record and associated indexes func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { + // call the hook if present + if k.validatorHooks != nil { + k.validatorHooks.OnValidatorRemoved(ctx, validator.OperatorAddr) + } + // first retrieve the old validator record validator, found := k.GetValidator(ctx, address) if !found { @@ -728,3 +733,38 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr)) } } + +//__________________________________________________________________________ + +// get a single validator +func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { + store := ctx.KVStore(k.storeKey) + + // call the hook if present + if k.validatorHooks != nil { + k.validatorHooks.OnValidatorCommissionChange(ctx, validator.OperatorAddr) + } + + validator, found := k.GetValidator(addr) + + // check for errors + switch { + case !found: + return types.ErrNoValidatorFound(k.Codespace()) + case newCommission.LT(sdk.ZeroDec()): + return types.ErrCommissionNegative(k.Codespace()) + case newCommission.GT(sdk.OnedDec()): + return types.ErrCommissionHuge(k.Codespace()) + case newCommission.GT(validator.CommissionMax): + return types.ErrCommissionBeyondMax(k.Codespace()) + //case rateChange(Commission) > CommissionMaxChange: // XXX XXX XXX TODO implementation + //return types.ErrCommissionPastRate(k.Codespace()) + } + + // TODO adjust all the commission terms appropriately + + validator.Commission = newCommission + + k.SetValidator(addr, validator) + return nil +} diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 366012bbfb..541ad3d7b9 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -65,6 +65,14 @@ func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%") } +func ErrCommissionBeyondMax(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than preset commission maximum") +} + +func ErrCommissionPastRate(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission change is greater than the commission rate, please wait before changing your commission more") +} + func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil") } From a18b89539aef9c0a55b02df2c0f770d9209c3ecc Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 18 Sep 2018 23:30:00 -0400 Subject: [PATCH 18/99] handler, tags, msgs, codec --- docs/spec/distribution/transactions.md | 27 ++-- x/distribution/codec.go | 10 -- x/distribution/handler.go | 83 ++++++++++++ x/distribution/keeper/validator.go | 3 +- x/distribution/tags/tags.go | 17 +++ x/distribution/types/codec.go | 24 ++++ x/distribution/types/msg.go | 175 +++++++++++++++++++++++++ x/stake/handler.go | 12 ++ x/stake/keeper/delegation.go | 16 +++ x/stake/keeper/keeper.go | 14 +- x/stake/keeper/validator.go | 16 +-- x/stake/types/codec.go | 3 +- 12 files changed, 356 insertions(+), 44 deletions(-) delete mode 100644 x/distribution/codec.go create mode 100644 x/distribution/tags/tags.go create mode 100644 x/distribution/types/codec.go create mode 100644 x/distribution/types/msg.go diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 47b11165a0..c8c1080ad4 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -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) @@ -41,16 +40,15 @@ func GetDelegatorRewardsAll(delegatorAddr sdk.AccAddress, height int64) DecCoins 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) @@ -72,19 +70,18 @@ func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.Acc ``` -## 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) diff --git a/x/distribution/codec.go b/x/distribution/codec.go deleted file mode 100644 index e3bf8d49ae..0000000000 --- a/x/distribution/codec.go +++ /dev/null @@ -1,10 +0,0 @@ -package distribution - -import ( - "github.com/cosmos/cosmos-sdk/codec" -) - -// XXX TODO -// Register concrete types on codec codec -func RegisterCodec(cdc *codec.Codec) { -} diff --git a/x/distribution/handler.go b/x/distribution/handler.go index d2ef538fb1..1ae74ac78e 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -1 +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.MsgModifyWithdrawAddress: + 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.MsgModifyWithdrawAddress, k keeper.Keeper) sdk.Result { + + k.SetDelegatorWithdrawAddr(ctx, msg.DelegatorAddr, msg.WithdrawAddress) + + 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, + } +} diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index ce73b22719..b8dece32cf 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -34,8 +34,7 @@ func (k Keeper) RemoveValidatorDistInfo(ctx sdk.Context, valAddr sdk.ValAddress) } // withdrawal all the validator rewards including the commission -func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, - operatorAddr sdk.ValAddress) { +func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.ValAddress) { // withdraw self-delegation height := ctx.BlockHeight() diff --git a/x/distribution/tags/tags.go b/x/distribution/tags/tags.go new file mode 100644 index 0000000000..dd55ba2369 --- /dev/null +++ b/x/distribution/tags/tags.go @@ -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 +) diff --git a/x/distribution/types/codec.go b/x/distribution/types/codec.go new file mode 100644 index 0000000000..84fee76a3a --- /dev/null +++ b/x/distribution/types/codec.go @@ -0,0 +1,24 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +// XXX TODO +// Register concrete types on codec codec +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterConcrete(MsgWithdrawDelegationRewardsAll{}, "cosmos-sdk/MsgWithdrawDelegationRewardsAll", nil) + cdc.RegisterConcrete(MsgWithdrawDelegationReward{}, "cosmos-sdk/MsgWithdrawDelegationReward", nil) + cdc.RegisterConcrete(MsgWithdrawValidatorRewardsAll{}, "cosmos-sdk/MsgWithdrawValidatorRewardsAll", nil) + cdc.RegisterConcrete(MsgModifyWithdrawAddress{}, "cosmos-sdk/MsgModifyWithdrawAddress", nil) +} + +// generic sealed codec to be used throughout sdk +var MsgCdc *codec.Codec + +func init() { + cdc := codec.New() + RegisterCodec(cdc) + codec.RegisterCrypto(cdc) + MsgCdc = cdc.Seal() +} diff --git a/x/distribution/types/msg.go b/x/distribution/types/msg.go new file mode 100644 index 0000000000..3808752f1d --- /dev/null +++ b/x/distribution/types/msg.go @@ -0,0 +1,175 @@ +//nolint +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// name to identify transaction types +const MsgType = "distr" + +// Verify interface at compile time +var _, _ sdk.Msg = &MsgModifyWithdrawAddress{}, &MsgWithdrawDelegatorRewardsAll{} +var _, _ sdk.Msg = &MsgWithdrawDelegationReward{}, &MsgWithdrawValidatorRewardsAll{} + +//______________________________________________________________________ + +// msg struct for changing the withdraw address for a delegator (or validator self-delegation) +type MsgModifyWithdrawAddress struct { + DelegatorAddr sdk.AccAddress `json:"delegator_addr"` + WithdrawAddr sdk.AccAddress `json:"delegator_addr"` +} + +func NewMsgModifyWithdrawAddress(delAddr, withdrawAddr sdk.AccAddress) MsgModifyWithdrawAddress { + return MsgModifyWithdrawAddress{ + DelegatorAddr: delAddr, + WithdrawAddr: withdrawAddr, + } +} + +func (msg MsgModifyWithdrawAddress) Type() string { return MsgType } +func (msg MsgModifyWithdrawAddress) Name() string { return "withdraw_delegation_rewards_all" } + +// Return address that must sign over msg.GetSignBytes() +func (msg MsgModifyWithdrawAddress) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{sdk.AccAddress(msg.DelegatorAddr)} +} + +// get the bytes for the message signer to sign on +func (msg MsgModifyWithdrawAddress) GetSignBytes() []byte { + b, err := MsgCdc.MarshalJSON(msg) + if err != nil { + panic(err) + } + return sdk.MustSortJSON(b) +} + +// quick validity check +func (msg MsgModifyWithdrawAddress) ValidateBasic() sdk.Error { + if msg.DelegatorAddr == nil { + return ErrNilDelegatorAddr(DefaultCodespace) + } + if msg.WithdrawAddr == nil { + return ErrNilWithdrawAddr(DefaultCodespace) + } + return nil +} + +//______________________________________________________________________ + +// msg struct for delegation withdraw for all of the delegator's delegations +type MsgWithdrawDelegatorRewardsAll struct { + DelegatorAddr sdk.AccAddress `json:"delegator_addr"` +} + +func NewMsgWithdrawDelegationRewardsAll(delAddr sdk.AccAddress) MsgWithdrawDelegatorRewardsAll { + return MsgWithdrawDelegatorRewardsAll{ + DelegatorAddr: delAddr, + } +} + +func (msg MsgWithdrawDelegatorRewardsAll) Type() string { return MsgType } +func (msg MsgWithdrawDelegatorRewardsAll) Name() string { return "withdraw_delegation_rewards_all" } + +// Return address that must sign over msg.GetSignBytes() +func (msg MsgWithdrawDelegatorRewardsAll) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{sdk.AccAddress(msg.DelegatorAddr)} +} + +// get the bytes for the message signer to sign on +func (msg MsgWithdrawDelegatorRewardsAll) GetSignBytes() []byte { + b, err := MsgCdc.MarshalJSON(msg) + if err != nil { + panic(err) + } + return sdk.MustSortJSON(b) +} + +// quick validity check +func (msg MsgWithdrawDelegatorRewardsAll) ValidateBasic() sdk.Error { + if msg.DelegatorAddr == nil { + return ErrNilDelegatorAddr(DefaultCodespace) + } + return nil +} + +//______________________________________________________________________ + +// msg struct for delegation withdraw from a single validator +type MsgWithdrawDelegationReward struct { + DelegatorAddr sdk.AccAddress `json:"delegator_addr"` + ValidatorAddr sdk.ValAddress `json:"validator_addr"` +} + +func NewMsgWithdrawDelegationReward(delAddr sdk.AccAddress, valAddr sdk.ValAddress) MsgWithdrawDelegationReward { + return MsgWithdrawDelegationReward{ + DelegatorAddr: delAddr, + ValidatorAddr: valAddr, + } +} + +func (msg MsgWithdrawDelegationReward) Type() string { return MsgType } +func (msg MsgWithdrawDelegationReward) Name() string { return "withdraw_delegation_reward" } + +// Return address that must sign over msg.GetSignBytes() +func (msg MsgWithdrawDelegationReward) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{sdk.AccAddress(msg.DelegatorAddr)} +} + +// get the bytes for the message signer to sign on +func (msg MsgWithdrawDelegationReward) GetSignBytes() []byte { + b, err := MsgCdc.MarshalJSON(msg) + if err != nil { + panic(err) + } + return sdk.MustSortJSON(b) +} + +// quick validity check +func (msg MsgWithdrawDelegationReward) ValidateBasic() sdk.Error { + if msg.DelegatorAddr == nil { + return ErrNilDelegatorAddr(DefaultCodespace) + } + if msg.ValidatorAddr == nil { + return ErrNilValidatorAddr(DefaultCodespace) + } + return nil +} + +//______________________________________________________________________ + +// msg struct for validator withdraw +type MsgWithdrawValidatorRewardsAll struct { + ValidatorAddr sdk.ValAddress `json:"validator_addr"` +} + +func NewMsgWithdrawValidatorRewardsAll(valAddr sdk.ValAddress) MsgWithdrawValidatorRewardsAll { + return MsgWithdrawValidatorRewardsAll{ + ValidatorAddr: valAddr, + } +} + +func (msg MsgWithdrawValidatorRewardsAll) Type() string { return MsgType } +func (msg MsgWithdrawValidatorRewardsAll) Name() string { return "withdraw_validator_rewards_all" } + +// Return address that must sign over msg.GetSignBytes() +func (msg MsgWithdrawValidatorRewardsAll) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{sdk.AccAddress(msg.ValidatorAddr.Bytes())} +} + +// get the bytes for the message signer to sign on +func (msg MsgWithdrawValidatorRewardsAll) GetSignBytes() []byte { + b, err := MsgCdc.MarshalJSON(msg) + if err != nil { + panic(err) + } + return sdk.MustSortJSON(b) +} + +// quick validity check +func (msg MsgWithdrawValidatorRewardsAll) ValidateBasic() sdk.Error { + if msg.ValidatorAddr == nil { + return ErrNilValidatorAddr(DefaultCodespace) + } + return nil +} diff --git a/x/stake/handler.go b/x/stake/handler.go index e7641393db..e1fb3edc02 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -87,6 +87,13 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k return err.Result() } + // call the hook if present + if k.validatorHooks != nil { + k.validatorHooks.OnValidatorCreated(ctx, validator.OperatorAddr) + accAddr := sdk.AccAddress{validator.OperatorAddr} + k.validatorHooks.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) + } + tags := sdk.NewTags( tags.Action, tags.ActionCreateValidator, tags.DstValidator, []byte(msg.ValidatorAddr.String()), @@ -146,6 +153,11 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) return err.Result() } + // call the hook if present + if k.validatorHooks != nil { + k.validatorHooks.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) + } + tags := sdk.NewTags( tags.Action, tags.ActionDelegate, tags.Delegator, []byte(msg.DelegatorAddr.String()), diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index ad2ab86f02..78e16de828 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -84,6 +84,12 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { // remove a delegation from store func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { + + // call the hook if present + if k.hooks != nil { + k.hooks.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr) + } + store := ctx.KVStore(k.storeKey) store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) } @@ -293,6 +299,11 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co k.SetDelegation(ctx, delegation) k.UpdateValidator(ctx, validator) + // call the hook if present + if k.hooks != nil { + k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) + } + return } @@ -351,6 +362,11 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA k.RemoveValidator(ctx, validator.OperatorAddr) } + // call the hook if present + if k.hooks != nil { + k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) + } + return amount, nil } diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index b9db3cbfb1..cb76a9562a 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -22,12 +22,12 @@ type Keeper struct { func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ - storeKey: key, - storeTKey: tkey, - cdc: cdc, - bankKeeper: ck, - validatorHooks: nil, - codespace: codespace, + storeKey: key, + storeTKey: tkey, + cdc: cdc, + bankKeeper: ck, + hooks: nil, + codespace: codespace, } return keeper } @@ -37,7 +37,7 @@ func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { if k.stakingHooks != nil { panic("cannot set validator hooks twice") } - k.validatorHooks = sh + k.hooks = sh return k } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 2e5191b2dd..27f2547fd9 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -623,8 +623,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) // call the unbond hook if present - if k.validatorHooks != nil { - k.validatorHooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) + if k.hooks != nil { + k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) } // return updated validator @@ -658,8 +658,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI) // call the bond hook if present - if k.validatorHooks != nil { - k.validatorHooks.OnValidatorBonded(ctx, validator.ConsAddress()) + if k.hooks != nil { + k.hooks.OnValidatorBonded(ctx, validator.ConsAddress()) } // return updated validator @@ -670,8 +670,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { // call the hook if present - if k.validatorHooks != nil { - k.validatorHooks.OnValidatorRemoved(ctx, validator.OperatorAddr) + if k.hooks != nil { + k.hooks.OnValidatorRemoved(ctx, validator.OperatorAddr) } // first retrieve the old validator record @@ -741,8 +741,8 @@ func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, store := ctx.KVStore(k.storeKey) // call the hook if present - if k.validatorHooks != nil { - k.validatorHooks.OnValidatorCommissionChange(ctx, validator.OperatorAddr) + if k.hooks != nil { + k.hooks.OnValidatorCommissionChange(ctx, validator.OperatorAddr) } validator, found := k.GetValidator(addr) diff --git a/x/stake/types/codec.go b/x/stake/types/codec.go index aa4f64f8a2..4921cdf8e2 100644 --- a/x/stake/types/codec.go +++ b/x/stake/types/codec.go @@ -22,6 +22,5 @@ func init() { cdc := codec.New() RegisterCodec(cdc) codec.RegisterCrypto(cdc) - MsgCdc = cdc - //MsgCdc = cdc.Seal() //TODO use when upgraded to go-amino 0.9.10 + MsgCdc = cdc.Seal() } From e3cf4f606ea9c24e4ecaf855e62ccebbecf1ac31 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 00:00:48 -0400 Subject: [PATCH 19/99] cli transactions --- x/distribution/client/cli/tx.go | 95 +++++++++++++++++++++++---------- x/stake/client/cli/flags.go | 8 +-- 2 files changed, 70 insertions(+), 33 deletions(-) diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index b794d08cb4..ca10471c64 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -2,6 +2,7 @@ package cli import ( + "fmt" "os" "github.com/cosmos/cosmos-sdk/client/context" @@ -13,64 +14,100 @@ import ( wire "github.com/tendermint/go-wire" ) -type TxWithdrawDelegationRewardsAll struct { - delegatorAddr sdk.AccAddress - withdrawAddr sdk.AccAddress // address to make the withdrawal to -} - -type TxWithdrawDelegationReward struct { - delegatorAddr sdk.AccAddress - validatorAddr sdk.AccAddress - withdrawAddr sdk.AccAddress // address to make the withdrawal to -} - -type TxWithdrawValidatorRewardsAll struct { - operatorAddr sdk.AccAddress // validator address to withdraw from - withdrawAddr sdk.AccAddress // address to make the withdrawal to -} - var ( flagOnlyFromValidator = "only-from-validator" flagIsValidator = "is-validator" ) -// GetCmdDelegate implements the delegate command. +// command to withdraw rewards func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "withdraw-rewards [delegator]", - Short: "withdraw rewards for all delegations", + 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) + } + txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) - amount, err := sdk.ParseCoin(viper.GetString(FlagAmount)) - if err != nil { - return err + var msg sdk.Msg + switch { + case isVal: + addr, err := cliCtx.GetFromAddress() + if err != nil { + return err + } + valAddr := sdk.ValAddress{addr.Bytes()} + msg := distr.NewMsgWithdrawValidatorRewardsAll(valAddr) + case onlyFromVal != "": + delAddr, err := cliCtx.GetFromAddress() + if err != nil { + return err + } + + valAddr, err := sdk.ValAddressFromBech32(onlyFromVal) + if err != nil { + return err + } + + msg := distr.NewMsgWithdrawDelegationReward(delAddr, valAddr) + default: + delAddr, err := cliCtx.GetFromAddress() + if err != nil { + return err + } + msg := distr.NewMsgWithdrawDelegationRewardsAll(delAddr) } + // build and sign the transaction, then broadcast to Tendermint + return utils.SendTx(txCtx, 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 GetCmdWithdrawDelegationRewardsAll(cdc *wire.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 { + + txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + cliCtx := context.NewCLIContext(). + WithCodec(cdc). + WithLogger(os.Stdout). + WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) + delAddr, err := cliCtx.GetFromAddress() if err != nil { return err } - valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator)) + withdrawAddr, err := sdk.AccAddressFromBech32(args[0]) if err != nil { return err } - msg := distr.NewMsgDelegate(delAddr, valAddr, amount) + msg := distr.NewMsgModifyWithdrawAddress(delAddr, withdrawAddr) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) }, } - - // TODO add flags for "is-validator", "only-for-validator" - cmd.Flags().String(flagOnlyFromValidator, "", "Only withdraw from this validator address") - cmd.Flags().Bool(flagIsValidator, false, "Also withdraw validator's commission") - return cmd } diff --git a/x/stake/client/cli/flags.go b/x/stake/client/cli/flags.go index d0e83ab3c6..4c36be0b54 100644 --- a/x/stake/client/cli/flags.go +++ b/x/stake/client/cli/flags.go @@ -48,8 +48,8 @@ func init() { fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)") fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website") fsDescriptionEdit.String(FlagDetails, types.DoNotModifyDesc, "optional details") - fsValidator.String(FlagAddressValidator, "", "hex address of the validator") - fsDelegator.String(FlagAddressDelegator, "", "hex address of the delegator") - fsRedelegation.String(FlagAddressValidatorSrc, "", "hex address of the source validator") - fsRedelegation.String(FlagAddressValidatorDst, "", "hex address of the destination validator") + fsValidator.String(FlagAddressValidator, "", "bech address of the validator") + fsDelegator.String(FlagAddressDelegator, "", "bech address of the delegator") + fsRedelegation.String(FlagAddressValidatorSrc, "", "bech address of the source validator") + fsRedelegation.String(FlagAddressValidatorDst, "", "bech address of the destination validator") } From 73c5fdf1f9b7c2ae48af7bffb964eb5a18295631 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 00:10:33 -0400 Subject: [PATCH 20/99] more cli related --- cmd/gaia/cmd/gaiacli/main.go | 14 ++++++++++++++ x/distribution/client/cli/tx.go | 4 ++-- x/distribution/types/codec.go | 1 - x/distribution/types/msg.go | 18 +++++++++--------- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index c216bb2eb0..166359201a 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -101,6 +101,20 @@ func main() { stakeCmd, ) + //Add distribution commands + distrCmd := &cobra.Command{ + Use: "distribution", + Short: "withdraw rewards for delegation and validation", + } + distrCmd.AddCommand( + client.PostCommands( + stakecmd.GetCmdWithdrawDelegationRewardsAll(cdc), + stakecmd.GetCmdSetWithdrawAddr(cdc), + )...) + rootCmd.AddCommand( + distrCmd, + ) + //Add stake commands govCmd := &cobra.Command{ Use: "gov", diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index ca10471c64..f9cd858bb1 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -80,7 +80,7 @@ func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { } // GetCmdDelegate implements the delegate command. -func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { +func GetCmdSetWithdrawAddr(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "set-withdraw-addr [withdraw-addr]", Short: "change the default withdraw address for rewards associated with an address", @@ -103,7 +103,7 @@ func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { return err } - msg := distr.NewMsgModifyWithdrawAddress(delAddr, withdrawAddr) + msg := distr.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) diff --git a/x/distribution/types/codec.go b/x/distribution/types/codec.go index 84fee76a3a..ece45a004f 100644 --- a/x/distribution/types/codec.go +++ b/x/distribution/types/codec.go @@ -4,7 +4,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" ) -// XXX TODO // Register concrete types on codec codec func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(MsgWithdrawDelegationRewardsAll{}, "cosmos-sdk/MsgWithdrawDelegationRewardsAll", nil) diff --git a/x/distribution/types/msg.go b/x/distribution/types/msg.go index 3808752f1d..ce77285c15 100644 --- a/x/distribution/types/msg.go +++ b/x/distribution/types/msg.go @@ -9,34 +9,34 @@ import ( const MsgType = "distr" // Verify interface at compile time -var _, _ sdk.Msg = &MsgModifyWithdrawAddress{}, &MsgWithdrawDelegatorRewardsAll{} +var _, _ sdk.Msg = &MsgSetWithdrawAddress{}, &MsgWithdrawDelegatorRewardsAll{} var _, _ sdk.Msg = &MsgWithdrawDelegationReward{}, &MsgWithdrawValidatorRewardsAll{} //______________________________________________________________________ // msg struct for changing the withdraw address for a delegator (or validator self-delegation) -type MsgModifyWithdrawAddress struct { +type MsgSetWithdrawAddress struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` WithdrawAddr sdk.AccAddress `json:"delegator_addr"` } -func NewMsgModifyWithdrawAddress(delAddr, withdrawAddr sdk.AccAddress) MsgModifyWithdrawAddress { - return MsgModifyWithdrawAddress{ +func NewMsgSetWithdrawAddress(delAddr, withdrawAddr sdk.AccAddress) MsgSetWithdrawAddress { + return MsgSetWithdrawAddress{ DelegatorAddr: delAddr, WithdrawAddr: withdrawAddr, } } -func (msg MsgModifyWithdrawAddress) Type() string { return MsgType } -func (msg MsgModifyWithdrawAddress) Name() string { return "withdraw_delegation_rewards_all" } +func (msg MsgSetWithdrawAddress) Type() string { return MsgType } +func (msg MsgSetWithdrawAddress) Name() string { return "withdraw_delegation_rewards_all" } // Return address that must sign over msg.GetSignBytes() -func (msg MsgModifyWithdrawAddress) GetSigners() []sdk.AccAddress { +func (msg MsgSetWithdrawAddress) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{sdk.AccAddress(msg.DelegatorAddr)} } // get the bytes for the message signer to sign on -func (msg MsgModifyWithdrawAddress) GetSignBytes() []byte { +func (msg MsgSetWithdrawAddress) GetSignBytes() []byte { b, err := MsgCdc.MarshalJSON(msg) if err != nil { panic(err) @@ -45,7 +45,7 @@ func (msg MsgModifyWithdrawAddress) GetSignBytes() []byte { } // quick validity check -func (msg MsgModifyWithdrawAddress) ValidateBasic() sdk.Error { +func (msg MsgSetWithdrawAddress) ValidateBasic() sdk.Error { if msg.DelegatorAddr == nil { return ErrNilDelegatorAddr(DefaultCodespace) } From de4071f69354e873260b9c7a97a1bc641a0ce076 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 00:42:05 -0400 Subject: [PATCH 21/99] aliases, errors --- cmd/gaia/app/genesis.go | 2 +- x/distribution/alias.go | 74 +++++++++++++++++++++++++++++ x/distribution/genesis.go | 7 +-- x/distribution/keeper/allocation.go | 2 +- x/distribution/keeper/keeper.go | 24 +++++++++- x/distribution/types/errors.go | 23 +++++++++ 6 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 x/distribution/alias.go create mode 100644 x/distribution/types/errors.go diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index d2a567fa4b..3166a6cc2a 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -11,9 +11,9 @@ 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/stake" - distr "github.com/cosmos/cosmos-sdk/x/stake" stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/spf13/pflag" diff --git a/x/distribution/alias.go b/x/distribution/alias.go new file mode 100644 index 0000000000..a89375034a --- /dev/null +++ b/x/distribution/alias.go @@ -0,0 +1,74 @@ +// nolint +package stake + +import ( + "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + "github.com/cosmos/cosmos-sdk/x/distribution/querier" + "github.com/cosmos/cosmos-sdk/x/distribution/tags" + "github.com/cosmos/cosmos-sdk/x/distribution/types" +) + +type ( + Keeper = keeper.Keeper + DelegatorWithdrawInfo = types.DelegatorWithdrawInfo + DelegatorDistInfo = types.DelegatorDistInfo + ValidatorDistInfo = types.ValidatorDistInfo + TotalAccum = types.TotalAccum + FeePool = types.FeePool + + MsgSetWithdrawAddress = types.MsgSetWithdrawAddress + MsgWithdrawDelegatorRewardsAll = types.MsgWithdrawDelegatorRewardsAll + MsgWithdrawDelegationReward = types.MsgWithdrawDelegationReward + MsgWithdrawValidatorRewardsAll = types.MsgWithdrawValidatorRewardsAll + + GenesisState = types.GenesisState +) + +var ( + NewKeeper = keeper.NewKeeper + NewQuerier = querier.NewQuerier + + GetValidatorDistInfoKey = keeper.GetValidatorDistInfoKey + GetDelegationDistInfoKey = keeper.GetDelegationDistInfoKey + GetDelegationDistInfosKey = keeper.GetDelegationDistInfosKey + GetDelegatorWithdrawAddrKey = keeper.GetDelegatorWithdrawAddrKey + FeePoolKey = keeper.FeePoolKey + ValidatorDistInfoKey = keeper.ValidatorDistInfoKey + DelegatorDistInfoKey = keeper.DelegatorDistInfoKey + DelegatorWithdrawInfoKey = keeper.DelegatorWithdrawInfoKey + ProposerKey = keeper.ProposerKey + + InitialFeePool = types.InitialFeePool + + NewGenesisState = types.NewGenesisState + DefaultGenesisState = types.DefaultGenesisState + + RegisterCodec = types.RegisterCodec + + NewMsgSetWithdrawAddress = types.NewMsgSetWithdrawAddress + NewMsgWithdrawDelegatorRewardsAll = types.NewMsgWithdrawDelegatorRewardsAll + NewMsgWithdrawDelegationReward = types.NewMsgWithdrawDelegationReward + 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.SrcValidator + TagDelegator = tags.Delegator +) diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index f377750f8e..045c840ed9 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -5,12 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake/types" ) -// InitGenesis sets the pool and parameters for the provided keeper and -// initializes the IntraTxCounter. For each validator in data, it sets that -// validator in the keeper along with manually setting the indexes. In -// addition, it also sets any delegations found in data. Finally, it updates -// the bonded validators. -// Returns final validator set after applying all declaration and delegations +// InitGenesis sets distribution information for genesis func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { keeper.SetFeePool(ctx, data.FeePool) diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 922d609897..d6e586b605 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -30,7 +30,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { proposerDist.Pool = proposerDist.Pool.Add(proposerReward.Sub(commission)) // allocate community funding - communityTax := sdk.NewDecWithPrec(1, 2) // XXX TODO get from global params store + communityTax := k.GetCommunityTax(ctx) communityFunding := feesCollectedDec.Mul(communityTax) feePool := k.GetFeePool(ctx) feePool.CommunityFund = feePool.CommunityFund.Add(communityFunding) diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 13c5a0b734..ff5ab62cc6 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -5,6 +5,12 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/params" +) + +// nolint +const ( + ParamStoreKeyCommunityTax = "distr/community-tax" ) // keeper of the stake store @@ -12,6 +18,7 @@ type Keeper struct { storeKey sdk.StoreKey storeTKey sdk.StoreKey cdc *wire.Codec + ps params.Setter coinKeeper types.CoinKeeper stakeKeeper types.StakeKeeper @@ -19,7 +26,7 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(cdc *wire.Codec, key, tkey sdk.StoreKey, ck types.CoinKeeper, +func NewKeeper(cdc *wire.Codec, key, tkey sdk.StoreKey, ps params.Setter, ck types.CoinKeeper, sk types.StakeKeeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ @@ -75,3 +82,18 @@ func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { b := k.cdc.MustMarshalBinary(consAddr) store.Set(ProposerKey, b) } + +//______________________________________________________________________ + +// Returns the current Deposit Procedure from the global param store +// nolint: errcheck +func (k Keeper) GetCommunityTax(ctx sdk.Context) sdk.Dec { + var communityTax sdk.Dec + keeper.ps.Get(ctx, ParamStoreKeyCommunityTax, &communityTax) + return communityTax +} + +// nolint: errcheck +func (k Keeper) setCommunityTax(ctx sdk.Context, communityTax sdk.Dec) { + keeper.ps.Set(ctx, ParamStoreKeyCommunityTax, &communityTax) +} diff --git a/x/distribution/types/errors.go b/x/distribution/types/errors.go new file mode 100644 index 0000000000..57a3dd73e3 --- /dev/null +++ b/x/distribution/types/errors.go @@ -0,0 +1,23 @@ +// nolint +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type CodeType = sdk.CodeType + +const ( + DefaultCodespace sdk.CodespaceType = 6 + CodeInvalidInput CodeType = 103 +) + +func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil") +} +func ErrNilWithdrawAddr(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidInput, "withdraw address is nil") +} +func ErrNilValidatorAddr(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidInput, "validator address is nil") +} From 76882991a49982a5a60a0a4744e6f00fd870d60e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 14:47:25 -0400 Subject: [PATCH 22/99] alias work, working on compiling --- Gopkg.lock | 9 ++++++++ x/distribution/alias.go | 4 ++-- x/distribution/types/delegator_info.go | 8 +++---- x/distribution/types/validator_info.go | 32 +++++++++++++------------- x/stake/keeper/validator.go | 3 +-- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 05019f84a1..0ad107b49d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -414,6 +414,14 @@ revision = "a8328986c1608950fa5d3d1c0472cccc4f8fc02c" version = "v0.12.0-rc0" +[[projects]] + digest = "1:2c971a45c89ca2ccc735af50919cdee05fbdc54d4bf50625073693300e31ead8" + name = "github.com/tendermint/go-wire" + packages = ["."] + pruneopts = "UT" + revision = "faa6e731944e2b7b6a46ad202902851e8ce85bee" + version = "v0.12.0" + [[projects]] digest = "1:53397098d6acb7613358683cc84ae59281a60c6033f0bff62fa8d3f279c6c430" name = "github.com/tendermint/iavl" @@ -645,6 +653,7 @@ "github.com/stretchr/testify/assert", "github.com/stretchr/testify/require", "github.com/tendermint/go-amino", + "github.com/tendermint/go-wire", "github.com/tendermint/iavl", "github.com/tendermint/tendermint/abci/server", "github.com/tendermint/tendermint/abci/types", diff --git a/x/distribution/alias.go b/x/distribution/alias.go index a89375034a..898a07714a 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -1,11 +1,11 @@ // nolint -package stake +package distribution import ( "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - "github.com/cosmos/cosmos-sdk/x/distribution/querier" "github.com/cosmos/cosmos-sdk/x/distribution/tags" "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/stake/querier" ) type ( diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index c34fad0772..fc3dca729a 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -10,12 +10,12 @@ type DelegatorDistInfo struct { } // withdraw rewards from delegator -func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, +func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, delegatorShares, - commissionRate Dec) (di DelegatorDistInfo, g Global, withdrawn DecCoins) { + commissionRate sdk.Dec) (DelegatorDistInfo, FeePool, DecCoins) { vi.UpdateTotalDelAccum(height, totalDelShares) - g = vi.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) + fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) blocks = height - di.WithdrawalHeight di.WithdrawalHeight = height @@ -25,7 +25,7 @@ func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, vi.Pool = vi.Pool.Sub(withdrawalTokens) vi.TotalDelAccum = vi.TotalDelAccum.sub(accum) - return di, g, withdrawalTokens + return di, fp, withdrawalTokens } //_____________________________________________________________________ diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 8ca4c03872..9c962b7c0d 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -14,41 +14,41 @@ type ValidatorDistInfo struct { } // update total delegator accumululation -func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec) ValidatorDistInfo { +func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares sdk.Dec) ValidatorDistInfo { vi.DelAccum = vi.DelAccum.Update(height, totalDelShares) return vi } +// XXX TODO Update dec logic // move any available accumulated fees in the Global to the validator's pool -func (vi ValidatorDistInfo) TakeGlobalRewards(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) ( - vi ValidatorDistInfo, g Global) { +func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBonded, vdTokens, + commissionRate sdk.Dec) (ValidatorDistInfo, FeePool) { - g.UpdateTotalValAccum(height, totalBondedShares) + fp.UpdateTotalValAccum(height, totalBondedShares) // update the validators pool blocks = height - vi.GlobalWithdrawalHeight vi.GlobalWithdrawalHeight = height - accum = blocks * vdTokens - withdrawalTokens := g.Pool * accum / g.TotalValAccum - commission := withdrawalTokens * commissionRate + accum = sdk.NewDec(blocks).Mul(vdTokens) + withdrawalTokens := fp.Pool.Mul(accum).Quo(fp.TotalValAccum) + commission := withdrawalTokens.Mul(commissionRate) - g.TotalValAccum -= accumm - g.Pool -= withdrawalTokens - vi.PoolCommission += commission - vi.PoolCommissionFree += withdrawalTokens - commission + fp.TotalValAccum = fp.TotalValAccum.Sub(accum) + fp.Pool = fp.Pool.Sub(withdrawalTokens) + vi.PoolCommission = vi.PoolCommission.Add(commission) + vi.PoolCommissionFree = vi.PoolCommissionFree.Add(withdrawalTokens.Sub(commission)) - return vi, g + return vi, fp } // withdraw commission rewards func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64, - totalBonded, vdTokens, commissionRate Dec) ( - vi ValidatorDistInfo, g Global, withdrawn DecCoins) { + totalBonded, vdTokens, commissionRate Dec) (vio ValidatorDistInfo, fpo FeePool, withdrawn DecCoins) { - g = vi.TakeGlobalRewards(g, height, totalBonded, vdTokens, commissionRate) + fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) withdrawalTokens := vi.PoolCommission vi.PoolCommission = 0 - return vi, g, withdrawalTokens + return vi, fp, withdrawalTokens } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 27f2547fd9..d2c314222f 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -736,6 +736,7 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { //__________________________________________________________________________ +// XXX remove this code - this is should be superceded by commission work that bez is doing // get a single validator func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { store := ctx.KVStore(k.storeKey) @@ -753,8 +754,6 @@ func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, return types.ErrNoValidatorFound(k.Codespace()) case newCommission.LT(sdk.ZeroDec()): return types.ErrCommissionNegative(k.Codespace()) - case newCommission.GT(sdk.OnedDec()): - return types.ErrCommissionHuge(k.Codespace()) case newCommission.GT(validator.CommissionMax): return types.ErrCommissionBeyondMax(k.Codespace()) //case rateChange(Commission) > CommissionMaxChange: // XXX XXX XXX TODO implementation From df9c8db5e76b42ad61354380060338d89bc02227 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 19:00:21 -0400 Subject: [PATCH 23/99] working through compile errors --- Gopkg.lock | 9 --------- x/distribution/client/cli/tx.go | 15 ++++++++------- x/distribution/keeper/keeper.go | 7 +++---- x/distribution/types/codec.go | 6 +++--- x/distribution/types/dec_coin.go | 13 +++++++------ x/distribution/types/fee_pool.go | 2 +- x/distribution/types/genesis.go | 10 ++++------ x/distribution/types/keepers.go | 4 ++-- x/distribution/types/msg.go | 18 +++++++++--------- x/distribution/types/validator_info.go | 16 ++++++++-------- x/stake/keeper/keeper.go | 2 +- x/stake/keeper/sdk_types.go | 23 ++--------------------- x/stake/keeper/validator.go | 17 ++++++++--------- 13 files changed, 56 insertions(+), 86 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 0ad107b49d..05019f84a1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -414,14 +414,6 @@ revision = "a8328986c1608950fa5d3d1c0472cccc4f8fc02c" version = "v0.12.0-rc0" -[[projects]] - digest = "1:2c971a45c89ca2ccc735af50919cdee05fbdc54d4bf50625073693300e31ead8" - name = "github.com/tendermint/go-wire" - packages = ["."] - pruneopts = "UT" - revision = "faa6e731944e2b7b6a46ad202902851e8ce85bee" - version = "v0.12.0" - [[projects]] digest = "1:53397098d6acb7613358683cc84ae59281a60c6033f0bff62fa8d3f279c6c430" name = "github.com/tendermint/iavl" @@ -653,7 +645,6 @@ "github.com/stretchr/testify/assert", "github.com/stretchr/testify/require", "github.com/tendermint/go-amino", - "github.com/tendermint/go-wire", "github.com/tendermint/iavl", "github.com/tendermint/tendermint/abci/server", "github.com/tendermint/tendermint/abci/types", diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index f9cd858bb1..37330634e9 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -5,13 +5,14 @@ import ( "fmt" "os" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/client/utils" - sdk "github.com/cosmos/cosmos-sdk/types" - distr "github.com/cosmos/cosmos-sdk/x/distribution" "github.com/spf13/cobra" "github.com/spf13/viper" - wire "github.com/tendermint/go-wire" + + "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" + distr "github.com/cosmos/cosmos-sdk/x/distribution" ) var ( @@ -20,7 +21,7 @@ var ( ) // command to withdraw rewards -func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { +func GetCmdWithdrawDelegationRewardsAll(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "withdraw-rewards", Short: "withdraw rewards for either: all-delegations, a delegation, or a validator", @@ -80,7 +81,7 @@ func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command { } // GetCmdDelegate implements the delegate command. -func GetCmdSetWithdrawAddr(cdc *wire.Codec) *cobra.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", diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index ff5ab62cc6..01f0ee0784 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -1,8 +1,7 @@ package keeper import ( - wire "github.com/tendermint/go-wire" - + "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" @@ -17,7 +16,7 @@ const ( type Keeper struct { storeKey sdk.StoreKey storeTKey sdk.StoreKey - cdc *wire.Codec + cdc *codec.Codec ps params.Setter coinKeeper types.CoinKeeper stakeKeeper types.StakeKeeper @@ -26,7 +25,7 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(cdc *wire.Codec, key, tkey sdk.StoreKey, ps params.Setter, ck types.CoinKeeper, +func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ps params.Setter, ck types.CoinKeeper, sk types.StakeKeeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ diff --git a/x/distribution/types/codec.go b/x/distribution/types/codec.go index ece45a004f..edb121d20d 100644 --- a/x/distribution/types/codec.go +++ b/x/distribution/types/codec.go @@ -6,10 +6,10 @@ import ( // Register concrete types on codec codec func RegisterCodec(cdc *codec.Codec) { - cdc.RegisterConcrete(MsgWithdrawDelegationRewardsAll{}, "cosmos-sdk/MsgWithdrawDelegationRewardsAll", nil) - cdc.RegisterConcrete(MsgWithdrawDelegationReward{}, "cosmos-sdk/MsgWithdrawDelegationReward", nil) + cdc.RegisterConcrete(MsgWithdrawDelegatorRewardsAll{}, "cosmos-sdk/MsgWithdrawDelegationRewardsAll", nil) + cdc.RegisterConcrete(MsgWithdrawDelegatorReward{}, "cosmos-sdk/MsgWithdrawDelegationReward", nil) cdc.RegisterConcrete(MsgWithdrawValidatorRewardsAll{}, "cosmos-sdk/MsgWithdrawValidatorRewardsAll", nil) - cdc.RegisterConcrete(MsgModifyWithdrawAddress{}, "cosmos-sdk/MsgModifyWithdrawAddress", nil) + cdc.RegisterConcrete(MsgSetWithdrawAddress{}, "cosmos-sdk/MsgModifyWithdrawAddress", nil) } // generic sealed codec to be used throughout sdk diff --git a/x/distribution/types/dec_coin.go b/x/distribution/types/dec_coin.go index 4e6a4cfc3c..f014e3615d 100644 --- a/x/distribution/types/dec_coin.go +++ b/x/distribution/types/dec_coin.go @@ -13,9 +13,9 @@ type DecCoin struct { } func NewDecCoin(coin sdk.Coin) DecCoin { - return DecCoins{ + return DecCoin{ Denom: coin.Denom, - Amount: sdk.NewDec(coin.Amount), + Amount: sdk.NewDecFromInt(coin.Amount), } } @@ -24,7 +24,7 @@ func (coin DecCoin) Plus(coinB DecCoin) DecCoin { if !(coin.Denom == coinB.Denom) { return coin } - return Coin{coin.Denom, coin.Amount.Add(coinB.Amount)} + return DecCoin{coin.Denom, coin.Amount.Add(coinB.Amount)} } // return the decimal coins with trunctated decimals @@ -38,19 +38,20 @@ func (coin DecCoin) TruncateDecimal() sdk.Coin { type DecCoins []DecCoin func NewDecCoins(coins sdk.Coins) DecCoins { - dcs := make(DecCoins, len(coins)) for i, coin := range coins { dcs[i] = NewDecCoin(coin) } + return dcs } -// return the decimal coins with trunctated decimals +// return the coins with trunctated decimals func (coins DecCoins) TruncateDecimal() sdk.Coins { - out := make(DecCoins, len(coins)) + out := make(sdk.Coins, len(coins)) for i, coin := range coins { out[i] = coin.TruncateDecimal() } + return out } // Plus combines two sets of coins diff --git a/x/distribution/types/fee_pool.go b/x/distribution/types/fee_pool.go index 14744689df..7c215fce2d 100644 --- a/x/distribution/types/fee_pool.go +++ b/x/distribution/types/fee_pool.go @@ -33,7 +33,7 @@ type FeePool struct { } // update total validator accumulation factor -func (f FeePool) UpdateTotalValAccum(height int64, totalBondedTokens Dec) FeePool { +func (f FeePool) UpdateTotalValAccum(height int64, totalBondedTokens sdk.Dec) FeePool { f.ValAccum = f.ValAccum.Update(height, totalBondedTokens) return f } diff --git a/x/distribution/types/genesis.go b/x/distribution/types/genesis.go index 782f54ade0..a42f705941 100644 --- a/x/distribution/types/genesis.go +++ b/x/distribution/types/genesis.go @@ -1,13 +1,11 @@ package types -import sdk "github.com/cosmos/cosmos-sdk/types" - // GenesisState - all distribution state that must be provided at genesis type GenesisState struct { - FeePool FeePool `json:"fee_pool"` - ValidatorDistInfos []ValidatorDistInfo `json:"validator_dist_infos"` - DelegatorDistInfos []DelegatorDistInfo `json:"delegator_dist_infos"` - DelegatorDistInfos []sdk.AccAddress `json:"delegator_dist_infos"` + FeePool FeePool `json:"fee_pool"` + ValidatorDistInfos []ValidatorDistInfo `json:"validator_dist_infos"` + DelegatorDistInfos []DelegatorDistInfo `json:"delegator_dist_infos"` + DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"` } func NewGenesisState(feePool FeePool, vdis []ValidatorDistInfo, ddis []DelegatorDistInfo) GenesisState { diff --git a/x/distribution/types/keepers.go b/x/distribution/types/keepers.go index 7b05392167..3cf34da2a4 100644 --- a/x/distribution/types/keepers.go +++ b/x/distribution/types/keepers.go @@ -4,8 +4,8 @@ import sdk "github.com/cosmos/cosmos-sdk/types" // expected stake keeper type StakeKeeper interface { - IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, - fn func(index int64, del types.Delegation) (stop bool)) + IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress, + fn func(index int64, delegation sdk.Delegation) (stop bool)) GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress) GetValidator(ctx sdk.Context, valAddr sdk.AccAddress) GetPool(ctx sdk.Context) diff --git a/x/distribution/types/msg.go b/x/distribution/types/msg.go index ce77285c15..6b4997fef6 100644 --- a/x/distribution/types/msg.go +++ b/x/distribution/types/msg.go @@ -10,7 +10,7 @@ const MsgType = "distr" // Verify interface at compile time var _, _ sdk.Msg = &MsgSetWithdrawAddress{}, &MsgWithdrawDelegatorRewardsAll{} -var _, _ sdk.Msg = &MsgWithdrawDelegationReward{}, &MsgWithdrawValidatorRewardsAll{} +var _, _ sdk.Msg = &MsgWithdrawDelegatorReward{}, &MsgWithdrawValidatorRewardsAll{} //______________________________________________________________________ @@ -96,28 +96,28 @@ func (msg MsgWithdrawDelegatorRewardsAll) ValidateBasic() sdk.Error { //______________________________________________________________________ // msg struct for delegation withdraw from a single validator -type MsgWithdrawDelegationReward struct { +type MsgWithdrawDelegatorReward struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` ValidatorAddr sdk.ValAddress `json:"validator_addr"` } -func NewMsgWithdrawDelegationReward(delAddr sdk.AccAddress, valAddr sdk.ValAddress) MsgWithdrawDelegationReward { - return MsgWithdrawDelegationReward{ +func NewMsgWithdrawDelegationReward(delAddr sdk.AccAddress, valAddr sdk.ValAddress) MsgWithdrawDelegatorReward { + return MsgWithdrawDelegatorReward{ DelegatorAddr: delAddr, ValidatorAddr: valAddr, } } -func (msg MsgWithdrawDelegationReward) Type() string { return MsgType } -func (msg MsgWithdrawDelegationReward) Name() string { return "withdraw_delegation_reward" } +func (msg MsgWithdrawDelegatorReward) Type() string { return MsgType } +func (msg MsgWithdrawDelegatorReward) Name() string { return "withdraw_delegation_reward" } // Return address that must sign over msg.GetSignBytes() -func (msg MsgWithdrawDelegationReward) GetSigners() []sdk.AccAddress { +func (msg MsgWithdrawDelegatorReward) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{sdk.AccAddress(msg.DelegatorAddr)} } // get the bytes for the message signer to sign on -func (msg MsgWithdrawDelegationReward) GetSignBytes() []byte { +func (msg MsgWithdrawDelegatorReward) GetSignBytes() []byte { b, err := MsgCdc.MarshalJSON(msg) if err != nil { panic(err) @@ -126,7 +126,7 @@ func (msg MsgWithdrawDelegationReward) GetSignBytes() []byte { } // quick validity check -func (msg MsgWithdrawDelegationReward) ValidateBasic() sdk.Error { +func (msg MsgWithdrawDelegatorReward) ValidateBasic() sdk.Error { if msg.DelegatorAddr == nil { return ErrNilDelegatorAddr(DefaultCodespace) } diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 9c962b7c0d..5f8fa686be 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -6,9 +6,9 @@ import sdk "github.com/cosmos/cosmos-sdk/types" type ValidatorDistInfo struct { OperatorAddr sdk.ValAddress `json:"operator_addr"` - GlobalWithdrawalHeight int64 `json:"global_withdrawal_height"` // last height this validator withdrew from the global pool - Pool DecCoins `json:"pool"` // rewards owed to delegators, commission has already been charged (includes proposer reward) - PoolCommission DecCoins `json:"pool_commission"` // commission collected by this validator (pending withdrawal) + FeePoolWithdrawalHeight int64 `json:"global_withdrawal_height"` // last height this validator withdrew from the global pool + Pool DecCoins `json:"pool"` // rewards owed to delegators, commission has already been charged (includes proposer reward) + PoolCommission DecCoins `json:"pool_commission"` // commission collected by this validator (pending withdrawal) DelAccum TotalAccum `json:"del_accum"` // total proposer pool accumulation factor held by delegators } @@ -20,15 +20,15 @@ func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares sdk } // XXX TODO Update dec logic -// move any available accumulated fees in the Global to the validator's pool +// move any available accumulated fees in the FeePool to the validator's pool func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBonded, vdTokens, commissionRate sdk.Dec) (ValidatorDistInfo, FeePool) { fp.UpdateTotalValAccum(height, totalBondedShares) // update the validators pool - blocks = height - vi.GlobalWithdrawalHeight - vi.GlobalWithdrawalHeight = height + blocks = height - vi.FeePoolWithdrawalHeight + vi.FeePoolWithdrawalHeight = height accum = sdk.NewDec(blocks).Mul(vdTokens) withdrawalTokens := fp.Pool.Mul(accum).Quo(fp.TotalValAccum) commission := withdrawalTokens.Mul(commissionRate) @@ -42,8 +42,8 @@ func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBo } // withdraw commission rewards -func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64, - totalBonded, vdTokens, commissionRate Dec) (vio ValidatorDistInfo, fpo FeePool, withdrawn DecCoins) { +func (vi ValidatorDistInfo) WithdrawCommission(fp FeePool, height int64, + totalBonded, vdTokens, commissionRate sdk.Dec) (vio ValidatorDistInfo, fpo FeePool, withdrawn DecCoins) { fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index cb76a9562a..82170a4aed 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -34,7 +34,7 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespa // Set the validator hooks func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { - if k.stakingHooks != nil { + if k.hooks != nil { panic("cannot set validator hooks twice") } k.hooks = sh diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index e4c7a1c193..6297919392 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -3,8 +3,6 @@ package keeper import ( "fmt" - "github.com/tendermint/tendermint/crypto" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" ) @@ -60,8 +58,8 @@ func (k Keeper) Validator(ctx sdk.Context, address sdk.ValAddress) sdk.Validator } // get the sdk.validator for a particular pubkey -func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Validator { - val, found := k.GetValidatorByPubKey(ctx, pubkey) +func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) sdk.Validator { + val, found := k.GetValidatorByConsAddr(ctx, addr) if !found { return nil } @@ -94,20 +92,3 @@ func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk. return bond } - -// iterate through the active validator set and perform the provided function -func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, fn func(index int64, delegation sdk.Delegation) (stop bool)) { - store := ctx.KVStore(k.storeKey) - key := GetDelegationsKey(delAddr) - iterator := sdk.KVStorePrefixIterator(store, key) - i := int64(0) - for ; iterator.Valid(); iterator.Next() { - delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) - stop := fn(i, delegation) // XXX is this safe will the fields be able to get written to? - if stop { - break - } - i++ - } - iterator.Close() -} diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index d2c314222f..d0dbcc9e45 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -6,7 +6,6 @@ import ( "fmt" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" @@ -59,13 +58,13 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty } // get a single validator by pubkey -func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (validator types.Validator, found bool) { +func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) { store := ctx.KVStore(k.storeKey) - addr := store.Get(GetValidatorByPubKeyIndexKey(pubkey)) - if addr == nil { + opAddr := store.Get(GetValidatorByConsAddrKey(consAddr)) + if opAddr == nil { return validator, false } - return k.GetValidator(ctx, addr) + return k.GetValidator(ctx, opAddr) } // set the main record holding validator details @@ -78,8 +77,8 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { // validator index func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - consAddr := sdk.consAddress{validator.Address()} - store.Set(GetValidatorByPubKeyIndexKey(consAddr), validator.OperatorAddr) + consAddr := sdk.ConsAddress{validator.OperatorAddr.Bytes()} + store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr) } // validator index @@ -671,7 +670,7 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { // call the hook if present if k.hooks != nil { - k.hooks.OnValidatorRemoved(ctx, validator.OperatorAddr) + k.hooks.OnValidatorRemoved(ctx, address) } // first retrieve the old validator record @@ -684,7 +683,7 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) store.Delete(GetValidatorKey(address)) - store.Delete(GetValidatorByPubKeyIndexKey(validator.ConsPubKey)) + store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddr{validator.ConsPubKey.Address()})) store.Delete(GetValidatorsByPowerIndexKey(validator, pool)) // delete from the current and power weighted validator groups if the validator From d9396ed7324378fc7555137cf1ecf010e669c702 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 19:33:12 -0400 Subject: [PATCH 24/99] working compile errors --- types/stake.go | 2 +- x/distribution/types/dec_coin.go | 2 +- x/distribution/types/delegator_info.go | 8 ++++---- x/distribution/types/fee_pool.go | 4 ++-- x/distribution/types/validator_info.go | 17 +++++++++-------- x/stake/genesis.go | 2 +- x/stake/handler.go | 16 ++++++++-------- x/stake/keeper/delegation.go | 18 ------------------ x/stake/keeper/sdk_types.go | 18 ++++++++++++++++++ x/stake/keeper/slash.go | 4 ++-- x/stake/keeper/validator.go | 11 +++++------ x/stake/stake.go | 4 ++-- 12 files changed, 53 insertions(+), 53 deletions(-) diff --git a/types/stake.go b/types/stake.go index 68257689d2..6012e4643a 100644 --- a/types/stake.go +++ b/types/stake.go @@ -68,7 +68,7 @@ type ValidatorSet interface { func(index int64, validator Validator) (stop bool)) Validator(Context, ValAddress) Validator // get a particular validator by operator - ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey + ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address TotalPower(Context) Dec // total power of the validator set // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction diff --git a/x/distribution/types/dec_coin.go b/x/distribution/types/dec_coin.go index f014e3615d..eef4f78a63 100644 --- a/x/distribution/types/dec_coin.go +++ b/x/distribution/types/dec_coin.go @@ -93,7 +93,7 @@ func (coins DecCoins) Plus(coinsB DecCoins) DecCoins { func (coins DecCoins) Mul(multiple sdk.Dec) DecCoins { products := make([]DecCoin, len(coins)) for i, coin := range coins { - product := DecCoins{ + product := DecCoin{ Denom: coin.Denom, Amount: coin.Amount.Mul(multiple), } diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index fc3dca729a..eeb5af11d4 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -15,15 +15,15 @@ func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, commissionRate sdk.Dec) (DelegatorDistInfo, FeePool, DecCoins) { vi.UpdateTotalDelAccum(height, totalDelShares) - fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) + vi, fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) - blocks = height - di.WithdrawalHeight + blocks := height - di.WithdrawalHeight di.WithdrawalHeight = height accum := delegatorShares.Mul(sdk.NewDec(blocks)) - withdrawalTokens := vi.Pool.Mul(accum.Quo(vi.TotalDelAccum)) + withdrawalTokens := vi.Pool.Mul(accum.Quo(vi.DelAccum.Accum)) vi.Pool = vi.Pool.Sub(withdrawalTokens) - vi.TotalDelAccum = vi.TotalDelAccum.sub(accum) + vi.DelAccum.Accum = vi.DelAccum.Accum.Sub(accum) return di, fp, withdrawalTokens } diff --git a/x/distribution/types/fee_pool.go b/x/distribution/types/fee_pool.go index 7c215fce2d..03725d7c1d 100644 --- a/x/distribution/types/fee_pool.go +++ b/x/distribution/types/fee_pool.go @@ -18,7 +18,7 @@ func NewTotalAccum(height int64) TotalAccum { // update total validator accumulation factor func (ta TotalAccum) Update(height int64, accumCreatedPerBlock sdk.Dec) TotalAccum { blocks := height - ta.UpdateHeight - f.Accum = f.Accum.Add(accumCreatedPerBlock.Mul(sdk.NewDec(blocks))) + ta.Accum = ta.Accum.Add(accumCreatedPerBlock.Mul(sdk.NewDec(blocks))) ta.UpdateHeight = height return ta } @@ -41,7 +41,7 @@ func (f FeePool) UpdateTotalValAccum(height int64, totalBondedTokens sdk.Dec) Fe // zero fee pool func InitialFeePool() FeePool { return FeePool{ - ValAccum: NewwTotalAccum(0), + ValAccum: NewTotalAccum(0), Pool: DecCoins{}, CommunityPool: DecCoins{}, } diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 5f8fa686be..b2f2592ea3 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -24,19 +24,20 @@ func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares sdk func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBonded, vdTokens, commissionRate sdk.Dec) (ValidatorDistInfo, FeePool) { - fp.UpdateTotalValAccum(height, totalBondedShares) + fp.UpdateTotalValAccum(height, totalBonded) // update the validators pool - blocks = height - vi.FeePoolWithdrawalHeight + blocks := height - vi.FeePoolWithdrawalHeight vi.FeePoolWithdrawalHeight = height - accum = sdk.NewDec(blocks).Mul(vdTokens) - withdrawalTokens := fp.Pool.Mul(accum).Quo(fp.TotalValAccum) + accum := sdk.NewDec(blocks).Mul(vdTokens) + withdrawalTokens := fp.Pool.Mul(accum.Quo(fp.ValAccum.Accum)) commission := withdrawalTokens.Mul(commissionRate) + afterCommission := withdrawalTokens.Sub(commission) - fp.TotalValAccum = fp.TotalValAccum.Sub(accum) + fp.ValAccum.Accum = fp.ValAccum.Accum.Sub(accum) fp.Pool = fp.Pool.Sub(withdrawalTokens) vi.PoolCommission = vi.PoolCommission.Add(commission) - vi.PoolCommissionFree = vi.PoolCommissionFree.Add(withdrawalTokens.Sub(commission)) + vi.Pool = vi.Pool.Add(afterCommission) return vi, fp } @@ -45,10 +46,10 @@ func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBo func (vi ValidatorDistInfo) WithdrawCommission(fp FeePool, height int64, totalBonded, vdTokens, commissionRate sdk.Dec) (vio ValidatorDistInfo, fpo FeePool, withdrawn DecCoins) { - fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) + vi, fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) withdrawalTokens := vi.PoolCommission - vi.PoolCommission = 0 + vi.PoolCommission = DecCoins{} // zero return vi, fp, withdrawalTokens } diff --git a/x/stake/genesis.go b/x/stake/genesis.go index 7a004bccd2..a7f8493081 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -32,7 +32,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ } // Manually set indexes for the first time - keeper.SetValidatorByPubKeyIndex(ctx, validator) + keeper.SetValidatorByConsAddr(ctx, validator) keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool) if validator.Status == sdk.Bonded { diff --git a/x/stake/handler.go b/x/stake/handler.go index e1fb3edc02..2f563fdc0f 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -68,7 +68,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k if found { return ErrValidatorOwnerExists(k.Codespace()).Result() } - _, found = k.GetValidatorByPubKey(ctx, msg.PubKey) + _, found = k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(msg.PubKey.Address())) if found { return ErrValidatorPubKeyExists(k.Codespace()).Result() } @@ -78,7 +78,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description) k.SetValidator(ctx, validator) - k.SetValidatorByPubKeyIndex(ctx, validator) + k.SetValidatorByConsAddr(ctx, validator) // move coins from the msg.Address account to a (self-delegation) delegator account // the validator account and global shares are updated within here @@ -88,10 +88,10 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k } // call the hook if present - if k.validatorHooks != nil { - k.validatorHooks.OnValidatorCreated(ctx, validator.OperatorAddr) - accAddr := sdk.AccAddress{validator.OperatorAddr} - k.validatorHooks.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) + if k.hooks != nil { + k.hooks.OnValidatorCreated(ctx, validator.OperatorAddr) + accAddr := sdk.AccAddress(validator.OperatorAddr) + k.hooks.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) } tags := sdk.NewTags( @@ -154,8 +154,8 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) } // call the hook if present - if k.validatorHooks != nil { - k.validatorHooks.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) + if k.hooks != nil { + k.hooks.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) } tags := sdk.NewTags( diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 78e16de828..6ac51ac196 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -57,24 +57,6 @@ func (k Keeper) GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddres return delegations[:i] // trim if the array length < maxRetrieve } -// iterate through all of the delegations from a delegator -func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, - fn func(index int64, del types.Delegation) (stop bool)) { - - store := ctx.KVStore(k.storeKey) - delegatorPrefixKey := GetDelegationsKey(delAddr) - iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest - for i := int64(0); iterator.Valid(); iterator.Next() { - del := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) - stop := fn(i, del) - if stop { - break - } - i++ - } - iterator.Close() -} - // set the delegation func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { store := ctx.KVStore(k.storeKey) diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 6297919392..d702e845da 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -92,3 +92,21 @@ func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk. return bond } + +// iterate through all of the delegations from a delegator +func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, + fn func(index int64, del sdk.Delegation) (stop bool)) { + + store := ctx.KVStore(k.storeKey) + delegatorPrefixKey := GetDelegationsKey(delAddr) + iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest + for i := int64(0); iterator.Valid(); iterator.Next() { + del := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) + stop := fn(i, del) + if stop { + break + } + i++ + } + iterator.Close() +} diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index 52dbd21c7e..e45c458f77 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -36,7 +36,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // ref https://github.com/cosmos/cosmos-sdk/issues/1348 // ref https://github.com/cosmos/cosmos-sdk/issues/1471 - validator, found := k.GetValidatorByPubKey(ctx, pubkey) + validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(pubkey.Address())) if !found { // If not found, the validator must have been overslashed and removed - so we don't need to do anything // NOTE: Correctness dependent on invariant that unbonding delegations / redelegations must also have been completely @@ -152,7 +152,7 @@ func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { // set the jailed flag on a validator func (k Keeper) setJailed(ctx sdk.Context, pubkey crypto.PubKey, isJailed bool) { - validator, found := k.GetValidatorByPubKey(ctx, pubkey) + validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(pubkey.Address())) if !found { panic(fmt.Errorf("validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed)) } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index d0dbcc9e45..766f3fc8f1 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -77,7 +77,7 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { // validator index func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - consAddr := sdk.ConsAddress{validator.OperatorAddr.Bytes()} + consAddr := sdk.ConsAddress(validator.OperatorAddr.Bytes()) store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr) } @@ -683,7 +683,7 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) store.Delete(GetValidatorKey(address)) - store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddr{validator.ConsPubKey.Address()})) + store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address()))) store.Delete(GetValidatorsByPowerIndexKey(validator, pool)) // delete from the current and power weighted validator groups if the validator @@ -738,14 +738,13 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { // XXX remove this code - this is should be superceded by commission work that bez is doing // get a single validator func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { - store := ctx.KVStore(k.storeKey) // call the hook if present if k.hooks != nil { - k.hooks.OnValidatorCommissionChange(ctx, validator.OperatorAddr) + k.hooks.OnValidatorCommissionChange(ctx, addr) } - validator, found := k.GetValidator(addr) + validator, found := k.GetValidator(ctx, addr) // check for errors switch { @@ -763,6 +762,6 @@ func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, validator.Commission = newCommission - k.SetValidator(addr, validator) + k.SetValidator(ctx, validator) return nil } diff --git a/x/stake/stake.go b/x/stake/stake.go index 18b99fd4a0..6b4036d281 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -35,7 +35,7 @@ var ( NewKeeper = keeper.NewKeeper GetValidatorKey = keeper.GetValidatorKey - GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey + GetValidatorByConsAddrKey = keeper.GetValidatorByConsAddrKey GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey @@ -44,7 +44,7 @@ var ( ParamKey = keeper.ParamKey PoolKey = keeper.PoolKey ValidatorsKey = keeper.ValidatorsKey - ValidatorsByPubKeyIndexKey = keeper.ValidatorsByPubKeyIndexKey + ValidatorsByConsAddrKey = keeper.ValidatorsByConsAddrKey ValidatorsBondedIndexKey = keeper.ValidatorsBondedIndexKey ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey From 7002438d5f287b2296bdabe2fa10f62e9b4b1fd1 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 21:17:28 -0400 Subject: [PATCH 25/99] compile debugging --- x/slashing/keeper.go | 2 +- x/stake/handler.go | 12 +++------ x/stake/keeper/hooks.go | 54 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 x/stake/keeper/hooks.go diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 5a008ccec5..468f941630 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -118,7 +118,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p } minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx) if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) { - validator := k.validatorSet.ValidatorByPubKey(ctx, pubkey) + validator := k.validatorSet.ValidatorByConsAddr(ctx, address) if validator != nil && !validator.GetJailed() { // Downtime confirmed: slash and jail the validator logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d", diff --git a/x/stake/handler.go b/x/stake/handler.go index 2f563fdc0f..c9955f1bfa 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -88,11 +88,9 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k } // call the hook if present - if k.hooks != nil { - k.hooks.OnValidatorCreated(ctx, validator.OperatorAddr) - accAddr := sdk.AccAddress(validator.OperatorAddr) - k.hooks.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) - } + k.OnValidatorCreated(ctx, validator.OperatorAddr) + accAddr := sdk.AccAddress(validator.OperatorAddr) + k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) tags := sdk.NewTags( tags.Action, tags.ActionCreateValidator, @@ -154,9 +152,7 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) } // call the hook if present - if k.hooks != nil { - k.hooks.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) - } + k.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) tags := sdk.NewTags( tags.Action, tags.ActionDelegate, diff --git a/x/stake/keeper/hooks.go b/x/stake/keeper/hooks.go new file mode 100644 index 0000000000..81bf5594ba --- /dev/null +++ b/x/stake/keeper/hooks.go @@ -0,0 +1,54 @@ +//nolint +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Expose the hooks if present +func (k Keeper) OnValidatorCreated(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorCreated(ctx, address) + } +} +func (k Keeper) OnValidatorCommissionChange(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorCommissionChange(ctx, address) + } +} + +func (k Keeper) OnValidatorRemoved(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorRemoved(ctx, address) + } +} + +func (k Keeper) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { + if k.hooks != nil { + k.hooks.OnValidatorBonded(ctx, address) + } +} + +func (k Keeper) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { + if k.hooks != nil { + k.hooks.OnValidatorBeginUnbonding(ctx, address) + } +} + +func (k Keeper) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationCreated(ctx, delAddr, valAddr) + } +} + +func (k Keeper) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationSharesModified(ctx, delAddr, valAddr) + } +} + +func (k Keeper) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationRemoved(ctx, delAddr, valAddr) + } +} From 18fdccf95b097b2273db2bb13417a5d0ccac15fc Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 22:13:12 -0400 Subject: [PATCH 26/99] ... --- types/stake.go | 1 + x/distribution/keeper/allocation.go | 25 +++++++++++----------- x/distribution/keeper/delegation.go | 20 +++++++++--------- x/distribution/keeper/keeper.go | 29 ++++++++++++++------------ x/distribution/types/delegator_info.go | 3 ++- x/distribution/types/keepers.go | 7 ++++--- x/distribution/types/validator_info.go | 10 +++++---- x/stake/types/validator.go | 1 + 8 files changed, 53 insertions(+), 43 deletions(-) diff --git a/types/stake.go b/types/stake.go index 6012e4643a..3d5969f9d4 100644 --- a/types/stake.go +++ b/types/stake.go @@ -44,6 +44,7 @@ type Validator interface { GetPubKey() crypto.PubKey // validation pubkey 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 } diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index d6e586b605..a20055bbb4 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -2,6 +2,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution/types" ) // Allocate fees handles distribution of the collected fees @@ -10,22 +11,22 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) proserValidator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, proposerConsAddr) - proposerDist := k.GetFeeDistribution(ctx, proserValidator.OperatorAddr) + proposerDist := k.GetValidatorDistInfo(ctx, proserValidator.GetOperator()) // get the fees which have been getting collected through all the // transactions in the block - feesCollected := k.FeeCollectionKeeper.GetCollectedFees(ctx) - feesCollectedDec := NewDecCoins(feesCollected) + feesCollected := k.feeCollectionKeeper.GetCollectedFees(ctx) + feesCollectedDec := types.NewDecCoins(feesCollected) // allocated rewards to proposer - stakePool := k.stakeKeeper.GetPool(ctx) + bondedTokens := k.stakeKeeper.TotalPower(ctx) sumPowerPrecommitValidators := sdk.NewDec(1) // XXX TODO actually calculate this proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( - sumPowerPrecommitValidators).Div(stakePool.BondedTokens)) + sumPowerPrecommitValidators).Quo(bondedTokens)) proposerReward := feesCollectedDec.Mul(proposerMultiplier) // apply commission - commission := proposerReward.Mul(proserValidator.Commission) + commission := proposerReward.Mul(proserValidator.GetCommission()) proposerDist.PoolCommission = proposerDist.PoolCommission.Add(commission) proposerDist.Pool = proposerDist.Pool.Add(proposerReward.Sub(commission)) @@ -33,15 +34,15 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { communityTax := k.GetCommunityTax(ctx) communityFunding := feesCollectedDec.Mul(communityTax) feePool := k.GetFeePool(ctx) - feePool.CommunityFund = feePool.CommunityFund.Add(communityFunding) + feePool.CommunityPool = feePool.CommunityPool.Add(communityFunding) // set the global pool within the distribution module - poolReceived := feesCollectedDec.Sub(proposerReward).Sub(communityFunding) - feePool.Pool = feePool.Pool.Add(poolReceived) + poolReceived := feesCollectedDec.Mul(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) + feePool.Pool = feePool.Pool.Plus(poolReceived) - SetValidatorDistribution(proposerDist) - SetFeePool(feePool) + k.SetValidatorDistInfo(ctx, proposerDist) + k.SetFeePool(ctx, feePool) // clear the now distributed fees - k.FeeCollectionKeeper.ClearCollectedFees(ctx) + k.feeCollectionKeeper.ClearCollectedFees(ctx) } diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 5bf6793f19..1323f2dbc4 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -32,7 +32,7 @@ func (k Keeper) RemoveDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, valOperatorAddr sdk.ValAddress) { store := ctx.KVStore(k.storeKey) - store.Delete(GetDelegationDistInfoKey(DelegatorAddr, ValOperatorAddr)) + store.Delete(GetDelegationDistInfoKey(delAddr, valOperatorAddr)) } //___________________________________________________________________________________________ @@ -45,13 +45,13 @@ func (k Keeper) GetDelegatorWithdrawAddr(ctx sdk.Context, delAddr sdk.AccAddress if b == nil { return delAddr } - return sdk.AccAddress{b} + 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(ddi.DelegatorAddr), withdrawAddr.Bytes()) + store.Set(GetDelegatorWithdrawAddrKey(delAddr), withdrawAddr.Bytes()) } // remove a delegator withdraw info @@ -67,18 +67,18 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA validatorAddr sdk.ValAddress) { height := ctx.BlockHeight() - pool := k.sk.GetPool(ctx) + bondedTokens := k.stakeKeeper.TotalPower(ctx) feePool := k.GetFeePool(ctx) - delInfo := k.GetDelegationDistInfo(ctx, delegatorAddr, validatorAddr) + delInfo := k.GetDelegatorDistInfo(ctx, delegatorAddr, validatorAddr) valInfo := k.GetValidatorDistInfo(ctx, validatorAddr) - validator := k.GetValidator(ctx, validatorAddr) + validator := k.stakeKeeper.GetValidator(ctx, validatorAddr) - feePool, withdraw := delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, + delInfo, feePool, withdraw := delInfo.WithdrawRewards(ctx, feePool, valInfo, height, bondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) k.SetFeePool(ctx, feePool) - withdrawAddr := k.GetDelegatorWithdrawAddr(delegatorAddr) - k.ck.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) + withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr) + k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) } //___________________________________________________________________________________________ @@ -92,7 +92,7 @@ func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr sdk. } // return all rewards for all delegations of a delegator -func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) DecCoins { +func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) types.DecCoins { withdraw := sdk.NewDec(0) pool := k.sk.GetPool(ctx) diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 01f0ee0784..bbf4c15411 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -14,26 +14,29 @@ const ( // keeper of the stake store type Keeper struct { - storeKey sdk.StoreKey - storeTKey sdk.StoreKey - cdc *codec.Codec - ps params.Setter - coinKeeper types.CoinKeeper - stakeKeeper types.StakeKeeper + storeKey sdk.StoreKey + storeTKey sdk.StoreKey + cdc *codec.Codec + ps params.Setter + bankKeeper types.BankKeeper + stakeKeeper types.StakeKeeper + feeCollectionKeeper types.FeeCollectionKeeper // codespace codespace sdk.CodespaceType } -func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ps params.Setter, ck types.CoinKeeper, - sk types.StakeKeeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ps params.Setter, ck types.BankKeeper, + sk types.StakeKeeper, fck types.FeeCollectionKeeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ - storeKey: key, - storeTKey: tkey, - cdc: cdc, - coinKeeper: ck, - codespace: codespace, + storeKey: key, + storeTKey: tkey, + cdc: cdc, + bankKeeper: ck, + stakeKeeper: sk, + feeCollectionKeeper: fck, + codespace: codespace, } return keeper } diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index eeb5af11d4..4bb02e20c5 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -21,8 +21,9 @@ func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, di.WithdrawalHeight = height accum := delegatorShares.Mul(sdk.NewDec(blocks)) withdrawalTokens := vi.Pool.Mul(accum.Quo(vi.DelAccum.Accum)) + remainingTokens := vi.Pool.Mul(sdk.OneDec().Sub(accum.Quo(vi.DelAccum.Accum))) - vi.Pool = vi.Pool.Sub(withdrawalTokens) + vi.Pool = remainingTokens vi.DelAccum.Accum = vi.DelAccum.Accum.Sub(accum) return di, fp, withdrawalTokens diff --git a/x/distribution/types/keepers.go b/x/distribution/types/keepers.go index 3cf34da2a4..b33e916b87 100644 --- a/x/distribution/types/keepers.go +++ b/x/distribution/types/keepers.go @@ -6,9 +6,10 @@ import sdk "github.com/cosmos/cosmos-sdk/types" type StakeKeeper interface { IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress, fn func(index int64, delegation sdk.Delegation) (stop bool)) - GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress) - GetValidator(ctx sdk.Context, valAddr sdk.AccAddress) - GetPool(ctx sdk.Context) + GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress) sdk.Delegation + GetValidator(ctx sdk.Context, valAddr sdk.AccAddress) sdk.Validator + GetValidatorFromConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) sdk.Validator + TotalPower(ctx sdk.Context) sdk.Dec } // expected coin keeper diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index b2f2592ea3..7c41b7e50f 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -31,13 +31,15 @@ func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBo vi.FeePoolWithdrawalHeight = height accum := sdk.NewDec(blocks).Mul(vdTokens) withdrawalTokens := fp.Pool.Mul(accum.Quo(fp.ValAccum.Accum)) + remainingTokens := fp.Pool.Mul(sdk.OneDec().Sub(accum.Quo(fp.ValAccum.Accum))) + commission := withdrawalTokens.Mul(commissionRate) - afterCommission := withdrawalTokens.Sub(commission) + afterCommission := withdrawalTokens.Mul(sdk.OneDec().Sub(commissionRate)) fp.ValAccum.Accum = fp.ValAccum.Accum.Sub(accum) - fp.Pool = fp.Pool.Sub(withdrawalTokens) - vi.PoolCommission = vi.PoolCommission.Add(commission) - vi.Pool = vi.Pool.Add(afterCommission) + fp.Pool = remainingTokens + vi.PoolCommission = vi.PoolCommission.Plus(commission) + vi.Pool = vi.Pool.Plus(afterCommission) return vi, fp } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 6c5066a783..d7463eb79c 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -477,5 +477,6 @@ func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } func (v Validator) GetTokens() sdk.Dec { return v.Tokens } +func (v Validator) GetCommission() sdk.Dec { return v.Commission } func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } func (v Validator) GetBondHeight() int64 { return v.BondHeight } From 5dabd1bf6da0f90d8cb234589fa1a4924eb0c76b Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 22:54:46 -0400 Subject: [PATCH 27/99] the errors never want to seem to end... --- types/stake.go | 6 ++--- x/distribution/abci_app.go | 4 +++- x/distribution/keeper/allocation.go | 7 +++--- x/distribution/keeper/delegation.go | 34 ++++++++++++++++------------ x/distribution/keeper/genesis.go | 5 ++-- x/distribution/{ => keeper}/hooks.go | 22 +++++++++--------- x/distribution/keeper/keeper.go | 4 ++-- x/distribution/keeper/key.go | 2 +- x/distribution/keeper/validator.go | 25 ++++++++++---------- x/distribution/types/keepers.go | 4 ++-- x/gov/tally.go | 4 ++-- x/stake/types/delegation.go | 2 +- 12 files changed, 63 insertions(+), 56 deletions(-) rename x/distribution/{ => keeper}/hooks.go (84%) diff --git a/types/stake.go b/types/stake.go index 3d5969f9d4..4577e60474 100644 --- a/types/stake.go +++ b/types/stake.go @@ -45,7 +45,7 @@ type Validator interface { GetPower() Dec // validation power GetTokens() Dec // validation tokens GetCommission() Dec // validator commission rate - GetDelegatorShares() Dec // Total out standing delegator shares + GetDelegatorShares() Dec // Total delegator shares GetBondHeight() int64 // height in which the validator became active } @@ -87,8 +87,8 @@ type ValidatorSet interface { // delegation bond for a delegated proof of stake system type Delegation interface { GetDelegator() AccAddress // delegator AccAddress for the bond - GetValidator() ValAddress // validator operator address - GetBondShares() Dec // amount of validator's shares + GetValidator() ValAddress // validator operator address TODO change to GetValAddr + GetShares() Dec // amount of validator's shares } // properties for the set of all delegations for a particular diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index e70252a8de..2ed9af0c0a 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -1,8 +1,10 @@ package distribution import ( - "github.com/cosmos/cosmos-sdk/x/distribution/keeper" 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 diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index a20055bbb4..1c990dc4b5 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -27,14 +27,15 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // apply commission commission := proposerReward.Mul(proserValidator.GetCommission()) - proposerDist.PoolCommission = proposerDist.PoolCommission.Add(commission) - proposerDist.Pool = proposerDist.Pool.Add(proposerReward.Sub(commission)) + remaining := proposerReward.Mul(sdk.OneDec().Sub(proserValidator.GetCommission())) + proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission) + proposerDist.Pool = proposerDist.Pool.Plus(remaining) // allocate community funding communityTax := k.GetCommunityTax(ctx) communityFunding := feesCollectedDec.Mul(communityTax) feePool := k.GetFeePool(ctx) - feePool.CommunityPool = feePool.CommunityPool.Add(communityFunding) + feePool.CommunityPool = feePool.CommunityPool.Plus(communityFunding) // set the global pool within the distribution module poolReceived := feesCollectedDec.Mul(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 1323f2dbc4..9913bfce5d 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -72,9 +72,10 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA delInfo := k.GetDelegatorDistInfo(ctx, delegatorAddr, validatorAddr) valInfo := k.GetValidatorDistInfo(ctx, validatorAddr) validator := k.stakeKeeper.GetValidator(ctx, validatorAddr) + delegation := k.stakeKeeper.GetDelegation(ctx, delegatorAddr, validatorAddr) - delInfo, feePool, withdraw := delInfo.WithdrawRewards(ctx, feePool, valInfo, height, bondedTokens, - validator.Tokens, validator.DelegatorShares, validator.Commission) + delInfo, feePool, withdraw := delInfo.WithdrawRewards(feePool, valInfo, height, bondedTokens, + validator.GetTokens(), validator.GetDelegatorShares(), delegation.GetShares(), validator.GetCommission()) k.SetFeePool(ctx, feePool) withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr) @@ -86,28 +87,31 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA // 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(delegatorAddr) - k.coinsKeeper.AddCoins(withdrawAddr, withdraw.Amount.TruncateDecimal()) + withdraw := k.GetDelegatorRewardsAll(ctx, delegatorAddr, height) + withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr) + k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) } // return all rewards for all delegations of a delegator func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) types.DecCoins { - withdraw := sdk.NewDec(0) - pool := k.sk.GetPool(ctx) + withdraw := types.DecCoins{} + bondedTokens := k.stakeKeeper.TotalPower(ctx) feePool := k.GetFeePool(ctx) // iterate over all the delegations - operationAtDelegation := func(_ int64, del types.Delegation) (stop bool) { - delInfo := k.GetDelegationDistInfo(ctx, delAddr, del.ValidatorAddr) - valInfo := k.GetValidatorDistInfo(ctx, del.ValidatorAddr) - validator := k.sk.GetValidator(ctx, del.ValidatorAddr) + operationAtDelegation := func(_ int64, del sdk.Delegation) (stop bool) { + valAddr := del.GetValidator() + delInfo := k.GetDelegatorDistInfo(ctx, delAddr, valAddr) + valInfo := k.GetValidatorDistInfo(ctx, valAddr) + validator := k.stakeKeeper.GetValidator(ctx, valAddr) + delegation := k.stakeKeeper.GetDelegation(ctx, delAddr, valAddr) - feePool, diWithdraw := delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens, - validator.Tokens, validator.DelegatorShares, validator.Commission) - withdraw = withdraw.Add(diWithdraw) - SetFeePool(feePool) + delInfo, 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.SetDelegatorDistInfo(ctx, delInfo) return false } k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation) diff --git a/x/distribution/keeper/genesis.go b/x/distribution/keeper/genesis.go index dfc6109240..ab010f277e 100644 --- a/x/distribution/keeper/genesis.go +++ b/x/distribution/keeper/genesis.go @@ -40,10 +40,9 @@ func (k Keeper) GetAllDWs(ctx sdk.Context) (dws []types.DelegatorWithdrawInfo) { defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - addr := iterator.Key()[1:] dw := types.DelegatorWithdrawInfo{ - DelegatorAddr: sdk.AccAddress{iterator.Key()}, - WithdrawAddr: sdk.AccAddress{iterator.Value()}, + DelegatorAddr: sdk.AccAddress(iterator.Key()), + WithdrawAddr: sdk.AccAddress(iterator.Value()), } dws = append(dws, dw) } diff --git a/x/distribution/hooks.go b/x/distribution/keeper/hooks.go similarity index 84% rename from x/distribution/hooks.go rename to x/distribution/keeper/hooks.go index 97be985f29..e846acd265 100644 --- a/x/distribution/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -1,4 +1,4 @@ -package distribution +package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" @@ -10,11 +10,11 @@ func (k Keeper) onValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { height := ctx.BlockHeight() vdi := types.ValidatorDistInfo{ - OperatorAddr: addr, - GlobalWithdrawalHeight: height, - Pool: DecCoins{}, - PoolCommission: DecCoins{}, - DelAccum: NewTotalAccum(height), + OperatorAddr: addr, + FeePoolWithdrawalHeight: height, + Pool: types.DecCoins{}, + PoolCommission: types.DecCoins{}, + DelAccum: types.NewTotalAccum(height), } k.SetValidatorDistInfo(ctx, vdi) } @@ -68,20 +68,20 @@ type Hooks struct { func (k Keeper) ValidatorHooks() Hooks { return Hooks{k} } // nolint -func (h Hooks) OnValidatorCreated(ctx sdk.Context, addr sdk.VlAddress) { - v.k.onValidatorCreated(ctx, address) +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) { - v.k.onValidatorCommissionChange(ctx, address) + h.k.onValidatorCommissionChange(ctx, addr) } func (h Hooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { - v.k.onValidatorRemoved(ctx, address) + 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) { - d.k.onDelegationSharesModified(ctx, delAddr, valAddr) + 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) diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index bbf4c15411..31ce345b22 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -91,11 +91,11 @@ func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { // nolint: errcheck func (k Keeper) GetCommunityTax(ctx sdk.Context) sdk.Dec { var communityTax sdk.Dec - keeper.ps.Get(ctx, ParamStoreKeyCommunityTax, &communityTax) + k.ps.Get(ctx, ParamStoreKeyCommunityTax, &communityTax) return communityTax } // nolint: errcheck func (k Keeper) setCommunityTax(ctx sdk.Context, communityTax sdk.Dec) { - keeper.ps.Set(ctx, ParamStoreKeyCommunityTax, &communityTax) + k.ps.Set(ctx, ParamStoreKeyCommunityTax, &communityTax) } diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index f6f93464f6..771343f017 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -23,7 +23,7 @@ func GetValidatorDistInfoKey(operatorAddr sdk.ValAddress) []byte { // gets the key for delegator distribution for a validator // VALUE: distribution/types.DelegatorDistInfo -func GetDelegationDistInfoKey(delAddr sdk.AccAddress, valOperatorAddr sdk.ValAddress) []byte { +func GetDelegationDistInfoKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { return append(GetDelegationDistInfosKey(delAddr), valAddr.Bytes()...) } diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index b8dece32cf..f8e04f0cb8 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -11,7 +11,7 @@ func (k Keeper) GetValidatorDistInfo(ctx sdk.Context, store := ctx.KVStore(k.storeKey) - b := store.Get(GetValidatorDistInfoKey(ctx, operatorAddr)) + b := store.Get(GetValidatorDistInfoKey(operatorAddr)) if b == nil { panic("Stored delegation-distribution info should not have been nil") } @@ -24,13 +24,13 @@ func (k Keeper) GetValidatorDistInfo(ctx sdk.Context, func (k Keeper) SetValidatorDistInfo(ctx sdk.Context, vdi types.ValidatorDistInfo) { store := ctx.KVStore(k.storeKey) b := k.cdc.MustMarshalBinary(vdi) - store.Set(GetValidatorDistInfoKey(ctx, vdi.OperatorAddr), b) + 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(ctx, vdi.OperatorAddr)) + store.Delete(GetValidatorDistInfoKey(valAddr)) } // withdrawal all the validator rewards including the commission @@ -38,19 +38,20 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.Va // withdraw self-delegation height := ctx.BlockHeight() - validator := k.GetValidator(ctx, operatorAddr) - accAddr := sdk.AccAddress{operatorAddr.Bytes()} + validator := k.stakeKeeper.GetValidator(ctx, operatorAddr) + accAddr := sdk.AccAddress(operatorAddr.Bytes()) withdraw := k.GetDelegatorRewardsAll(ctx, accAddr, height) // withdrawal validator commission rewards - pool := k.stakeKeeper.GetPool(ctx) + bondedTokens := k.stakeKeeper.TotalPower(ctx) valInfo := k.GetValidatorDistInfo(ctx, operatorAddr) feePool := k.GetFeePool(ctx) - feePool, commission := valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens, - validator.Tokens, validator.Commission) - withdraw = withdraw.Add(commission) - k.SetFeePool(feePool) + 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(accAddr) - k.coinKeeper.AddCoins(withdrawAddr, withdraw.TruncateDecimal()) + withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, accAddr) + k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) } diff --git a/x/distribution/types/keepers.go b/x/distribution/types/keepers.go index b33e916b87..14ea30dc0f 100644 --- a/x/distribution/types/keepers.go +++ b/x/distribution/types/keepers.go @@ -6,8 +6,8 @@ import sdk "github.com/cosmos/cosmos-sdk/types" type StakeKeeper interface { IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress, fn func(index int64, delegation sdk.Delegation) (stop bool)) - GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress) sdk.Delegation - GetValidator(ctx sdk.Context, valAddr sdk.AccAddress) sdk.Validator + GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) sdk.Delegation + GetValidator(ctx sdk.Context, valAddr sdk.ValAddress) sdk.Validator GetValidatorFromConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) sdk.Validator TotalPower(ctx sdk.Context) sdk.Dec } diff --git a/x/gov/tally.go b/x/gov/tally.go index a756eaf926..55fd81da24 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -53,10 +53,10 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall valAddrStr := delegation.GetValidator().String() if val, ok := currValidators[valAddrStr]; ok { - val.Minus = val.Minus.Add(delegation.GetBondShares()) + val.Minus = val.Minus.Add(delegation.GetShares()) currValidators[valAddrStr] = val - delegatorShare := delegation.GetBondShares().Quo(val.DelegatorShares) + delegatorShare := delegation.GetShares().Quo(val.DelegatorShares) votingPower := val.Power.Mul(delegatorShare) results[vote.Option] = results[vote.Option].Add(votingPower) diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 38a94c3695..57ac70a571 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -89,7 +89,7 @@ var _ sdk.Delegation = Delegation{} // nolint - for sdk.Delegation func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr } func (d Delegation) GetValidator() sdk.ValAddress { return d.ValidatorAddr } -func (d Delegation) GetBondShares() sdk.Dec { return d.Shares } +func (d Delegation) GetShares() sdk.Dec { return d.Shares } // HumanReadableString returns a human readable string representation of a // Delegation. An error is returned if the Delegation's delegator or validator From 5790f33159744ee48d72c7448719eda3f281145d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 19 Sep 2018 23:01:55 -0400 Subject: [PATCH 28/99] ... --- cmd/gaia/app/app.go | 2 +- x/distribution/abci_app.go | 4 ++-- x/distribution/alias.go | 10 ++++++---- x/distribution/genesis.go | 6 +++--- x/distribution/handler.go | 6 +++--- x/distribution/types/msg.go | 4 ++-- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 5b1dbd6722..d3692dce01 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -254,7 +254,7 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val // Combined Staking Hooks type Hooks struct { dh distr.Hooks - sh slashing.ValidatorHooks + sh slashing.Hooks } func NewHooks(dh distr.Hooks, sh slashing.ValidatorHooks) Hooks { diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index 2ed9af0c0a..648d70a5dc 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -9,8 +9,8 @@ import ( // set the proposer for determining distribution during endblock func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) { - consAddr := sdk.ConsAddress{req.Header.Proposer.Address} - k.SetProposerConsAddr(consAddr) + consAddr := sdk.ConsAddress(req.Header.Proposer.Address) + k.SetProposerConsAddr(ctx, consAddr) } // allocate fees diff --git a/x/distribution/alias.go b/x/distribution/alias.go index 898a07714a..920be5d3ee 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -9,7 +9,9 @@ import ( ) type ( - Keeper = keeper.Keeper + Keeper = keeper.Keeper + Hooks = keeper.Hooks + DelegatorWithdrawInfo = types.DelegatorWithdrawInfo DelegatorDistInfo = types.DelegatorDistInfo ValidatorDistInfo = types.ValidatorDistInfo @@ -18,7 +20,7 @@ type ( MsgSetWithdrawAddress = types.MsgSetWithdrawAddress MsgWithdrawDelegatorRewardsAll = types.MsgWithdrawDelegatorRewardsAll - MsgWithdrawDelegationReward = types.MsgWithdrawDelegationReward + MsgWithdrawDelegatorReward = types.MsgWithdrawDelegatorReward MsgWithdrawValidatorRewardsAll = types.MsgWithdrawValidatorRewardsAll GenesisState = types.GenesisState @@ -47,7 +49,7 @@ var ( NewMsgSetWithdrawAddress = types.NewMsgSetWithdrawAddress NewMsgWithdrawDelegatorRewardsAll = types.NewMsgWithdrawDelegatorRewardsAll - NewMsgWithdrawDelegationReward = types.NewMsgWithdrawDelegationReward + NewMsgWithdrawDelegationReward = types.NewMsgWithdrawDelegatorReward NewMsgWithdrawValidatorRewardsAll = types.NewMsgWithdrawValidatorRewardsAll ) @@ -69,6 +71,6 @@ var ( ActionWithdrawValidatorRewardsAll = tags.ActionWithdrawValidatorRewardsAll TagAction = tags.Action - TagValidator = tags.SrcValidator + TagValidator = tags.Validator TagDelegator = tags.Delegator ) diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index 045c840ed9..c7636c80c0 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -2,7 +2,7 @@ package distribution import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/stake/types" + "github.com/cosmos/cosmos-sdk/x/distribution/types" ) // InitGenesis sets distribution information for genesis @@ -15,7 +15,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { for _, ddi := range data.DelegatorDistInfos { keeper.SetDelegatorDistInfo(ctx, ddi) } - for _, dw := range data.DelegatorWithdrawAddrs { + for _, dw := range data.DelegatorWithdrawInfos { keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr) } } @@ -32,6 +32,6 @@ func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { FeePool: feePool, ValidatorDistInfos: vdis, DelegatorDistInfos: ddis, - DelegatorWithdrawAddrs: dws, + DelegatorWithdrawInfos: dws, } } diff --git a/x/distribution/handler.go b/x/distribution/handler.go index 1ae74ac78e..661d7d32aa 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -11,7 +11,7 @@ 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.MsgModifyWithdrawAddress: + case types.MsgSetWithdrawAddress: return handleMsgModifyWithdrawAddress(ctx, msg, k) case types.MsgWithdrawDelegatorRewardsAll: return handleMsgWithdrawDelegatorRewardsAll(ctx, msg, k) @@ -30,9 +30,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler { // These functions assume everything has been authenticated, // now we just perform action and save -func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgModifyWithdrawAddress, k keeper.Keeper) sdk.Result { +func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAddress, k keeper.Keeper) sdk.Result { - k.SetDelegatorWithdrawAddr(ctx, msg.DelegatorAddr, msg.WithdrawAddress) + k.SetDelegatorWithdrawAddr(ctx, msg.DelegatorAddr, msg.WithdrawAddr) tags := sdk.NewTags( tags.Action, tags.ActionModifyWithdrawAddress, diff --git a/x/distribution/types/msg.go b/x/distribution/types/msg.go index 6b4997fef6..a98892ee99 100644 --- a/x/distribution/types/msg.go +++ b/x/distribution/types/msg.go @@ -62,7 +62,7 @@ type MsgWithdrawDelegatorRewardsAll struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` } -func NewMsgWithdrawDelegationRewardsAll(delAddr sdk.AccAddress) MsgWithdrawDelegatorRewardsAll { +func NewMsgWithdrawDelegatorRewardsAll(delAddr sdk.AccAddress) MsgWithdrawDelegatorRewardsAll { return MsgWithdrawDelegatorRewardsAll{ DelegatorAddr: delAddr, } @@ -101,7 +101,7 @@ type MsgWithdrawDelegatorReward struct { ValidatorAddr sdk.ValAddress `json:"validator_addr"` } -func NewMsgWithdrawDelegationReward(delAddr sdk.AccAddress, valAddr sdk.ValAddress) MsgWithdrawDelegatorReward { +func NewMsgWithdrawDelegatorReward(delAddr sdk.AccAddress, valAddr sdk.ValAddress) MsgWithdrawDelegatorReward { return MsgWithdrawDelegatorReward{ DelegatorAddr: delAddr, ValidatorAddr: valAddr, From 251a81f589814fbbd4dcbddfa14a78aa24903d00 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 00:53:48 -0400 Subject: [PATCH 29/99] yay it compiles --- cmd/gaia/app/app.go | 25 +++++++++++++++---------- cmd/gaia/cmd/gaiacli/main.go | 5 +++-- x/distribution/alias.go | 8 +++++--- x/distribution/client/cli/tx.go | 25 ++++++++++++++----------- x/distribution/keeper/allocation.go | 2 +- x/distribution/keeper/delegation.go | 8 ++++---- x/distribution/keeper/hooks.go | 2 +- x/distribution/keeper/validator.go | 2 +- x/distribution/types/keepers.go | 6 +++--- 9 files changed, 47 insertions(+), 36 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index d3692dce01..5b544af3ec 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -97,24 +97,29 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio ) // add handlers + app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) app.bankKeeper = bank.NewBaseKeeper(app.accountMapper) app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace)) app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) - app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) - app.distrKeeper = distr.NewKeeper(app.cdc, app.keyDistr, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) - app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) - app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) - app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) + app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, + app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.distrKeeper = distr.NewKeeper(app.cdc, app.keyDistr, app.tkeyStake, + app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, + app.feeCollectionKeeper, app.RegisterCodespace(stake.DefaultCodespace)) + app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, + app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) + app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), + app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) // register the staking hooks - app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(NewHooks(app.distrKeeper.Hooks(), app.slashingKeeper.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("ibc", ibc.NewHandler(app.ibcMapper, app.bankKeeper)). AddRoute("stake", stake.NewHandler(app.stakeKeeper)). - AddRoute("distr", stake.NewHandler(app.distrKeeper)). + AddRoute("distr", distr.NewHandler(app.distrKeeper)). AddRoute("slashing", slashing.NewHandler(app.slashingKeeper)). AddRoute("gov", gov.NewHandler(app.govKeeper)) @@ -257,7 +262,7 @@ type Hooks struct { sh slashing.Hooks } -func NewHooks(dh distr.Hooks, sh slashing.ValidatorHooks) Hooks { +func NewHooks(dh distr.Hooks, sh slashing.Hooks) Hooks { return Hooks{dh, sh} } @@ -276,8 +281,8 @@ func (h Hooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { func (h Hooks) OnValidatorBonded(ctx sdk.Context, addr sdk.ConsAddress) { h.sh.OnValidatorBonded(ctx, addr) } -func (h Hooks) OnValidatorBeginBonded(ctx sdk.Context, addr sdk.ConsAddress) { - h.sh.OnValidatorBeginBonding(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) diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index 166359201a..61eeeeac8e 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -13,6 +13,7 @@ import ( "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" + distr "github.com/cosmos/cosmos-sdk/x/distribution" govcmd "github.com/cosmos/cosmos-sdk/x/gov/client/cli" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli" @@ -108,8 +109,8 @@ func main() { } distrCmd.AddCommand( client.PostCommands( - stakecmd.GetCmdWithdrawDelegationRewardsAll(cdc), - stakecmd.GetCmdSetWithdrawAddr(cdc), + distr.GetCmdWithdrawRewards(cdc), + distr.GetCmdSetWithdrawAddr(cdc), )...) rootCmd.AddCommand( distrCmd, diff --git a/x/distribution/alias.go b/x/distribution/alias.go index 920be5d3ee..e7af73fba3 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -2,10 +2,10 @@ package distribution import ( + "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" "github.com/cosmos/cosmos-sdk/x/distribution/keeper" "github.com/cosmos/cosmos-sdk/x/distribution/tags" "github.com/cosmos/cosmos-sdk/x/distribution/types" - "github.com/cosmos/cosmos-sdk/x/stake/querier" ) type ( @@ -27,8 +27,7 @@ type ( ) var ( - NewKeeper = keeper.NewKeeper - NewQuerier = querier.NewQuerier + NewKeeper = keeper.NewKeeper GetValidatorDistInfoKey = keeper.GetValidatorDistInfoKey GetDelegationDistInfoKey = keeper.GetDelegationDistInfoKey @@ -51,6 +50,9 @@ var ( NewMsgWithdrawDelegatorRewardsAll = types.NewMsgWithdrawDelegatorRewardsAll NewMsgWithdrawDelegationReward = types.NewMsgWithdrawDelegatorReward NewMsgWithdrawValidatorRewardsAll = types.NewMsgWithdrawValidatorRewardsAll + + GetCmdWithdrawRewards = cli.GetCmdWithdrawRewards + GetCmdSetWithdrawAddr = cli.GetCmdSetWithdrawAddr ) const ( diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 37330634e9..2cf293d89d 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -12,7 +12,10 @@ import ( "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - distr "github.com/cosmos/cosmos-sdk/x/distribution" + 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 ( @@ -21,7 +24,7 @@ var ( ) // command to withdraw rewards -func GetCmdWithdrawDelegationRewardsAll(cdc *codec.Codec) *cobra.Command { +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", @@ -36,7 +39,7 @@ func GetCmdWithdrawDelegationRewardsAll(cdc *codec.Codec) *cobra.Command { flagOnlyFromValidator, flagIsValidator) } - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -49,8 +52,8 @@ func GetCmdWithdrawDelegationRewardsAll(cdc *codec.Codec) *cobra.Command { if err != nil { return err } - valAddr := sdk.ValAddress{addr.Bytes()} - msg := distr.NewMsgWithdrawValidatorRewardsAll(valAddr) + valAddr := sdk.ValAddress(addr.Bytes()) + msg = types.NewMsgWithdrawValidatorRewardsAll(valAddr) case onlyFromVal != "": delAddr, err := cliCtx.GetFromAddress() if err != nil { @@ -62,17 +65,17 @@ func GetCmdWithdrawDelegationRewardsAll(cdc *codec.Codec) *cobra.Command { return err } - msg := distr.NewMsgWithdrawDelegationReward(delAddr, valAddr) + msg = types.NewMsgWithdrawDelegatorReward(delAddr, valAddr) default: delAddr, err := cliCtx.GetFromAddress() if err != nil { return err } - msg := distr.NewMsgWithdrawDelegationRewardsAll(delAddr) + msg = types.NewMsgWithdrawDelegatorRewardsAll(delAddr) } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } cmd.Flags().String(flagOnlyFromValidator, "", "only withdraw from this validator address (in bech)") @@ -88,7 +91,7 @@ func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). WithLogger(os.Stdout). @@ -104,10 +107,10 @@ func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command { return err } - msg := distr.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) + msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg}) + return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } return cmd diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 1c990dc4b5..8cc61dcad5 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -10,7 +10,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) - proserValidator := k.stakeKeeper.GetValidatorFromConsAddr(ctx, proposerConsAddr) + proserValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) proposerDist := k.GetValidatorDistInfo(ctx, proserValidator.GetOperator()) // get the fees which have been getting collected through all the diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 9913bfce5d..34caa5c1a9 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -71,8 +71,8 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA feePool := k.GetFeePool(ctx) delInfo := k.GetDelegatorDistInfo(ctx, delegatorAddr, validatorAddr) valInfo := k.GetValidatorDistInfo(ctx, validatorAddr) - validator := k.stakeKeeper.GetValidator(ctx, validatorAddr) - delegation := k.stakeKeeper.GetDelegation(ctx, delegatorAddr, validatorAddr) + validator := k.stakeKeeper.Validator(ctx, validatorAddr) + delegation := k.stakeKeeper.Delegation(ctx, delegatorAddr, validatorAddr) delInfo, feePool, withdraw := delInfo.WithdrawRewards(feePool, valInfo, height, bondedTokens, validator.GetTokens(), validator.GetDelegatorShares(), delegation.GetShares(), validator.GetCommission()) @@ -104,8 +104,8 @@ func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, valAddr := del.GetValidator() delInfo := k.GetDelegatorDistInfo(ctx, delAddr, valAddr) valInfo := k.GetValidatorDistInfo(ctx, valAddr) - validator := k.stakeKeeper.GetValidator(ctx, valAddr) - delegation := k.stakeKeeper.GetDelegation(ctx, delAddr, valAddr) + validator := k.stakeKeeper.Validator(ctx, valAddr) + delegation := k.stakeKeeper.Delegation(ctx, delAddr, valAddr) delInfo, feePool, diWithdraw := delInfo.WithdrawRewards(feePool, valInfo, height, bondedTokens, validator.GetTokens(), validator.GetDelegatorShares(), delegation.GetShares(), validator.GetCommission()) diff --git a/x/distribution/keeper/hooks.go b/x/distribution/keeper/hooks.go index e846acd265..f13daf03af 100644 --- a/x/distribution/keeper/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -65,7 +65,7 @@ type Hooks struct { } // New Validator Hooks -func (k Keeper) ValidatorHooks() Hooks { return Hooks{k} } +func (k Keeper) Hooks() Hooks { return Hooks{k} } // nolint func (h Hooks) OnValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index f8e04f0cb8..0b58ca68c9 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -38,7 +38,7 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.Va // withdraw self-delegation height := ctx.BlockHeight() - validator := k.stakeKeeper.GetValidator(ctx, operatorAddr) + validator := k.stakeKeeper.Validator(ctx, operatorAddr) accAddr := sdk.AccAddress(operatorAddr.Bytes()) withdraw := k.GetDelegatorRewardsAll(ctx, accAddr, height) diff --git a/x/distribution/types/keepers.go b/x/distribution/types/keepers.go index 14ea30dc0f..31a68a5da9 100644 --- a/x/distribution/types/keepers.go +++ b/x/distribution/types/keepers.go @@ -6,9 +6,9 @@ import sdk "github.com/cosmos/cosmos-sdk/types" type StakeKeeper interface { IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress, fn func(index int64, delegation sdk.Delegation) (stop bool)) - GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) sdk.Delegation - GetValidator(ctx sdk.Context, valAddr sdk.ValAddress) sdk.Validator - GetValidatorFromConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) sdk.Validator + Delegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) sdk.Delegation + Validator(ctx sdk.Context, valAddr sdk.ValAddress) sdk.Validator + ValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) sdk.Validator TotalPower(ctx sdk.Context) sdk.Dec } From d36030424ee5fb2d58f37cf43f422b4d8467c440 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 15:36:32 -0400 Subject: [PATCH 30/99] breakout use of GetValidatorByConsAddr --- types/stake.go | 7 ++++--- x/gov/handler.go | 2 +- x/slashing/handler.go | 8 ++++---- x/slashing/keeper.go | 36 ++++++++++++++++++------------------ x/stake/handler.go | 2 +- x/stake/keeper/sdk_types.go | 10 ++++++++++ x/stake/keeper/slash.go | 33 ++++++++++++--------------------- x/stake/keeper/slash_test.go | 36 ++++++++++++++++++------------------ x/stake/keeper/validator.go | 15 ++++++++++++++- x/stake/types/validator.go | 21 +++++++++++---------- 10 files changed, 93 insertions(+), 77 deletions(-) diff --git a/types/stake.go b/types/stake.go index 4577e60474..d97001cfb2 100644 --- a/types/stake.go +++ b/types/stake.go @@ -42,6 +42,7 @@ type Validator interface { GetStatus() BondStatus // status of the validator GetOperator() ValAddress // operator address to receive/return validators coins GetPubKey() crypto.PubKey // validation pubkey + GetConsAddr() ConsAddress // validation consensus address GetPower() Dec // validation power GetTokens() Dec // validation tokens GetCommission() Dec // validator commission rate @@ -73,9 +74,9 @@ type ValidatorSet interface { TotalPower(Context) Dec // total power of the validator set // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction - Slash(Context, crypto.PubKey, int64, int64, Dec) - Jail(Context, crypto.PubKey) // jail a validator - Unjail(Context, crypto.PubKey) // unjail a validator + Slash(Context, ConsAddress, int64, int64, Dec) + Jail(Context, ConsAddress) // jail a validator + Unjail(Context, ConsAddress) // unjail a validator // Delegation allows for getting a particular delegation for a given validator // and delegator outside the scope of the staking module. diff --git a/x/gov/handler.go b/x/gov/handler.go index c996749265..84964b20f6 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -155,7 +155,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { for _, valAddr := range nonVotingVals { val := keeper.ds.GetValidatorSet().Validator(ctx, valAddr) keeper.ds.GetValidatorSet().Slash(ctx, - val.GetPubKey(), + val.GetConsAddr(), ctx.BlockHeight(), val.GetPower().RoundInt64(), keeper.GetTallyingProcedure(ctx).GovernancePenalty) diff --git a/x/slashing/handler.go b/x/slashing/handler.go index c43ed6be61..4f342f62a0 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -34,9 +34,9 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { return ErrValidatorNotJailed(k.codespace).Result() } - addr := sdk.ConsAddress(validator.GetPubKey().Address()) + consAddr := sdk.ConsAddress(validator.GetPubKey().Address()) - info, found := k.getValidatorSigningInfo(ctx, addr) + info, found := k.getValidatorSigningInfo(ctx, consAddr) if !found { return ErrNoValidatorForAddress(k.codespace).Result() } @@ -49,9 +49,9 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { // update the starting height so the validator can't be immediately jailed // again info.StartHeight = ctx.BlockHeight() - k.setValidatorSigningInfo(ctx, addr, info) + k.setValidatorSigningInfo(ctx, consAddr, info) - k.validatorSet.Unjail(ctx, validator.GetPubKey()) + k.validatorSet.Unjail(ctx, consAddr) tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String())) diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 468f941630..3506d27416 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -40,10 +40,10 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio logger := ctx.Logger().With("module", "x/slashing") time := ctx.BlockHeader().Time age := time.Sub(timestamp) - address := sdk.ConsAddress(addr) + consAddr := sdk.ConsAddress(addr) pubkey, err := k.getPubkey(ctx, addr) if err != nil { - panic(fmt.Sprintf("Validator address %v not found", addr)) + panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr)) } // Double sign too old @@ -59,22 +59,22 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio // Cap the amount slashed to the penalty for the worst infraction // within the slashing period when this infraction was committed fraction := k.SlashFractionDoubleSign(ctx) - revisedFraction := k.capBySlashingPeriod(ctx, address, fraction, infractionHeight) + revisedFraction := k.capBySlashingPeriod(ctx, consAddr, fraction, infractionHeight) logger.Info(fmt.Sprintf("Fraction slashed capped by slashing period from %v to %v", fraction, revisedFraction)) // Slash validator - k.validatorSet.Slash(ctx, pubkey, infractionHeight, power, revisedFraction) + k.validatorSet.Slash(ctx, consAddr, infractionHeight, power, revisedFraction) // Jail validator - k.validatorSet.Jail(ctx, pubkey) + k.validatorSet.Jail(ctx, consAddr) // Set validator jail duration - signInfo, found := k.getValidatorSigningInfo(ctx, address) + signInfo, found := k.getValidatorSigningInfo(ctx, consAddr) if !found { - panic(fmt.Sprintf("Expected signing info for validator %s but not found", address)) + panic(fmt.Sprintf("Expected signing info for validator %s but not found", consAddr)) } signInfo.JailedUntil = time.Add(k.DoubleSignUnbondDuration(ctx)) - k.setValidatorSigningInfo(ctx, address, signInfo) + k.setValidatorSigningInfo(ctx, consAddr, signInfo) } // handle a validator signature, must be called once per validator per block @@ -82,14 +82,14 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) { logger := ctx.Logger().With("module", "x/slashing") height := ctx.BlockHeight() - address := sdk.ConsAddress(addr) + consAddr := sdk.ConsAddress(addr) pubkey, err := k.getPubkey(ctx, addr) if err != nil { - panic(fmt.Sprintf("Validator address %v not found", addr)) + panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr)) } // Local index, so counts blocks validator *should* have signed // Will use the 0-value default signing info if not present, except for start height - signInfo, found := k.getValidatorSigningInfo(ctx, address) + signInfo, found := k.getValidatorSigningInfo(ctx, consAddr) if !found { // If this validator has never been seen before, construct a new SigningInfo with the correct start height signInfo = NewValidatorSigningInfo(height, 0, time.Unix(0, 0), 0) @@ -100,16 +100,16 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p // Update signed block bit array & counter // This counter just tracks the sum of the bit array // That way we avoid needing to read/write the whole array each time - previous := k.getValidatorSigningBitArray(ctx, address, index) + previous := k.getValidatorSigningBitArray(ctx, consAddr, index) if previous == signed { // Array value at this index has not changed, no need to update counter } else if previous && !signed { // Array value has changed from signed to unsigned, decrement counter - k.setValidatorSigningBitArray(ctx, address, index, false) + k.setValidatorSigningBitArray(ctx, consAddr, index, false) signInfo.SignedBlocksCounter-- } else if !previous && signed { // Array value has changed from unsigned to signed, increment counter - k.setValidatorSigningBitArray(ctx, address, index, true) + k.setValidatorSigningBitArray(ctx, consAddr, index, true) signInfo.SignedBlocksCounter++ } @@ -118,13 +118,13 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p } minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx) if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) { - validator := k.validatorSet.ValidatorByConsAddr(ctx, address) + validator := k.validatorSet.ValidatorByConsAddr(ctx, consAddr) if validator != nil && !validator.GetJailed() { // Downtime confirmed: slash and jail the validator logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d", pubkey.Address(), minHeight, k.MinSignedPerWindow(ctx))) - k.validatorSet.Slash(ctx, pubkey, height, power, k.SlashFractionDowntime(ctx)) - k.validatorSet.Jail(ctx, pubkey) + k.validatorSet.Slash(ctx, consAddr, height, power, k.SlashFractionDowntime(ctx)) + k.validatorSet.Jail(ctx, consAddr) signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx)) } else { // Validator was (a) not found or (b) already jailed, don't slash @@ -134,7 +134,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p } // Set the updated signing info - k.setValidatorSigningInfo(ctx, address, signInfo) + k.setValidatorSigningInfo(ctx, consAddr, signInfo) } // AddValidators adds the validators to the keepers validator addr to pubkey mapping. diff --git a/x/stake/handler.go b/x/stake/handler.go index c9955f1bfa..005b3af7d0 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -68,7 +68,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k if found { return ErrValidatorOwnerExists(k.Codespace()).Result() } - _, found = k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(msg.PubKey.Address())) + _, found = k.GetValidatorByConsPubKey(ctx, msg.PubKey) if found { return ErrValidatorPubKeyExists(k.Codespace()).Result() } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index d702e845da..9872630a4e 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" + "github.com/tendermint/tendermint/crypto" ) // Implements ValidatorSet @@ -66,6 +67,15 @@ func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) sdk.V return val } +// get the sdk.validator for a particular pubkey +func (k Keeper) ValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) sdk.Validator { + val, found := k.GetValidatorByConsPubKey(ctx, consPubKey) + if !found { + return nil + } + return val +} + // total power from the bond func (k Keeper) TotalPower(ctx sdk.Context) sdk.Dec { pool := k.GetPool(ctx) diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index e45c458f77..ea378678ae 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -5,7 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/x/stake/types" - "github.com/tendermint/tendermint/crypto" ) // Slash a validator for an infraction committed at a known height @@ -24,7 +23,7 @@ import ( // not at a height in the future // // nolint: gocyclo -func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Dec) { +func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeight int64, power int64, slashFactor sdk.Dec) { logger := ctx.Logger().With("module", "x/stake") if slashFactor.LT(sdk.ZeroDec()) { @@ -36,7 +35,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // ref https://github.com/cosmos/cosmos-sdk/issues/1348 // ref https://github.com/cosmos/cosmos-sdk/issues/1471 - validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(pubkey.Address())) + validator, found := k.GetValidatorByConsAddr(ctx, consAddr) if !found { // If not found, the validator must have been overslashed and removed - so we don't need to do anything // NOTE: Correctness dependent on invariant that unbonding delegations / redelegations must also have been completely @@ -44,7 +43,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // Log the slash attempt for future reference (maybe we should tag it too) logger.Error(fmt.Sprintf( "WARNING: Ignored attempt to slash a nonexistent validator with address %s, we recommend you investigate immediately", - pubkey.Address())) + consAddr)) return } @@ -125,36 +124,28 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in } // jail a validator -func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) { - k.setJailed(ctx, pubkey, true) - validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String()) - if err != nil { - panic(err.Error()) - } +func (k Keeper) Jail(ctx sdk.Context, consAddr sdk.ConsAddress) { + k.setJailed(ctx, consAddr, true) logger := ctx.Logger().With("module", "x/stake") - logger.Info(fmt.Sprintf("validator %s jailed", validatorAddr)) + logger.Info(fmt.Sprintf("validator %s jailed", consAddr)) // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 return } // unjail a validator -func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { - k.setJailed(ctx, pubkey, false) - validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String()) - if err != nil { - panic(err.Error()) - } +func (k Keeper) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) { + k.setJailed(ctx, consAddr, false) logger := ctx.Logger().With("module", "x/stake") - logger.Info(fmt.Sprintf("validator %s unjailed", validatorAddr)) + logger.Info(fmt.Sprintf("validator %s unjailed", consAddr)) // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 return } // set the jailed flag on a validator -func (k Keeper) setJailed(ctx sdk.Context, pubkey crypto.PubKey, isJailed bool) { - validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(pubkey.Address())) +func (k Keeper) setJailed(ctx sdk.Context, consAddr sdk.ConsAddress, isJailed bool) { + validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(consAddr)) if !found { - panic(fmt.Errorf("validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed)) + panic(fmt.Errorf("validator with consensus-Address %s not found, cannot set jailed to %v", consAddr, isJailed)) } validator.Jailed = isJailed k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index 65bac2d808..caed72ff55 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -27,7 +27,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) { validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) validator = keeper.UpdateValidator(ctx, validator) - keeper.SetValidatorByPubKeyIndex(ctx, validator) + keeper.SetValidatorByConsAddr(ctx, validator) } pool = keeper.GetPool(ctx) @@ -191,12 +191,12 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) { fraction := sdk.NewDecWithPrec(5, 1) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) keeper.Slash(ctx, pk, ctx.BlockHeight(), 10, fraction) // read updated state - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) newPool := keeper.GetPool(ctx) @@ -227,7 +227,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // slash validator for the first time ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) keeper.Slash(ctx, pk, 10, 10, fraction) @@ -241,7 +241,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) // power decreased by 3 - 6 stake originally bonded at the time of infraction // was still bonded at the time of discovery and was slashed by half, 4 stake @@ -261,7 +261,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned again require.Equal(t, int64(6), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) // power decreased by 3 again require.Equal(t, sdk.NewDec(4), validator.GetPower()) @@ -281,7 +281,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned again require.Equal(t, int64(9), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) // power decreased by 3 again require.Equal(t, sdk.NewDec(1), validator.GetPower()) @@ -303,7 +303,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // read updated validator // power decreased by 1 again, validator is out of stake // ergo validator should have been removed from the store - _, found = keeper.GetValidatorByPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.False(t, found) } @@ -343,7 +343,7 @@ func TestSlashWithRedelegation(t *testing.T) { // slash validator ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) keeper.Slash(ctx, pk, 10, 10, fraction) @@ -357,7 +357,7 @@ func TestSlashWithRedelegation(t *testing.T) { // bonded tokens burned require.Equal(t, int64(5), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) // power decreased by 2 - 4 stake originally bonded at the time of infraction // was still bonded at the time of discovery and was slashed by half, 4 stake @@ -367,7 +367,7 @@ func TestSlashWithRedelegation(t *testing.T) { // slash the validator again ctx = ctx.WithBlockHeight(12) - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) }) @@ -381,14 +381,14 @@ func TestSlashWithRedelegation(t *testing.T) { // seven bonded tokens burned require.Equal(t, int64(12), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) // power decreased by 4 require.Equal(t, sdk.NewDec(4), validator.GetPower()) // slash the validator again, by 100% ctx = ctx.WithBlockHeight(12) - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) @@ -403,14 +403,14 @@ func TestSlashWithRedelegation(t *testing.T) { require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator // validator decreased to zero power, should have been removed from the store - _, found = keeper.GetValidatorByPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.False(t, found) // slash the validator again, by 100% // no stake remains to be slashed ctx = ctx.WithBlockHeight(12) // validator no longer in the store - _, found = keeper.GetValidatorByPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.False(t, found) keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) @@ -425,7 +425,7 @@ func TestSlashWithRedelegation(t *testing.T) { require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator // power still zero, still not in the store - _, found = keeper.GetValidatorByPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsPubKey(ctx, pk) require.False(t, found) } @@ -472,7 +472,7 @@ func TestSlashBoth(t *testing.T) { // slash validator ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByPubKey(ctx, PKs[0]) + validator, found := keeper.GetValidatorByConsPubkey(ctx, PKs[0]) require.True(t, found) keeper.Slash(ctx, PKs[0], 10, 10, fraction) @@ -488,7 +488,7 @@ func TestSlashBoth(t *testing.T) { // bonded tokens burned require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0]) + validator, found = keeper.GetValidatorByConsPubKey(ctx, PKs[0]) require.True(t, found) // power not decreased, all stake was bonded since require.Equal(t, sdk.NewDec(10), validator.GetPower()) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 766f3fc8f1..af7d77e207 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -6,6 +6,7 @@ import ( "fmt" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" @@ -57,7 +58,7 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty return validator, true } -// get a single validator by pubkey +// get a single validator by consensus address func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) { store := ctx.KVStore(k.storeKey) opAddr := store.Get(GetValidatorByConsAddrKey(consAddr)) @@ -67,6 +68,17 @@ func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress return k.GetValidator(ctx, opAddr) } +// get a single validator by pubkey +func (k Keeper) GetValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) (validator types.Validator, found bool) { + store := ctx.KVStore(k.storeKey) + consAddr := sdk.ConsAddress(consPubKey.Address()) + opAddr := store.Get(GetValidatorByConsAddrKey(consAddr)) + if opAddr == nil { + return validator, false + } + return k.GetValidator(ctx, opAddr) +} + // set the main record holding validator details func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) @@ -75,6 +87,7 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { } // validator index +// TODO change to SetValidatorByConsAddr? used for retrieving from ConsPubkey as well- kinda confusing func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) consAddr := sdk.ConsAddress(validator.OperatorAddr.Bytes()) diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index d7463eb79c..c15d43396c 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -470,13 +470,14 @@ func (v Validator) IsUnbonded(ctx sdk.Context) bool { var _ sdk.Validator = Validator{} // nolint - for sdk.Validator -func (v Validator) GetJailed() bool { return v.Jailed } -func (v Validator) GetMoniker() string { return v.Description.Moniker } -func (v Validator) GetStatus() sdk.BondStatus { return v.Status } -func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } -func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } -func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } -func (v Validator) GetTokens() sdk.Dec { return v.Tokens } -func (v Validator) GetCommission() sdk.Dec { return v.Commission } -func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } -func (v Validator) GetBondHeight() int64 { return v.BondHeight } +func (v Validator) GetJailed() bool { return v.Jailed } +func (v Validator) GetMoniker() string { return v.Description.Moniker } +func (v Validator) GetStatus() sdk.BondStatus { return v.Status } +func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } +func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } +func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) } +func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } +func (v Validator) GetTokens() sdk.Dec { return v.Tokens } +func (v Validator) GetCommission() sdk.Dec { return v.Commission } +func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } +func (v Validator) GetBondHeight() int64 { return v.BondHeight } From 0d9105cf7c27b404e986eddde41a77d14506390e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 20:10:26 -0400 Subject: [PATCH 31/99] ... --- cmd/gaia/app/app.go | 4 +- cmd/gaia/cmd/gaiacli/main.go | 6 +-- examples/democoin/mock/validator.go | 23 ++++++++-- types/stake.go | 7 +-- x/distribution/alias.go | 4 -- x/gov/tally_test.go | 2 +- x/slashing/hooks.go | 10 +++++ x/slashing/keeper.go | 1 + x/slashing/keeper_test.go | 47 +++++++++++--------- x/slashing/tick_test.go | 2 +- x/stake/handler_test.go | 17 ++++--- x/stake/keeper/slash_test.go | 69 +++++++++++++++-------------- x/stake/keeper/validator_test.go | 5 ++- 13 files changed, 115 insertions(+), 82 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 5b544af3ec..41f91c6029 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -132,9 +132,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper)) - app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, + app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, 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) err := app.LoadLatestVersion(app.keyMain) if err != nil { cmn.Exit(err.Error()) diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index 61eeeeac8e..d178f04847 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -13,7 +13,7 @@ import ( "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" - distr "github.com/cosmos/cosmos-sdk/x/distribution" + distrcmd "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" govcmd "github.com/cosmos/cosmos-sdk/x/gov/client/cli" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli" @@ -109,8 +109,8 @@ func main() { } distrCmd.AddCommand( client.PostCommands( - distr.GetCmdWithdrawRewards(cdc), - distr.GetCmdSetWithdrawAddr(cdc), + distrcmd.GetCmdWithdrawRewards(cdc), + distrcmd.GetCmdSetWithdrawAddr(cdc), )...) rootCmd.AddCommand( distrCmd, diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index 9f84786adf..fd5ec85b14 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -28,6 +28,11 @@ func (v Validator) GetPubKey() crypto.PubKey { return nil } +// Implements sdk.Validator +func (v Validator) GetConsAddr() sdk.ConsAddress { + return sdk.ConsAddress{} +} + // Implements sdk.Validator func (v Validator) GetTokens() sdk.Dec { return sdk.ZeroDec() @@ -43,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 @@ -88,7 +98,12 @@ func (vs *ValidatorSet) Validator(ctx sdk.Context, addr sdk.ValAddress) sdk.Vali } // ValidatorByPubKey implements sdk.ValidatorSet -func (vs *ValidatorSet) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Validator { +func (vs *ValidatorSet) ValidatorByConsPubKey(ctx sdk.Context, _ crypto.PubKey) sdk.Validator { + panic("not implemented") +} + +// ValidatorByPubKey implements sdk.ValidatorSet +func (vs *ValidatorSet) ValidatorByConsAddr(ctx sdk.Context, _ sdk.ConsAddress) sdk.Validator { panic("not implemented") } @@ -122,17 +137,17 @@ func (vs *ValidatorSet) RemoveValidator(addr sdk.AccAddress) { } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Dec) { +func (vs *ValidatorSet) Slash(ctx sdk.Context, _ sdk.ConsAddress, height int64, power int64, amt sdk.Dec) { panic("not implemented") } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Jail(ctx sdk.Context, pubkey crypto.PubKey) { +func (vs *ValidatorSet) Jail(_ sdk.Context, _ sdk.ConsAddress) { panic("not implemented") } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { +func (vs *ValidatorSet) Unjail(_ sdk.Context, _ sdk.ConsAddress) { panic("not implemented") } diff --git a/types/stake.go b/types/stake.go index d97001cfb2..ded7715486 100644 --- a/types/stake.go +++ b/types/stake.go @@ -69,9 +69,10 @@ type ValidatorSet interface { IterateValidatorsBonded(Context, func(index int64, validator Validator) (stop bool)) - Validator(Context, ValAddress) Validator // get a particular validator by operator - ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address - TotalPower(Context) Dec // total power of the validator set + Validator(Context, ValAddress) Validator // get a particular validator by operator + ValidatorByConsPubKey(Context, crypto.PubKey) Validator // get a particular validator by consensus address + ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address + TotalPower(Context) Dec // total power of the validator set // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction Slash(Context, ConsAddress, int64, int64, Dec) diff --git a/x/distribution/alias.go b/x/distribution/alias.go index e7af73fba3..80667b1897 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -2,7 +2,6 @@ package distribution import ( - "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" "github.com/cosmos/cosmos-sdk/x/distribution/keeper" "github.com/cosmos/cosmos-sdk/x/distribution/tags" "github.com/cosmos/cosmos-sdk/x/distribution/types" @@ -50,9 +49,6 @@ var ( NewMsgWithdrawDelegatorRewardsAll = types.NewMsgWithdrawDelegatorRewardsAll NewMsgWithdrawDelegationReward = types.NewMsgWithdrawDelegatorReward NewMsgWithdrawValidatorRewardsAll = types.NewMsgWithdrawValidatorRewardsAll - - GetCmdWithdrawRewards = cli.GetCmdWithdrawRewards - GetCmdSetWithdrawAddr = cli.GetCmdSetWithdrawAddr ) const ( diff --git a/x/gov/tally_test.go b/x/gov/tally_test.go index 6c6d64aa67..9c5348b2c7 100644 --- a/x/gov/tally_test.go +++ b/x/gov/tally_test.go @@ -440,7 +440,7 @@ func TestTallyJailedValidator(t *testing.T) { val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1])) require.True(t, found) - sk.Jail(ctx, val2.ConsPubKey) + sk.Jail(ctx, sdk.ConsAddress(val2.ConsPubKey.Address())) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index 8d519c7945..701a6b2cde 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -29,6 +29,8 @@ type Hooks struct { k Keeper } +var _ sdk.StakingHooks = Hooks{} + // Return the wrapper struct func (k Keeper) Hooks() Hooks { return Hooks{k} @@ -43,3 +45,11 @@ func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { h.k.onValidatorBeginUnbonding(ctx, address) } + +// nolint - unused hooks +func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnValidatorCommissionChange(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 3506d27416..e639182e18 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -78,6 +78,7 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio } // handle a validator signature, must be called once per validator per block +// TODO refactor to take in a consensus address, additionally should maybe just take in the pubkey too // nolint gocyclo func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) { logger := ctx.Logger().With("module", "x/slashing") diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index ff50a594ea..1d69f714f0 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -18,13 +18,16 @@ func init() { defaultDoubleSignUnbondDuration = 60 * 60 } +// ______________________________________________________________ + // Test that a validator is slashed correctly // when we discover evidence of infraction +// TODO fix this test to not be using the same pubkey/address for signing and operating, it's confusing func TestHandleDoubleSign(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) @@ -43,7 +46,7 @@ func TestHandleDoubleSign(t *testing.T) { // should be jailed require.True(t, sk.Validator(ctx, addr).GetJailed()) // unjail to measure power - sk.Unjail(ctx, val) + sk.Unjail(ctx, sdk.ConsAddress(addr)) // TODO distinguish cons address // power should be reduced require.Equal( t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), @@ -61,14 +64,16 @@ func TestHandleDoubleSign(t *testing.T) { // Test that the amount a validator is slashed for multiple double signs // is correctly capped by the slashing period in which they were committed +// TODO properly distinguish between consensus and operator address is variable names func TestSlashingPeriodCap(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) - addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) + addr, amt := addrs[0], sdk.NewInt(amtInt) + valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address()) + got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, valConsPubKey, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) @@ -76,39 +81,39 @@ func TestSlashingPeriodCap(t *testing.T) { require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) // handle a signature to set signing info - keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) + keeper.handleValidatorSignature(ctx, valConsPubKey.Address(), amtInt, true) // double sign less than max age - keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) + keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 0, time.Unix(0, 0), amtInt) // should be jailed require.True(t, sk.Validator(ctx, addr).GetJailed()) // update block height ctx = ctx.WithBlockHeight(int64(1)) // unjail to measure power - sk.Unjail(ctx, val) + sk.Unjail(ctx, valConsAddr) // power should be reduced expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) // double sign again, same slashing period - keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) + keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 0, time.Unix(0, 0), amtInt) // should be jailed require.True(t, sk.Validator(ctx, addr).GetJailed()) // update block height ctx = ctx.WithBlockHeight(int64(2)) // unjail to measure power - sk.Unjail(ctx, val) + sk.Unjail(ctx, valConsAddr) // power should be equal, no more should have been slashed expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) // double sign again, new slashing period - keeper.handleDoubleSign(ctx, val.Address(), 2, time.Unix(0, 0), amtInt) + keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 2, time.Unix(0, 0), amtInt) // should be jailed require.True(t, sk.Validator(ctx, addr).GetJailed()) // unjail to measure power - sk.Unjail(ctx, val) + sk.Unjail(ctx, valConsAddr) // power should be reduced expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20))) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) @@ -120,7 +125,7 @@ func TestHandleAbsentValidator(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) @@ -162,7 +167,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter) // validator should be bonded still - validator, _ := sk.GetValidatorByPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) require.Equal(t, amtInt, pool.BondedTokens.RoundInt64()) @@ -176,7 +181,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter) // validator should have been jailed - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // unrevocation should fail prior to jail expiration @@ -189,7 +194,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.True(t, got.IsOK()) // validator should be rebonded now - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) // validator should have been slashed @@ -207,7 +212,7 @@ func TestHandleAbsentValidator(t *testing.T) { height++ ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) // 500 signed blocks @@ -223,7 +228,7 @@ func TestHandleAbsentValidator(t *testing.T) { ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) } - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } @@ -258,7 +263,7 @@ func TestHandleNewValidator(t *testing.T) { require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil) // validator should be bonded still, should not have been jailed or slashed - validator, _ := sk.GetValidatorByPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) require.Equal(t, int64(100), pool.BondedTokens.RoundInt64()) @@ -292,7 +297,7 @@ func TestHandleAlreadyJailed(t *testing.T) { } // validator should have been jailed and slashed - validator, _ := sk.GetValidatorByPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // validator should have been slashed @@ -303,7 +308,7 @@ func TestHandleAlreadyJailed(t *testing.T) { keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) // validator should not have been slashed twice - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64()) } diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index 81003a968a..fe273be5eb 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -78,7 +78,7 @@ func TestBeginBlocker(t *testing.T) { } // validator should be jailed - validator, found := sk.GetValidatorByPubKey(ctx, pk) + validator, found := sk.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 70a21c171c..4bc92c0b73 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -81,8 +81,9 @@ func TestValidatorByPowerIndex(t *testing.T) { require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) // slash and jail the first validator - keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewDecWithPrec(5, 1)) - keeper.Jail(ctx, keep.PKs[0]) + consAddr0 := sdk.ConsAddress(keep.PKs[0].Address()) + keeper.Slash(ctx, consAddr0, 0, initBond, sdk.NewDecWithPrec(5, 1)) + keeper.Jail(ctx, consAddr0) validator, found = keeper.GetValidator(ctx, validatorAddr) require.True(t, found) require.Equal(t, sdk.Unbonding, validator.Status) // ensure is unbonding @@ -198,11 +199,12 @@ func TestLegacyValidatorDelegations(t *testing.T) { setInstantUnbondPeriod(keeper, ctx) bondAmount := int64(10) - valAddr, valPubKey := sdk.ValAddress(keep.Addrs[0]), keep.PKs[0] + valAddr := sdk.ValAddress(keep.Addrs[0]) + valConsPubKey, valConsAddr := keep.PKs[0], sdk.ConsAddress(keep.PKs[0].Address()) delAddr := keep.Addrs[1] // create validator - msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, 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) @@ -264,7 +266,7 @@ func TestLegacyValidatorDelegations(t *testing.T) { require.Equal(t, bondAmount*2, validator.Tokens.RoundInt64()) // unjail the validator now that is has non-zero self-delegated shares - keeper.Unjail(ctx, valPubKey) + keeper.Unjail(ctx, valConsAddr) // verify the validator can now accept delegations msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount) @@ -911,6 +913,7 @@ func TestCliffValidator(t *testing.T) { func TestBondUnbondRedelegateSlashTwice(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) 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) got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) @@ -944,7 +947,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { require.Equal(t, sdk.NewDec(6), delegation.Shares) // slash the validator by half - keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewDecWithPrec(5, 1)) + keeper.Slash(ctx, consAddr0, 0, 20, sdk.NewDecWithPrec(5, 1)) // unbonding delegation should have been slashed by half unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA) @@ -968,7 +971,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { // slash the validator for an infraction committed after the unbonding and redelegation begin ctx = ctx.WithBlockHeight(3) - keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewDecWithPrec(5, 1)) + keeper.Slash(ctx, consAddr0, 2, 10, sdk.NewDecWithPrec(5, 1)) // unbonding delegation should be unchanged unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA) diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index caed72ff55..0086b529cb 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -42,7 +42,7 @@ func TestRevocation(t *testing.T) { // setup ctx, keeper, _ := setupHelper(t, 10) addr := addrVals[0] - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) // initial state val, found := keeper.GetValidator(ctx, addr) @@ -50,13 +50,13 @@ func TestRevocation(t *testing.T) { require.False(t, val.GetJailed()) // test jail - keeper.Jail(ctx, pk) + keeper.Jail(ctx, consAddr) val, found = keeper.GetValidator(ctx, addr) require.True(t, found) require.True(t, val.GetJailed()) // test unjail - keeper.Unjail(ctx, pk) + keeper.Unjail(ctx, consAddr) val, found = keeper.GetValidator(ctx, addr) require.True(t, found) require.False(t, val.GetJailed()) @@ -179,24 +179,24 @@ func TestSlashRedelegation(t *testing.T) { // tests Slash at a future height (must panic) func TestSlashAtFutureHeight(t *testing.T) { ctx, keeper, _ := setupHelper(t, 10) - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := sdk.NewDecWithPrec(5, 1) - require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) }) + require.Panics(t, func() { keeper.Slash(ctx, consAddr, 1, 10, fraction) }) } // tests Slash at the current height func TestSlashValidatorAtCurrentHeight(t *testing.T) { ctx, keeper, _ := setupHelper(t, 10) - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := sdk.NewDecWithPrec(5, 1) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - keeper.Slash(ctx, pk, ctx.BlockHeight(), 10, fraction) + keeper.Slash(ctx, consAddr, ctx.BlockHeight(), 10, fraction) // read updated state - validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) newPool := keeper.GetPool(ctx) @@ -209,7 +209,7 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) { // tests Slash at a previous height with an unbonding delegation func TestSlashWithUnbondingDelegation(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := sdk.NewDecWithPrec(5, 1) // set an unbonding delegation @@ -227,9 +227,9 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // slash validator for the first time ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - keeper.Slash(ctx, pk, 10, 10, fraction) + keeper.Slash(ctx, consAddr, 10, 10, fraction) // read updating unbonding delegation ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) @@ -241,7 +241,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 3 - 6 stake originally bonded at the time of infraction // was still bonded at the time of discovery and was slashed by half, 4 stake @@ -251,7 +251,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // slash validator again ctx = ctx.WithBlockHeight(13) - keeper.Slash(ctx, pk, 9, 10, fraction) + keeper.Slash(ctx, consAddr, 9, 10, fraction) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) // balance decreased again @@ -261,7 +261,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned again require.Equal(t, int64(6), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 3 again require.Equal(t, sdk.NewDec(4), validator.GetPower()) @@ -271,7 +271,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // on the unbonding delegation, but it will slash stake bonded since the infraction // this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440 ctx = ctx.WithBlockHeight(13) - keeper.Slash(ctx, pk, 9, 10, fraction) + keeper.Slash(ctx, consAddr, 9, 10, fraction) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) // balance unchanged @@ -281,7 +281,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned again require.Equal(t, int64(9), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 3 again require.Equal(t, sdk.NewDec(1), validator.GetPower()) @@ -291,7 +291,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // on the unbonding delegation, but it will slash stake bonded since the infraction // this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440 ctx = ctx.WithBlockHeight(13) - keeper.Slash(ctx, pk, 9, 10, fraction) + keeper.Slash(ctx, consAddr, 9, 10, fraction) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) // balance unchanged @@ -303,14 +303,14 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // read updated validator // power decreased by 1 again, validator is out of stake // ergo validator should have been removed from the store - _, found = keeper.GetValidatorByConsPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.False(t, found) } // tests Slash at a previous height with a redelegation func TestSlashWithRedelegation(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := sdk.NewDecWithPrec(5, 1) // set a redelegation @@ -343,9 +343,9 @@ func TestSlashWithRedelegation(t *testing.T) { // slash validator ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - keeper.Slash(ctx, pk, 10, 10, fraction) + keeper.Slash(ctx, consAddr, 10, 10, fraction) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -357,7 +357,7 @@ func TestSlashWithRedelegation(t *testing.T) { // bonded tokens burned require.Equal(t, int64(5), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 2 - 4 stake originally bonded at the time of infraction // was still bonded at the time of discovery and was slashed by half, 4 stake @@ -367,9 +367,9 @@ func TestSlashWithRedelegation(t *testing.T) { // slash the validator again ctx = ctx.WithBlockHeight(12) - validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) }) + require.NotPanics(t, func() { keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) }) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -381,16 +381,16 @@ func TestSlashWithRedelegation(t *testing.T) { // seven bonded tokens burned require.Equal(t, int64(12), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 4 require.Equal(t, sdk.NewDec(4), validator.GetPower()) // slash the validator again, by 100% ctx = ctx.WithBlockHeight(12) - validator, found = keeper.GetValidatorByConsPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) + keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -403,16 +403,16 @@ func TestSlashWithRedelegation(t *testing.T) { require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator // validator decreased to zero power, should have been removed from the store - _, found = keeper.GetValidatorByConsPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.False(t, found) // slash the validator again, by 100% // no stake remains to be slashed ctx = ctx.WithBlockHeight(12) // validator no longer in the store - _, found = keeper.GetValidatorByConsPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.False(t, found) - keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) + keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -425,7 +425,7 @@ func TestSlashWithRedelegation(t *testing.T) { require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator // power still zero, still not in the store - _, found = keeper.GetValidatorByConsPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.False(t, found) } @@ -472,9 +472,10 @@ func TestSlashBoth(t *testing.T) { // slash validator ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByConsPubkey(ctx, PKs[0]) + validator, found := keeper.GetValidatorByConsPubKey(ctx, PKs[0]) require.True(t, found) - keeper.Slash(ctx, PKs[0], 10, 10, fraction) + consAddr0 := sdk.ConsAddres(PKs[0].Address()) + keeper.Slash(ctx, consAddr0, 10, 10, fraction) // read updating redelegation rdA, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index e23d3b0aad..a541600d9f 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -260,12 +260,13 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { require.Equal(t, sdk.Unbonded, validator.Status) require.Equal(t, int64(100), validator.Tokens.RoundInt64()) keeper.SetPool(ctx, pool) - keeper.SetValidatorByPubKeyIndex(ctx, validator) + keeper.SetValidatorByConsAddr(ctx, validator) validator = keeper.UpdateValidator(ctx, validator) require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool) // slash the validator by 100% - keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneDec()) + consAddr0 := sdk.ConsAddress(PKs[0].Address()) + keeper.Slash(ctx, consAddr0, 0, 100, sdk.OneDec()) // validator should have been deleted _, found := keeper.GetValidator(ctx, addrVals[0]) require.False(t, found) From 0867ce8656a20e8d5e5ce0b788f364c7cbf94539 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 20:23:07 -0400 Subject: [PATCH 32/99] ... --- x/stake/keeper/slash_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index 0086b529cb..c4a1edd415 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -474,7 +474,7 @@ func TestSlashBoth(t *testing.T) { oldPool := keeper.GetPool(ctx) validator, found := keeper.GetValidatorByConsPubKey(ctx, PKs[0]) require.True(t, found) - consAddr0 := sdk.ConsAddres(PKs[0].Address()) + consAddr0 := sdk.ConsAddress(PKs[0].Address()) keeper.Slash(ctx, consAddr0, 10, 10, fraction) // read updating redelegation From 4e4749da9d8f53ceccf86ee500aa947f2b4007ef Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 20:30:18 -0400 Subject: [PATCH 33/99] pulling in stuff from fee-distr PR --- x/slashing/handler.go | 8 ++-- x/slashing/hooks.go | 31 ++++++++----- x/slashing/keeper.go | 37 ++++++++-------- x/slashing/keeper_test.go | 47 +++++++++++--------- x/slashing/tick_test.go | 2 +- x/stake/client/cli/flags.go | 8 ++-- x/stake/genesis.go | 2 +- x/stake/handler.go | 12 ++++- x/stake/handler_test.go | 17 +++++--- x/stake/keeper/delegation.go | 16 +++++++ x/stake/keeper/hooks.go | 54 +++++++++++++++++++++++ x/stake/keeper/keeper.go | 28 ++++++------ x/stake/keeper/key.go | 8 ++-- x/stake/keeper/sdk_types.go | 33 +++++++++----- x/stake/keeper/slash.go | 33 +++++--------- x/stake/keeper/slash_test.go | 73 ++++++++++++++++--------------- x/stake/keeper/validator.go | 75 +++++++++++++++++++++++++++----- x/stake/keeper/validator_test.go | 5 ++- x/stake/stake.go | 4 +- x/stake/types/codec.go | 3 +- x/stake/types/delegation.go | 2 +- x/stake/types/errors.go | 8 ++++ x/stake/types/validator.go | 20 +++++---- 23 files changed, 341 insertions(+), 185 deletions(-) create mode 100644 x/stake/keeper/hooks.go diff --git a/x/slashing/handler.go b/x/slashing/handler.go index c43ed6be61..4f342f62a0 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -34,9 +34,9 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { return ErrValidatorNotJailed(k.codespace).Result() } - addr := sdk.ConsAddress(validator.GetPubKey().Address()) + consAddr := sdk.ConsAddress(validator.GetPubKey().Address()) - info, found := k.getValidatorSigningInfo(ctx, addr) + info, found := k.getValidatorSigningInfo(ctx, consAddr) if !found { return ErrNoValidatorForAddress(k.codespace).Result() } @@ -49,9 +49,9 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { // update the starting height so the validator can't be immediately jailed // again info.StartHeight = ctx.BlockHeight() - k.setValidatorSigningInfo(ctx, addr, info) + k.setValidatorSigningInfo(ctx, consAddr, info) - k.validatorSet.Unjail(ctx, validator.GetPubKey()) + k.validatorSet.Unjail(ctx, consAddr) tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String())) diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index f5f3cc48c3..701a6b2cde 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -22,25 +22,34 @@ func (k Keeper) onValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddre k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) } -// Wrapper struct for sdk.ValidatorHooks -type ValidatorHooks struct { +//_________________________________________________________________________________________ + +// Wrapper struct +type Hooks struct { k Keeper } -// Assert implementation -var _ sdk.ValidatorHooks = ValidatorHooks{} +var _ sdk.StakingHooks = Hooks{} -// Return a sdk.ValidatorHooks interface over the wrapper struct -func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { - return ValidatorHooks{k} +// Return the wrapper struct +func (k Keeper) Hooks() Hooks { + return Hooks{k} } // Implements sdk.ValidatorHooks -func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { - v.k.onValidatorBonded(ctx, address) +func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { + h.k.onValidatorBonded(ctx, address) } // Implements sdk.ValidatorHooks -func (v ValidatorHooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { - v.k.onValidatorBeginUnbonding(ctx, address) +func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { + h.k.onValidatorBeginUnbonding(ctx, address) } + +// nolint - unused hooks +func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnValidatorCommissionChange(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 5a008ccec5..e639182e18 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -40,10 +40,10 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio logger := ctx.Logger().With("module", "x/slashing") time := ctx.BlockHeader().Time age := time.Sub(timestamp) - address := sdk.ConsAddress(addr) + consAddr := sdk.ConsAddress(addr) pubkey, err := k.getPubkey(ctx, addr) if err != nil { - panic(fmt.Sprintf("Validator address %v not found", addr)) + panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr)) } // Double sign too old @@ -59,37 +59,38 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio // Cap the amount slashed to the penalty for the worst infraction // within the slashing period when this infraction was committed fraction := k.SlashFractionDoubleSign(ctx) - revisedFraction := k.capBySlashingPeriod(ctx, address, fraction, infractionHeight) + revisedFraction := k.capBySlashingPeriod(ctx, consAddr, fraction, infractionHeight) logger.Info(fmt.Sprintf("Fraction slashed capped by slashing period from %v to %v", fraction, revisedFraction)) // Slash validator - k.validatorSet.Slash(ctx, pubkey, infractionHeight, power, revisedFraction) + k.validatorSet.Slash(ctx, consAddr, infractionHeight, power, revisedFraction) // Jail validator - k.validatorSet.Jail(ctx, pubkey) + k.validatorSet.Jail(ctx, consAddr) // Set validator jail duration - signInfo, found := k.getValidatorSigningInfo(ctx, address) + signInfo, found := k.getValidatorSigningInfo(ctx, consAddr) if !found { - panic(fmt.Sprintf("Expected signing info for validator %s but not found", address)) + panic(fmt.Sprintf("Expected signing info for validator %s but not found", consAddr)) } signInfo.JailedUntil = time.Add(k.DoubleSignUnbondDuration(ctx)) - k.setValidatorSigningInfo(ctx, address, signInfo) + k.setValidatorSigningInfo(ctx, consAddr, signInfo) } // handle a validator signature, must be called once per validator per block +// TODO refactor to take in a consensus address, additionally should maybe just take in the pubkey too // nolint gocyclo func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) { logger := ctx.Logger().With("module", "x/slashing") height := ctx.BlockHeight() - address := sdk.ConsAddress(addr) + consAddr := sdk.ConsAddress(addr) pubkey, err := k.getPubkey(ctx, addr) if err != nil { - panic(fmt.Sprintf("Validator address %v not found", addr)) + panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr)) } // Local index, so counts blocks validator *should* have signed // Will use the 0-value default signing info if not present, except for start height - signInfo, found := k.getValidatorSigningInfo(ctx, address) + signInfo, found := k.getValidatorSigningInfo(ctx, consAddr) if !found { // If this validator has never been seen before, construct a new SigningInfo with the correct start height signInfo = NewValidatorSigningInfo(height, 0, time.Unix(0, 0), 0) @@ -100,16 +101,16 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p // Update signed block bit array & counter // This counter just tracks the sum of the bit array // That way we avoid needing to read/write the whole array each time - previous := k.getValidatorSigningBitArray(ctx, address, index) + previous := k.getValidatorSigningBitArray(ctx, consAddr, index) if previous == signed { // Array value at this index has not changed, no need to update counter } else if previous && !signed { // Array value has changed from signed to unsigned, decrement counter - k.setValidatorSigningBitArray(ctx, address, index, false) + k.setValidatorSigningBitArray(ctx, consAddr, index, false) signInfo.SignedBlocksCounter-- } else if !previous && signed { // Array value has changed from unsigned to signed, increment counter - k.setValidatorSigningBitArray(ctx, address, index, true) + k.setValidatorSigningBitArray(ctx, consAddr, index, true) signInfo.SignedBlocksCounter++ } @@ -118,13 +119,13 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p } minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx) if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) { - validator := k.validatorSet.ValidatorByPubKey(ctx, pubkey) + validator := k.validatorSet.ValidatorByConsAddr(ctx, consAddr) if validator != nil && !validator.GetJailed() { // Downtime confirmed: slash and jail the validator logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d", pubkey.Address(), minHeight, k.MinSignedPerWindow(ctx))) - k.validatorSet.Slash(ctx, pubkey, height, power, k.SlashFractionDowntime(ctx)) - k.validatorSet.Jail(ctx, pubkey) + k.validatorSet.Slash(ctx, consAddr, height, power, k.SlashFractionDowntime(ctx)) + k.validatorSet.Jail(ctx, consAddr) signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx)) } else { // Validator was (a) not found or (b) already jailed, don't slash @@ -134,7 +135,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p } // Set the updated signing info - k.setValidatorSigningInfo(ctx, address, signInfo) + k.setValidatorSigningInfo(ctx, consAddr, signInfo) } // AddValidators adds the validators to the keepers validator addr to pubkey mapping. diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index ff50a594ea..1d69f714f0 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -18,13 +18,16 @@ func init() { defaultDoubleSignUnbondDuration = 60 * 60 } +// ______________________________________________________________ + // Test that a validator is slashed correctly // when we discover evidence of infraction +// TODO fix this test to not be using the same pubkey/address for signing and operating, it's confusing func TestHandleDoubleSign(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) @@ -43,7 +46,7 @@ func TestHandleDoubleSign(t *testing.T) { // should be jailed require.True(t, sk.Validator(ctx, addr).GetJailed()) // unjail to measure power - sk.Unjail(ctx, val) + sk.Unjail(ctx, sdk.ConsAddress(addr)) // TODO distinguish cons address // power should be reduced require.Equal( t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), @@ -61,14 +64,16 @@ func TestHandleDoubleSign(t *testing.T) { // Test that the amount a validator is slashed for multiple double signs // is correctly capped by the slashing period in which they were committed +// TODO properly distinguish between consensus and operator address is variable names func TestSlashingPeriodCap(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) - addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) + addr, amt := addrs[0], sdk.NewInt(amtInt) + valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address()) + got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, valConsPubKey, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) @@ -76,39 +81,39 @@ func TestSlashingPeriodCap(t *testing.T) { require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) // handle a signature to set signing info - keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) + keeper.handleValidatorSignature(ctx, valConsPubKey.Address(), amtInt, true) // double sign less than max age - keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) + keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 0, time.Unix(0, 0), amtInt) // should be jailed require.True(t, sk.Validator(ctx, addr).GetJailed()) // update block height ctx = ctx.WithBlockHeight(int64(1)) // unjail to measure power - sk.Unjail(ctx, val) + sk.Unjail(ctx, valConsAddr) // power should be reduced expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) // double sign again, same slashing period - keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) + keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 0, time.Unix(0, 0), amtInt) // should be jailed require.True(t, sk.Validator(ctx, addr).GetJailed()) // update block height ctx = ctx.WithBlockHeight(int64(2)) // unjail to measure power - sk.Unjail(ctx, val) + sk.Unjail(ctx, valConsAddr) // power should be equal, no more should have been slashed expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) // double sign again, new slashing period - keeper.handleDoubleSign(ctx, val.Address(), 2, time.Unix(0, 0), amtInt) + keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 2, time.Unix(0, 0), amtInt) // should be jailed require.True(t, sk.Validator(ctx, addr).GetJailed()) // unjail to measure power - sk.Unjail(ctx, val) + sk.Unjail(ctx, valConsAddr) // power should be reduced expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20))) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) @@ -120,7 +125,7 @@ func TestHandleAbsentValidator(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) @@ -162,7 +167,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter) // validator should be bonded still - validator, _ := sk.GetValidatorByPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) require.Equal(t, amtInt, pool.BondedTokens.RoundInt64()) @@ -176,7 +181,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter) // validator should have been jailed - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // unrevocation should fail prior to jail expiration @@ -189,7 +194,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.True(t, got.IsOK()) // validator should be rebonded now - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) // validator should have been slashed @@ -207,7 +212,7 @@ func TestHandleAbsentValidator(t *testing.T) { height++ ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) // 500 signed blocks @@ -223,7 +228,7 @@ func TestHandleAbsentValidator(t *testing.T) { ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) } - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } @@ -258,7 +263,7 @@ func TestHandleNewValidator(t *testing.T) { require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil) // validator should be bonded still, should not have been jailed or slashed - validator, _ := sk.GetValidatorByPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) require.Equal(t, int64(100), pool.BondedTokens.RoundInt64()) @@ -292,7 +297,7 @@ func TestHandleAlreadyJailed(t *testing.T) { } // validator should have been jailed and slashed - validator, _ := sk.GetValidatorByPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // validator should have been slashed @@ -303,7 +308,7 @@ func TestHandleAlreadyJailed(t *testing.T) { keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) // validator should not have been slashed twice - validator, _ = sk.GetValidatorByPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsPubKey(ctx, val) require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64()) } diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index 81003a968a..fe273be5eb 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -78,7 +78,7 @@ func TestBeginBlocker(t *testing.T) { } // validator should be jailed - validator, found := sk.GetValidatorByPubKey(ctx, pk) + validator, found := sk.GetValidatorByConsPubKey(ctx, pk) require.True(t, found) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } diff --git a/x/stake/client/cli/flags.go b/x/stake/client/cli/flags.go index d0e83ab3c6..4c36be0b54 100644 --- a/x/stake/client/cli/flags.go +++ b/x/stake/client/cli/flags.go @@ -48,8 +48,8 @@ func init() { fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)") fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website") fsDescriptionEdit.String(FlagDetails, types.DoNotModifyDesc, "optional details") - fsValidator.String(FlagAddressValidator, "", "hex address of the validator") - fsDelegator.String(FlagAddressDelegator, "", "hex address of the delegator") - fsRedelegation.String(FlagAddressValidatorSrc, "", "hex address of the source validator") - fsRedelegation.String(FlagAddressValidatorDst, "", "hex address of the destination validator") + fsValidator.String(FlagAddressValidator, "", "bech address of the validator") + fsDelegator.String(FlagAddressDelegator, "", "bech address of the delegator") + fsRedelegation.String(FlagAddressValidatorSrc, "", "bech address of the source validator") + fsRedelegation.String(FlagAddressValidatorDst, "", "bech address of the destination validator") } diff --git a/x/stake/genesis.go b/x/stake/genesis.go index 7a004bccd2..a7f8493081 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -32,7 +32,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ } // Manually set indexes for the first time - keeper.SetValidatorByPubKeyIndex(ctx, validator) + keeper.SetValidatorByConsAddr(ctx, validator) keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool) if validator.Status == sdk.Bonded { diff --git a/x/stake/handler.go b/x/stake/handler.go index e7641393db..005b3af7d0 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -68,7 +68,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k if found { return ErrValidatorOwnerExists(k.Codespace()).Result() } - _, found = k.GetValidatorByPubKey(ctx, msg.PubKey) + _, found = k.GetValidatorByConsPubKey(ctx, msg.PubKey) if found { return ErrValidatorPubKeyExists(k.Codespace()).Result() } @@ -78,7 +78,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description) k.SetValidator(ctx, validator) - k.SetValidatorByPubKeyIndex(ctx, validator) + k.SetValidatorByConsAddr(ctx, validator) // move coins from the msg.Address account to a (self-delegation) delegator account // the validator account and global shares are updated within here @@ -87,6 +87,11 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k return err.Result() } + // call the hook if present + k.OnValidatorCreated(ctx, validator.OperatorAddr) + accAddr := sdk.AccAddress(validator.OperatorAddr) + k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) + tags := sdk.NewTags( tags.Action, tags.ActionCreateValidator, tags.DstValidator, []byte(msg.ValidatorAddr.String()), @@ -146,6 +151,9 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) return err.Result() } + // call the hook if present + k.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) + tags := sdk.NewTags( tags.Action, tags.ActionDelegate, tags.Delegator, []byte(msg.DelegatorAddr.String()), diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 70a21c171c..4bc92c0b73 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -81,8 +81,9 @@ func TestValidatorByPowerIndex(t *testing.T) { require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) // slash and jail the first validator - keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewDecWithPrec(5, 1)) - keeper.Jail(ctx, keep.PKs[0]) + consAddr0 := sdk.ConsAddress(keep.PKs[0].Address()) + keeper.Slash(ctx, consAddr0, 0, initBond, sdk.NewDecWithPrec(5, 1)) + keeper.Jail(ctx, consAddr0) validator, found = keeper.GetValidator(ctx, validatorAddr) require.True(t, found) require.Equal(t, sdk.Unbonding, validator.Status) // ensure is unbonding @@ -198,11 +199,12 @@ func TestLegacyValidatorDelegations(t *testing.T) { setInstantUnbondPeriod(keeper, ctx) bondAmount := int64(10) - valAddr, valPubKey := sdk.ValAddress(keep.Addrs[0]), keep.PKs[0] + valAddr := sdk.ValAddress(keep.Addrs[0]) + valConsPubKey, valConsAddr := keep.PKs[0], sdk.ConsAddress(keep.PKs[0].Address()) delAddr := keep.Addrs[1] // create validator - msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, 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) @@ -264,7 +266,7 @@ func TestLegacyValidatorDelegations(t *testing.T) { require.Equal(t, bondAmount*2, validator.Tokens.RoundInt64()) // unjail the validator now that is has non-zero self-delegated shares - keeper.Unjail(ctx, valPubKey) + keeper.Unjail(ctx, valConsAddr) // verify the validator can now accept delegations msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount) @@ -911,6 +913,7 @@ func TestCliffValidator(t *testing.T) { func TestBondUnbondRedelegateSlashTwice(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) 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) got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) @@ -944,7 +947,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { require.Equal(t, sdk.NewDec(6), delegation.Shares) // slash the validator by half - keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewDecWithPrec(5, 1)) + keeper.Slash(ctx, consAddr0, 0, 20, sdk.NewDecWithPrec(5, 1)) // unbonding delegation should have been slashed by half unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA) @@ -968,7 +971,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { // slash the validator for an infraction committed after the unbonding and redelegation begin ctx = ctx.WithBlockHeight(3) - keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewDecWithPrec(5, 1)) + keeper.Slash(ctx, consAddr0, 2, 10, sdk.NewDecWithPrec(5, 1)) // unbonding delegation should be unchanged unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index ef09a307e1..6ac51ac196 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -66,6 +66,12 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { // remove a delegation from store func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { + + // call the hook if present + if k.hooks != nil { + k.hooks.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr) + } + store := ctx.KVStore(k.storeKey) store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) } @@ -275,6 +281,11 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co k.SetDelegation(ctx, delegation) k.UpdateValidator(ctx, validator) + // call the hook if present + if k.hooks != nil { + k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) + } + return } @@ -333,6 +344,11 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA k.RemoveValidator(ctx, validator.OperatorAddr) } + // call the hook if present + if k.hooks != nil { + k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) + } + return amount, nil } diff --git a/x/stake/keeper/hooks.go b/x/stake/keeper/hooks.go new file mode 100644 index 0000000000..81bf5594ba --- /dev/null +++ b/x/stake/keeper/hooks.go @@ -0,0 +1,54 @@ +//nolint +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Expose the hooks if present +func (k Keeper) OnValidatorCreated(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorCreated(ctx, address) + } +} +func (k Keeper) OnValidatorCommissionChange(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorCommissionChange(ctx, address) + } +} + +func (k Keeper) OnValidatorRemoved(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorRemoved(ctx, address) + } +} + +func (k Keeper) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { + if k.hooks != nil { + k.hooks.OnValidatorBonded(ctx, address) + } +} + +func (k Keeper) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { + if k.hooks != nil { + k.hooks.OnValidatorBeginUnbonding(ctx, address) + } +} + +func (k Keeper) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationCreated(ctx, delAddr, valAddr) + } +} + +func (k Keeper) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationSharesModified(ctx, delAddr, valAddr) + } +} + +func (k Keeper) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationRemoved(ctx, delAddr, valAddr) + } +} diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index a3754f7504..82170a4aed 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -10,11 +10,11 @@ import ( // keeper of the stake store type Keeper struct { - storeKey sdk.StoreKey - storeTKey sdk.StoreKey - cdc *codec.Codec - bankKeeper bank.Keeper - validatorHooks sdk.ValidatorHooks + storeKey sdk.StoreKey + storeTKey sdk.StoreKey + cdc *codec.Codec + bankKeeper bank.Keeper + hooks sdk.StakingHooks // codespace codespace sdk.CodespaceType @@ -22,22 +22,22 @@ type Keeper struct { func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ - storeKey: key, - storeTKey: tkey, - cdc: cdc, - bankKeeper: ck, - validatorHooks: nil, - codespace: codespace, + storeKey: key, + storeTKey: tkey, + cdc: cdc, + bankKeeper: ck, + hooks: nil, + codespace: codespace, } return keeper } // Set the validator hooks -func (k Keeper) WithValidatorHooks(v sdk.ValidatorHooks) Keeper { - if k.validatorHooks != nil { +func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { + if k.hooks != nil { panic("cannot set validator hooks twice") } - k.validatorHooks = v + k.hooks = sh return k } diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index c445e25524..91e6a69708 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -3,8 +3,6 @@ package keeper import ( "encoding/binary" - "github.com/tendermint/tendermint/crypto" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" ) @@ -17,7 +15,7 @@ var ( ParamKey = []byte{0x00} // key for parameters relating to staking PoolKey = []byte{0x01} // key for the staking pools ValidatorsKey = []byte{0x02} // prefix for each key to a validator - ValidatorsByPubKeyIndexKey = []byte{0x03} // prefix for each key to a validator index, by pubkey + ValidatorsByConsAddrKey = []byte{0x03} // prefix for each key to a validator index, by pubkey ValidatorsBondedIndexKey = []byte{0x04} // prefix for each key to a validator index, for bonded validators ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator @@ -44,8 +42,8 @@ func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { // gets the key for the validator with pubkey // VALUE: validator operator address ([]byte) -func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte { - return append(ValidatorsByPubKeyIndexKey, pubkey.Bytes()...) +func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { + return append(ValidatorsByConsAddrKey, addr.Bytes()...) } // gets the key for the current validator group diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index e4c7a1c193..9872630a4e 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -3,10 +3,9 @@ package keeper import ( "fmt" - "github.com/tendermint/tendermint/crypto" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" + "github.com/tendermint/tendermint/crypto" ) // Implements ValidatorSet @@ -60,8 +59,17 @@ func (k Keeper) Validator(ctx sdk.Context, address sdk.ValAddress) sdk.Validator } // get the sdk.validator for a particular pubkey -func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Validator { - val, found := k.GetValidatorByPubKey(ctx, pubkey) +func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) sdk.Validator { + val, found := k.GetValidatorByConsAddr(ctx, addr) + if !found { + return nil + } + return val +} + +// get the sdk.validator for a particular pubkey +func (k Keeper) ValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) sdk.Validator { + val, found := k.GetValidatorByConsPubKey(ctx, consPubKey) if !found { return nil } @@ -95,15 +103,16 @@ func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk. return bond } -// iterate through the active validator set and perform the provided function -func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, fn func(index int64, delegation sdk.Delegation) (stop bool)) { +// iterate through all of the delegations from a delegator +func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, + fn func(index int64, del sdk.Delegation) (stop bool)) { + store := ctx.KVStore(k.storeKey) - key := GetDelegationsKey(delAddr) - iterator := sdk.KVStorePrefixIterator(store, key) - i := int64(0) - for ; iterator.Valid(); iterator.Next() { - delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) - stop := fn(i, delegation) // XXX is this safe will the fields be able to get written to? + delegatorPrefixKey := GetDelegationsKey(delAddr) + iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest + for i := int64(0); iterator.Valid(); iterator.Next() { + del := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) + stop := fn(i, del) if stop { break } diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index 52dbd21c7e..ea378678ae 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -5,7 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/x/stake/types" - "github.com/tendermint/tendermint/crypto" ) // Slash a validator for an infraction committed at a known height @@ -24,7 +23,7 @@ import ( // not at a height in the future // // nolint: gocyclo -func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Dec) { +func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeight int64, power int64, slashFactor sdk.Dec) { logger := ctx.Logger().With("module", "x/stake") if slashFactor.LT(sdk.ZeroDec()) { @@ -36,7 +35,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // ref https://github.com/cosmos/cosmos-sdk/issues/1348 // ref https://github.com/cosmos/cosmos-sdk/issues/1471 - validator, found := k.GetValidatorByPubKey(ctx, pubkey) + validator, found := k.GetValidatorByConsAddr(ctx, consAddr) if !found { // If not found, the validator must have been overslashed and removed - so we don't need to do anything // NOTE: Correctness dependent on invariant that unbonding delegations / redelegations must also have been completely @@ -44,7 +43,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in // Log the slash attempt for future reference (maybe we should tag it too) logger.Error(fmt.Sprintf( "WARNING: Ignored attempt to slash a nonexistent validator with address %s, we recommend you investigate immediately", - pubkey.Address())) + consAddr)) return } @@ -125,36 +124,28 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in } // jail a validator -func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) { - k.setJailed(ctx, pubkey, true) - validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String()) - if err != nil { - panic(err.Error()) - } +func (k Keeper) Jail(ctx sdk.Context, consAddr sdk.ConsAddress) { + k.setJailed(ctx, consAddr, true) logger := ctx.Logger().With("module", "x/stake") - logger.Info(fmt.Sprintf("validator %s jailed", validatorAddr)) + logger.Info(fmt.Sprintf("validator %s jailed", consAddr)) // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 return } // unjail a validator -func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { - k.setJailed(ctx, pubkey, false) - validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String()) - if err != nil { - panic(err.Error()) - } +func (k Keeper) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) { + k.setJailed(ctx, consAddr, false) logger := ctx.Logger().With("module", "x/stake") - logger.Info(fmt.Sprintf("validator %s unjailed", validatorAddr)) + logger.Info(fmt.Sprintf("validator %s unjailed", consAddr)) // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 return } // set the jailed flag on a validator -func (k Keeper) setJailed(ctx sdk.Context, pubkey crypto.PubKey, isJailed bool) { - validator, found := k.GetValidatorByPubKey(ctx, pubkey) +func (k Keeper) setJailed(ctx sdk.Context, consAddr sdk.ConsAddress, isJailed bool) { + validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(consAddr)) if !found { - panic(fmt.Errorf("validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed)) + panic(fmt.Errorf("validator with consensus-Address %s not found, cannot set jailed to %v", consAddr, isJailed)) } validator.Jailed = isJailed k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index 65bac2d808..c4a1edd415 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -27,7 +27,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) { validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(amt)) keeper.SetPool(ctx, pool) validator = keeper.UpdateValidator(ctx, validator) - keeper.SetValidatorByPubKeyIndex(ctx, validator) + keeper.SetValidatorByConsAddr(ctx, validator) } pool = keeper.GetPool(ctx) @@ -42,7 +42,7 @@ func TestRevocation(t *testing.T) { // setup ctx, keeper, _ := setupHelper(t, 10) addr := addrVals[0] - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) // initial state val, found := keeper.GetValidator(ctx, addr) @@ -50,13 +50,13 @@ func TestRevocation(t *testing.T) { require.False(t, val.GetJailed()) // test jail - keeper.Jail(ctx, pk) + keeper.Jail(ctx, consAddr) val, found = keeper.GetValidator(ctx, addr) require.True(t, found) require.True(t, val.GetJailed()) // test unjail - keeper.Unjail(ctx, pk) + keeper.Unjail(ctx, consAddr) val, found = keeper.GetValidator(ctx, addr) require.True(t, found) require.False(t, val.GetJailed()) @@ -179,24 +179,24 @@ func TestSlashRedelegation(t *testing.T) { // tests Slash at a future height (must panic) func TestSlashAtFutureHeight(t *testing.T) { ctx, keeper, _ := setupHelper(t, 10) - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := sdk.NewDecWithPrec(5, 1) - require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) }) + require.Panics(t, func() { keeper.Slash(ctx, consAddr, 1, 10, fraction) }) } // tests Slash at the current height func TestSlashValidatorAtCurrentHeight(t *testing.T) { ctx, keeper, _ := setupHelper(t, 10) - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := sdk.NewDecWithPrec(5, 1) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - keeper.Slash(ctx, pk, ctx.BlockHeight(), 10, fraction) + keeper.Slash(ctx, consAddr, ctx.BlockHeight(), 10, fraction) // read updated state - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) newPool := keeper.GetPool(ctx) @@ -209,7 +209,7 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) { // tests Slash at a previous height with an unbonding delegation func TestSlashWithUnbondingDelegation(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := sdk.NewDecWithPrec(5, 1) // set an unbonding delegation @@ -227,9 +227,9 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // slash validator for the first time ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - keeper.Slash(ctx, pk, 10, 10, fraction) + keeper.Slash(ctx, consAddr, 10, 10, fraction) // read updating unbonding delegation ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) @@ -241,7 +241,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 3 - 6 stake originally bonded at the time of infraction // was still bonded at the time of discovery and was slashed by half, 4 stake @@ -251,7 +251,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // slash validator again ctx = ctx.WithBlockHeight(13) - keeper.Slash(ctx, pk, 9, 10, fraction) + keeper.Slash(ctx, consAddr, 9, 10, fraction) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) // balance decreased again @@ -261,7 +261,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned again require.Equal(t, int64(6), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 3 again require.Equal(t, sdk.NewDec(4), validator.GetPower()) @@ -271,7 +271,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // on the unbonding delegation, but it will slash stake bonded since the infraction // this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440 ctx = ctx.WithBlockHeight(13) - keeper.Slash(ctx, pk, 9, 10, fraction) + keeper.Slash(ctx, consAddr, 9, 10, fraction) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) // balance unchanged @@ -281,7 +281,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // bonded tokens burned again require.Equal(t, int64(9), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 3 again require.Equal(t, sdk.NewDec(1), validator.GetPower()) @@ -291,7 +291,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // on the unbonding delegation, but it will slash stake bonded since the infraction // this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440 ctx = ctx.WithBlockHeight(13) - keeper.Slash(ctx, pk, 9, 10, fraction) + keeper.Slash(ctx, consAddr, 9, 10, fraction) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) // balance unchanged @@ -303,14 +303,14 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // read updated validator // power decreased by 1 again, validator is out of stake // ergo validator should have been removed from the store - _, found = keeper.GetValidatorByPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.False(t, found) } // tests Slash at a previous height with a redelegation func TestSlashWithRedelegation(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) - pk := PKs[0] + consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := sdk.NewDecWithPrec(5, 1) // set a redelegation @@ -343,9 +343,9 @@ func TestSlashWithRedelegation(t *testing.T) { // slash validator ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByPubKey(ctx, pk) + validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - keeper.Slash(ctx, pk, 10, 10, fraction) + keeper.Slash(ctx, consAddr, 10, 10, fraction) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -357,7 +357,7 @@ func TestSlashWithRedelegation(t *testing.T) { // bonded tokens burned require.Equal(t, int64(5), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 2 - 4 stake originally bonded at the time of infraction // was still bonded at the time of discovery and was slashed by half, 4 stake @@ -367,9 +367,9 @@ func TestSlashWithRedelegation(t *testing.T) { // slash the validator again ctx = ctx.WithBlockHeight(12) - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) }) + require.NotPanics(t, func() { keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) }) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -381,16 +381,16 @@ func TestSlashWithRedelegation(t *testing.T) { // seven bonded tokens burned require.Equal(t, int64(12), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) // power decreased by 4 require.Equal(t, sdk.NewDec(4), validator.GetPower()) // slash the validator again, by 100% ctx = ctx.WithBlockHeight(12) - validator, found = keeper.GetValidatorByPubKey(ctx, pk) + validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.True(t, found) - keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) + keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -403,16 +403,16 @@ func TestSlashWithRedelegation(t *testing.T) { require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator // validator decreased to zero power, should have been removed from the store - _, found = keeper.GetValidatorByPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.False(t, found) // slash the validator again, by 100% // no stake remains to be slashed ctx = ctx.WithBlockHeight(12) // validator no longer in the store - _, found = keeper.GetValidatorByPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.False(t, found) - keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) + keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -425,7 +425,7 @@ func TestSlashWithRedelegation(t *testing.T) { require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator // power still zero, still not in the store - _, found = keeper.GetValidatorByPubKey(ctx, pk) + _, found = keeper.GetValidatorByConsAddr(ctx, consAddr) require.False(t, found) } @@ -472,9 +472,10 @@ func TestSlashBoth(t *testing.T) { // slash validator ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByPubKey(ctx, PKs[0]) + validator, found := keeper.GetValidatorByConsPubKey(ctx, PKs[0]) require.True(t, found) - keeper.Slash(ctx, PKs[0], 10, 10, fraction) + consAddr0 := sdk.ConsAddress(PKs[0].Address()) + keeper.Slash(ctx, consAddr0, 10, 10, fraction) // read updating redelegation rdA, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -488,7 +489,7 @@ func TestSlashBoth(t *testing.T) { // bonded tokens burned require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0]) + validator, found = keeper.GetValidatorByConsPubKey(ctx, PKs[0]) require.True(t, found) // power not decreased, all stake was bonded since require.Equal(t, sdk.NewDec(10), validator.GetPower()) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 996bf06bf5..af7d77e207 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -58,14 +58,25 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty return validator, true } -// get a single validator by pubkey -func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (validator types.Validator, found bool) { +// get a single validator by consensus address +func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) { store := ctx.KVStore(k.storeKey) - addr := store.Get(GetValidatorByPubKeyIndexKey(pubkey)) - if addr == nil { + opAddr := store.Get(GetValidatorByConsAddrKey(consAddr)) + if opAddr == nil { return validator, false } - return k.GetValidator(ctx, addr) + return k.GetValidator(ctx, opAddr) +} + +// get a single validator by pubkey +func (k Keeper) GetValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) (validator types.Validator, found bool) { + store := ctx.KVStore(k.storeKey) + consAddr := sdk.ConsAddress(consPubKey.Address()) + opAddr := store.Get(GetValidatorByConsAddrKey(consAddr)) + if opAddr == nil { + return validator, false + } + return k.GetValidator(ctx, opAddr) } // set the main record holding validator details @@ -76,9 +87,11 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { } // validator index -func (k Keeper) SetValidatorByPubKeyIndex(ctx sdk.Context, validator types.Validator) { +// TODO change to SetValidatorByConsAddr? used for retrieving from ConsPubkey as well- kinda confusing +func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorByPubKeyIndexKey(validator.ConsPubKey), validator.OperatorAddr) + consAddr := sdk.ConsAddress(validator.OperatorAddr.Bytes()) + store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr) } // validator index @@ -622,8 +635,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) // call the unbond hook if present - if k.validatorHooks != nil { - k.validatorHooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) + if k.hooks != nil { + k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) } // return updated validator @@ -657,8 +670,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI) // call the bond hook if present - if k.validatorHooks != nil { - k.validatorHooks.OnValidatorBonded(ctx, validator.ConsAddress()) + if k.hooks != nil { + k.hooks.OnValidatorBonded(ctx, validator.ConsAddress()) } // return updated validator @@ -668,6 +681,11 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // remove the validator record and associated indexes func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { + // call the hook if present + if k.hooks != nil { + k.hooks.OnValidatorRemoved(ctx, address) + } + // first retrieve the old validator record validator, found := k.GetValidator(ctx, address) if !found { @@ -678,7 +696,7 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) store.Delete(GetValidatorKey(address)) - store.Delete(GetValidatorByPubKeyIndexKey(validator.ConsPubKey)) + store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address()))) store.Delete(GetValidatorsByPowerIndexKey(validator, pool)) // delete from the current and power weighted validator groups if the validator @@ -727,3 +745,36 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr)) } } + +//__________________________________________________________________________ + +// XXX remove this code - this is should be superceded by commission work that bez is doing +// get a single validator +func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { + + // call the hook if present + if k.hooks != nil { + k.hooks.OnValidatorCommissionChange(ctx, addr) + } + + validator, found := k.GetValidator(ctx, addr) + + // check for errors + switch { + case !found: + return types.ErrNoValidatorFound(k.Codespace()) + case newCommission.LT(sdk.ZeroDec()): + return types.ErrCommissionNegative(k.Codespace()) + case newCommission.GT(validator.CommissionMax): + return types.ErrCommissionBeyondMax(k.Codespace()) + //case rateChange(Commission) > CommissionMaxChange: // XXX XXX XXX TODO implementation + //return types.ErrCommissionPastRate(k.Codespace()) + } + + // TODO adjust all the commission terms appropriately + + validator.Commission = newCommission + + k.SetValidator(ctx, validator) + return nil +} diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index e23d3b0aad..a541600d9f 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -260,12 +260,13 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { require.Equal(t, sdk.Unbonded, validator.Status) require.Equal(t, int64(100), validator.Tokens.RoundInt64()) keeper.SetPool(ctx, pool) - keeper.SetValidatorByPubKeyIndex(ctx, validator) + keeper.SetValidatorByConsAddr(ctx, validator) validator = keeper.UpdateValidator(ctx, validator) require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool) // slash the validator by 100% - keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneDec()) + consAddr0 := sdk.ConsAddress(PKs[0].Address()) + keeper.Slash(ctx, consAddr0, 0, 100, sdk.OneDec()) // validator should have been deleted _, found := keeper.GetValidator(ctx, addrVals[0]) require.False(t, found) diff --git a/x/stake/stake.go b/x/stake/stake.go index 18b99fd4a0..6b4036d281 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -35,7 +35,7 @@ var ( NewKeeper = keeper.NewKeeper GetValidatorKey = keeper.GetValidatorKey - GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey + GetValidatorByConsAddrKey = keeper.GetValidatorByConsAddrKey GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey @@ -44,7 +44,7 @@ var ( ParamKey = keeper.ParamKey PoolKey = keeper.PoolKey ValidatorsKey = keeper.ValidatorsKey - ValidatorsByPubKeyIndexKey = keeper.ValidatorsByPubKeyIndexKey + ValidatorsByConsAddrKey = keeper.ValidatorsByConsAddrKey ValidatorsBondedIndexKey = keeper.ValidatorsBondedIndexKey ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey diff --git a/x/stake/types/codec.go b/x/stake/types/codec.go index aa4f64f8a2..4921cdf8e2 100644 --- a/x/stake/types/codec.go +++ b/x/stake/types/codec.go @@ -22,6 +22,5 @@ func init() { cdc := codec.New() RegisterCodec(cdc) codec.RegisterCrypto(cdc) - MsgCdc = cdc - //MsgCdc = cdc.Seal() //TODO use when upgraded to go-amino 0.9.10 + MsgCdc = cdc.Seal() } diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 38a94c3695..57ac70a571 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -89,7 +89,7 @@ var _ sdk.Delegation = Delegation{} // nolint - for sdk.Delegation func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr } func (d Delegation) GetValidator() sdk.ValAddress { return d.ValidatorAddr } -func (d Delegation) GetBondShares() sdk.Dec { return d.Shares } +func (d Delegation) GetShares() sdk.Dec { return d.Shares } // HumanReadableString returns a human readable string representation of a // Delegation. An error is returned if the Delegation's delegator or validator diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 366012bbfb..541ad3d7b9 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -65,6 +65,14 @@ func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%") } +func ErrCommissionBeyondMax(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than preset commission maximum") +} + +func ErrCommissionPastRate(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission change is greater than the commission rate, please wait before changing your commission more") +} + func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil") } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 6c5066a783..c15d43396c 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -470,12 +470,14 @@ func (v Validator) IsUnbonded(ctx sdk.Context) bool { var _ sdk.Validator = Validator{} // nolint - for sdk.Validator -func (v Validator) GetJailed() bool { return v.Jailed } -func (v Validator) GetMoniker() string { return v.Description.Moniker } -func (v Validator) GetStatus() sdk.BondStatus { return v.Status } -func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } -func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } -func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } -func (v Validator) GetTokens() sdk.Dec { return v.Tokens } -func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } -func (v Validator) GetBondHeight() int64 { return v.BondHeight } +func (v Validator) GetJailed() bool { return v.Jailed } +func (v Validator) GetMoniker() string { return v.Description.Moniker } +func (v Validator) GetStatus() sdk.BondStatus { return v.Status } +func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } +func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } +func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) } +func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } +func (v Validator) GetTokens() sdk.Dec { return v.Tokens } +func (v Validator) GetCommission() sdk.Dec { return v.Commission } +func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } +func (v Validator) GetBondHeight() int64 { return v.BondHeight } From ab61695be97939cd5892de96aecf39cb60953cbe Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 20:39:23 -0400 Subject: [PATCH 34/99] PENDING --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index e07319d49e..d9b94175f0 100644 --- a/PENDING.md +++ b/PENDING.md @@ -49,6 +49,7 @@ BREAKING CHANGES * [store] Change storeInfo within the root multistore to use tmhash instead of ripemd160 \#2308 * [codec] \#2324 All referrences to wire have been renamed to codec. Additionally, wire.NewCodec is now codec.New(). * [types] \#2343 Make sdk.Msg have a names field, to facilitate automatic tagging. + * [x/staking] \#2244 staking now holds a consensus-address-index instead of a consensus-pubkey-index * Tendermint From 0f903bdd52d6ef069b66599756595e723cf7e545 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 21:17:50 -0400 Subject: [PATCH 35/99] finished pulling in, compiles --- types/stake.go | 38 +++++++++++++------------ x/gov/endblocker_test.go | 51 +++++++--------------------------- x/gov/genesis.go | 6 ++-- x/gov/handler.go | 10 +++---- x/gov/keeper.go | 19 +++++++------ x/gov/keeper_test.go | 9 +++--- x/gov/procedures.go | 8 ++---- x/gov/proposals.go | 27 +++++++++--------- x/gov/simulation/msgs.go | 5 ++-- x/gov/tally.go | 4 +-- x/gov/tally_test.go | 2 +- x/slashing/genesis.go | 2 +- x/slashing/handler.go | 2 +- x/slashing/hooks.go | 12 ++------ x/stake/genesis.go | 2 +- x/stake/handler.go | 8 ------ x/stake/keeper/delegation.go | 15 ---------- x/stake/keeper/hooks.go | 54 ------------------------------------ x/stake/keeper/keeper.go | 4 +-- x/stake/keeper/validator.go | 38 ------------------------- x/stake/types/validator.go | 2 +- 21 files changed, 80 insertions(+), 238 deletions(-) delete mode 100644 x/stake/keeper/hooks.go diff --git a/types/stake.go b/types/stake.go index 0b9f32b4b8..b8740a3cb9 100644 --- a/types/stake.go +++ b/types/stake.go @@ -37,22 +37,23 @@ func (b BondStatus) Equal(b2 BondStatus) bool { // validator for a delegated proof of stake system type Validator interface { - GetJailed() bool // whether the validator is jailed - GetMoniker() string // moniker of the validator - GetStatus() BondStatus // status of the validator - GetOperator() ValAddress // operator address to receive/return validators coins - GetPubKey() crypto.PubKey // validation pubkey - GetPower() Dec // validation power - GetTokens() Dec // validation tokens - GetDelegatorShares() Dec // Total out standing delegator shares - GetBondHeight() int64 // height in which the validator became active + GetJailed() bool // whether the validator is jailed + GetMoniker() string // moniker of the validator + GetStatus() BondStatus // status of the validator + GetOperator() ValAddress // operator address to receive/return validators coins + GetConsPubKey() crypto.PubKey // validation pubkey + GetConsAddr() ConsAddress // validation pubkey + GetPower() Dec // validation power + GetTokens() Dec // validation tokens + GetDelegatorShares() Dec // Total out standing delegator shares + GetBondHeight() int64 // height in which the validator became active } // validator which fulfills abci validator interface for use in Tendermint func ABCIValidator(v Validator) abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.GetPubKey()), - Address: v.GetPubKey().Address(), + PubKey: tmtypes.TM2PB.PubKey(v.GetConsPubKey()), + Address: v.GetConsPubKey().Address(), Power: v.GetPower().RoundInt64(), } } @@ -67,14 +68,15 @@ type ValidatorSet interface { IterateValidatorsBonded(Context, func(index int64, validator Validator) (stop bool)) - Validator(Context, ValAddress) Validator // get a particular validator by operator - ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey - TotalPower(Context) Dec // total power of the validator set + Validator(Context, ValAddress) Validator // get a particular validator by operator address + ValidatorByConsPubKey(Context, crypto.PubKey) Validator // get a particular validator by consensus PubKey + ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address + TotalPower(Context) Dec // total power of the validator set // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction - Slash(Context, crypto.PubKey, int64, int64, Dec) - Jail(Context, crypto.PubKey) // jail a validator - Unjail(Context, crypto.PubKey) // unjail a validator + Slash(Context, ConsAddress, int64, int64, Dec) + Jail(Context, ConsAddress) // jail a validator + Unjail(Context, ConsAddress) // unjail a validator // Delegation allows for getting a particular delegation for a given validator // and delegator outside the scope of the staking module. @@ -87,7 +89,7 @@ type ValidatorSet interface { type Delegation interface { GetDelegator() AccAddress // delegator AccAddress for the bond GetValidator() ValAddress // validator operator address - GetBondShares() Dec // amount of validator's shares + GetShares() Dec // amount of validator's shares held in this delegation } // properties for the set of all delegations for a particular diff --git a/x/gov/endblocker_test.go b/x/gov/endblocker_test.go index 4cbd1d7588..710ecb1dba 100644 --- a/x/gov/endblocker_test.go +++ b/x/gov/endblocker_test.go @@ -2,7 +2,6 @@ package gov import ( "testing" - "time" "github.com/stretchr/testify/require" @@ -29,18 +28,12 @@ func TestTickExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(250) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -66,10 +59,7 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -78,20 +68,14 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { res = govHandler(ctx, newProposalMsg2) require.True(t, res.IsOK()) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(205) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(215) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -121,10 +105,7 @@ func TestTickPassedDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -165,20 +146,14 @@ func TestTickPassedVotingPeriod(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)}) res = govHandler(ctx, newDepositMsg) require.True(t, res.IsOK()) EndBlocker(ctx, keeper) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(215) require.True(t, shouldPopActiveProposalQueue(ctx, keeper)) depositsIterator := keeper.GetDeposits(ctx, proposalID) require.True(t, depositsIterator.Valid()) @@ -222,10 +197,7 @@ func TestSlashing(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - newHeader := ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(10) require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) newVoteMsg := NewMsgVote(addrs[0], proposalID, OptionYes) @@ -234,10 +206,7 @@ func TestSlashing(t *testing.T) { EndBlocker(ctx, keeper) - newHeader = ctx.BlockHeader() - newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) - ctx = ctx.WithBlockHeader(newHeader) - + ctx = ctx.WithBlockHeight(215) require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) EndBlocker(ctx, keeper) diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 58273c8e84..15f952c000 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -1,8 +1,6 @@ package gov import ( - "time" - sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -29,10 +27,10 @@ func DefaultGenesisState() GenesisState { StartingProposalID: 1, DepositProcedure: DepositProcedure{ MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)}, - MaxDepositPeriod: time.Duration(172800) * time.Second, + MaxDepositPeriod: 200, }, VotingProcedure: VotingProcedure{ - VotingPeriod: time.Duration(172800) * time.Second, + VotingPeriod: 200, }, TallyingProcedure: TallyingProcedure{ Threshold: sdk.NewDecWithPrec(5, 1), diff --git a/x/gov/handler.go b/x/gov/handler.go index e8cdf49aa5..84964b20f6 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -128,9 +128,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { for shouldPopActiveProposalQueue(ctx, keeper) { activeProposal := keeper.ActiveProposalQueuePop(ctx) - proposalStartTime := activeProposal.GetVotingStartTime() + proposalStartBlock := activeProposal.GetVotingStartBlock() votingPeriod := keeper.GetVotingProcedure(ctx).VotingPeriod - if ctx.BlockHeader().Time.Before(proposalStartTime.Add(votingPeriod)) { + if ctx.BlockHeight() < proposalStartBlock+votingPeriod { continue } @@ -155,7 +155,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { for _, valAddr := range nonVotingVals { val := keeper.ds.GetValidatorSet().Validator(ctx, valAddr) keeper.ds.GetValidatorSet().Slash(ctx, - val.GetPubKey(), + val.GetConsAddr(), ctx.BlockHeight(), val.GetPower().RoundInt64(), keeper.GetTallyingProcedure(ctx).GovernancePenalty) @@ -178,7 +178,7 @@ func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { return false } else if peekProposal.GetStatus() != StatusDepositPeriod { return true - } else if !ctx.BlockHeader().Time.Before(peekProposal.GetSubmitTime().Add(depositProcedure.MaxDepositPeriod)) { + } else if ctx.BlockHeight() >= peekProposal.GetSubmitBlock()+depositProcedure.MaxDepositPeriod { return true } return false @@ -190,7 +190,7 @@ func shouldPopActiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { if peekProposal == nil { return false - } else if !ctx.BlockHeader().Time.Before(peekProposal.GetVotingStartTime().Add(votingProcedure.VotingPeriod)) { + } else if ctx.BlockHeight() >= peekProposal.GetVotingStartBlock()+votingProcedure.VotingPeriod { return true } return false diff --git a/x/gov/keeper.go b/x/gov/keeper.go index 8af2d1fd3a..bebcf51e78 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -66,14 +66,15 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description return nil } var proposal Proposal = &TextProposal{ - ProposalID: proposalID, - Title: title, - Description: description, - ProposalType: proposalType, - Status: StatusDepositPeriod, - TallyResult: EmptyTallyResult(), - TotalDeposit: sdk.Coins{}, - SubmitTime: ctx.BlockHeader().Time, + ProposalID: proposalID, + Title: title, + Description: description, + ProposalType: proposalType, + Status: StatusDepositPeriod, + TallyResult: EmptyTallyResult(), + TotalDeposit: sdk.Coins{}, + SubmitBlock: ctx.BlockHeight(), + VotingStartBlock: -1, // TODO: Make Time } keeper.SetProposal(ctx, proposal) keeper.InactiveProposalQueuePush(ctx, proposal) @@ -199,7 +200,7 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e } func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) { - proposal.SetVotingStartTime(ctx.BlockHeader().Time) + proposal.SetVotingStartBlock(ctx.BlockHeight()) proposal.SetStatus(StatusVotingPeriod) keeper.SetProposal(ctx, proposal) keeper.ActiveProposalQueuePush(ctx, proposal) diff --git a/x/gov/keeper_test.go b/x/gov/keeper_test.go index 91c41d7d7d..a61292b93e 100644 --- a/x/gov/keeper_test.go +++ b/x/gov/keeper_test.go @@ -2,7 +2,6 @@ package gov import ( "testing" - "time" "github.com/stretchr/testify/require" @@ -46,12 +45,12 @@ func TestActivateVotingPeriod(t *testing.T) { proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) - require.True(t, proposal.GetVotingStartTime().Equal(time.Time{})) + require.Equal(t, int64(-1), proposal.GetVotingStartBlock()) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) keeper.activateVotingPeriod(ctx, proposal) - require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time)) + require.Equal(t, proposal.GetVotingStartBlock(), ctx.BlockHeight()) require.Equal(t, proposal.GetProposalID(), keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) } @@ -78,7 +77,7 @@ func TestDeposits(t *testing.T) { // Check no deposits at beginning deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1]) require.False(t, found) - require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{})) + require.Equal(t, keeper.GetProposal(ctx, proposalID).GetVotingStartBlock(), int64(-1)) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) // Check first deposit @@ -115,7 +114,7 @@ func TestDeposits(t *testing.T) { require.Equal(t, addr1Initial.Minus(fourSteak), keeper.ck.GetCoins(ctx, addrs[1])) // Check that proposal moved to voting period - require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time)) + require.Equal(t, ctx.BlockHeight(), keeper.GetProposal(ctx, proposalID).GetVotingStartBlock()) require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx)) require.Equal(t, proposalID, keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) diff --git a/x/gov/procedures.go b/x/gov/procedures.go index e453add791..f74091c74f 100644 --- a/x/gov/procedures.go +++ b/x/gov/procedures.go @@ -1,15 +1,13 @@ package gov import ( - "time" - sdk "github.com/cosmos/cosmos-sdk/types" ) // Procedure around Deposits for governance type DepositProcedure struct { - MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months + MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. + MaxDepositPeriod int64 `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months } // Procedure around Tallying votes in governance @@ -21,5 +19,5 @@ type TallyingProcedure struct { // Procedure around Voting in governance type VotingProcedure struct { - VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period. + VotingPeriod int64 `json:"voting_period"` // Length of the voting period. } diff --git a/x/gov/proposals.go b/x/gov/proposals.go index e680699575..b4c6783673 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -3,7 +3,6 @@ package gov import ( "encoding/json" "fmt" - "time" "github.com/pkg/errors" @@ -31,14 +30,14 @@ type Proposal interface { GetTallyResult() TallyResult SetTallyResult(TallyResult) - GetSubmitTime() time.Time - SetSubmitTime(time.Time) + GetSubmitBlock() int64 + SetSubmitBlock(int64) GetTotalDeposit() sdk.Coins SetTotalDeposit(sdk.Coins) - GetVotingStartTime() time.Time - SetVotingStartTime(time.Time) + GetVotingStartBlock() int64 + SetVotingStartBlock(int64) } // checks if two proposals are equal @@ -49,9 +48,9 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool { proposalA.GetProposalType() == proposalB.GetProposalType() && proposalA.GetStatus() == proposalB.GetStatus() && proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) && - proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) && + proposalA.GetSubmitBlock() == proposalB.GetSubmitBlock() && proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) && - proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) { + proposalA.GetVotingStartBlock() == proposalB.GetVotingStartBlock() { return true } return false @@ -68,10 +67,10 @@ type TextProposal struct { Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected} TallyResult TallyResult `json:"tally_result"` // Result of Tallys - SubmitTime time.Time `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included + SubmitBlock int64 `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit - VotingStartTime time.Time `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached + VotingStartBlock int64 `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached } // Implements Proposal Interface @@ -90,13 +89,13 @@ func (tp TextProposal) GetStatus() ProposalStatus { return tp.S func (tp *TextProposal) SetStatus(status ProposalStatus) { tp.Status = status } func (tp TextProposal) GetTallyResult() TallyResult { return tp.TallyResult } func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult } -func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime } -func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime } +func (tp TextProposal) GetSubmitBlock() int64 { return tp.SubmitBlock } +func (tp *TextProposal) SetSubmitBlock(submitBlock int64) { tp.SubmitBlock = submitBlock } func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit } func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit } -func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime } -func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) { - tp.VotingStartTime = votingStartTime +func (tp TextProposal) GetVotingStartBlock() int64 { return tp.VotingStartBlock } +func (tp *TextProposal) SetVotingStartBlock(votingStartBlock int64) { + tp.VotingStartBlock = votingStartBlock } //----------------------------------------------------------- diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index f46fe995e1..168081b188 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -4,7 +4,6 @@ import ( "fmt" "math" "math/rand" - "time" "github.com/tendermint/tendermint/crypto" @@ -69,8 +68,8 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe votingPeriod := k.GetVotingProcedure(ctx).VotingPeriod fops := make([]simulation.FutureOperation, numVotes+1) for i := 0; i < numVotes; i++ { - whenVote := ctx.BlockHeader().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second) - fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, sk, keys[whoVotes[i]], proposalID)} + whenVote := ctx.BlockHeight() + r.Int63n(votingPeriod) + fops[i] = simulation.FutureOperation{BlockHeight: int(whenVote), Op: operationSimulateMsgVote(k, sk, keys[whoVotes[i]], proposalID)} } // 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant) // TODO: Find a way to check if a validator was slashed other than just checking their balance a block diff --git a/x/gov/tally.go b/x/gov/tally.go index a756eaf926..55fd81da24 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -53,10 +53,10 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall valAddrStr := delegation.GetValidator().String() if val, ok := currValidators[valAddrStr]; ok { - val.Minus = val.Minus.Add(delegation.GetBondShares()) + val.Minus = val.Minus.Add(delegation.GetShares()) currValidators[valAddrStr] = val - delegatorShare := delegation.GetBondShares().Quo(val.DelegatorShares) + delegatorShare := delegation.GetShares().Quo(val.DelegatorShares) votingPower := val.Power.Mul(delegatorShare) results[vote.Option] = results[vote.Option].Add(votingPower) diff --git a/x/gov/tally_test.go b/x/gov/tally_test.go index 6c6d64aa67..9c5348b2c7 100644 --- a/x/gov/tally_test.go +++ b/x/gov/tally_test.go @@ -440,7 +440,7 @@ func TestTallyJailedValidator(t *testing.T) { val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1])) require.True(t, found) - sk.Jail(ctx, val2.ConsPubKey) + sk.Jail(ctx, sdk.ConsAddress(val2.ConsPubKey.Address())) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() diff --git a/x/slashing/genesis.go b/x/slashing/genesis.go index 6e2809bfcb..43ae6b0d0a 100644 --- a/x/slashing/genesis.go +++ b/x/slashing/genesis.go @@ -8,7 +8,7 @@ import ( // InitGenesis initializes the keeper's address to pubkey map. func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { for _, validator := range data.Validators { - keeper.addPubkey(ctx, validator.GetPubKey()) + keeper.addPubkey(ctx, validator.GetConsPubKey()) } return } diff --git a/x/slashing/handler.go b/x/slashing/handler.go index 4f342f62a0..740166d2af 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -34,7 +34,7 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { return ErrValidatorNotJailed(k.codespace).Result() } - consAddr := sdk.ConsAddress(validator.GetPubKey().Address()) + consAddr := sdk.ConsAddress(validator.GetConsPubKey().Address()) info, found := k.getValidatorSigningInfo(ctx, consAddr) if !found { diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index 701a6b2cde..92c4cf85f8 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -29,10 +29,10 @@ type Hooks struct { k Keeper } -var _ sdk.StakingHooks = Hooks{} +var _ sdk.ValidatorHooks = Hooks{} // Return the wrapper struct -func (k Keeper) Hooks() Hooks { +func (k Keeper) ValidatorHooks() Hooks { return Hooks{k} } @@ -45,11 +45,3 @@ func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { h.k.onValidatorBeginUnbonding(ctx, address) } - -// nolint - unused hooks -func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {} -func (h Hooks) OnValidatorCommissionChange(_ sdk.Context, _ sdk.ValAddress) {} -func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {} -func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} -func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} -func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} diff --git a/x/stake/genesis.go b/x/stake/genesis.go index a7f8493081..58b7ed1b4f 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -75,7 +75,7 @@ func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisValidator) { keeper.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) (stop bool) { vals = append(vals, tmtypes.GenesisValidator{ - PubKey: validator.GetPubKey(), + PubKey: validator.GetConsPubKey(), Power: validator.GetPower().RoundInt64(), Name: validator.GetMoniker(), }) diff --git a/x/stake/handler.go b/x/stake/handler.go index 005b3af7d0..f4864a14a6 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -87,11 +87,6 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k return err.Result() } - // call the hook if present - k.OnValidatorCreated(ctx, validator.OperatorAddr) - accAddr := sdk.AccAddress(validator.OperatorAddr) - k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) - tags := sdk.NewTags( tags.Action, tags.ActionCreateValidator, tags.DstValidator, []byte(msg.ValidatorAddr.String()), @@ -151,9 +146,6 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) return err.Result() } - // call the hook if present - k.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) - tags := sdk.NewTags( tags.Action, tags.ActionDelegate, tags.Delegator, []byte(msg.DelegatorAddr.String()), diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 6ac51ac196..6efa4c8ed3 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -67,11 +67,6 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { // remove a delegation from store func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { - // call the hook if present - if k.hooks != nil { - k.hooks.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr) - } - store := ctx.KVStore(k.storeKey) store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) } @@ -281,11 +276,6 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co k.SetDelegation(ctx, delegation) k.UpdateValidator(ctx, validator) - // call the hook if present - if k.hooks != nil { - k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) - } - return } @@ -344,11 +334,6 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA k.RemoveValidator(ctx, validator.OperatorAddr) } - // call the hook if present - if k.hooks != nil { - k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) - } - return amount, nil } diff --git a/x/stake/keeper/hooks.go b/x/stake/keeper/hooks.go deleted file mode 100644 index 81bf5594ba..0000000000 --- a/x/stake/keeper/hooks.go +++ /dev/null @@ -1,54 +0,0 @@ -//nolint -package keeper - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// Expose the hooks if present -func (k Keeper) OnValidatorCreated(ctx sdk.Context, address sdk.ValAddress) { - if k.hooks != nil { - k.hooks.OnValidatorCreated(ctx, address) - } -} -func (k Keeper) OnValidatorCommissionChange(ctx sdk.Context, address sdk.ValAddress) { - if k.hooks != nil { - k.hooks.OnValidatorCommissionChange(ctx, address) - } -} - -func (k Keeper) OnValidatorRemoved(ctx sdk.Context, address sdk.ValAddress) { - if k.hooks != nil { - k.hooks.OnValidatorRemoved(ctx, address) - } -} - -func (k Keeper) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { - if k.hooks != nil { - k.hooks.OnValidatorBonded(ctx, address) - } -} - -func (k Keeper) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { - if k.hooks != nil { - k.hooks.OnValidatorBeginUnbonding(ctx, address) - } -} - -func (k Keeper) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - if k.hooks != nil { - k.hooks.OnDelegationCreated(ctx, delAddr, valAddr) - } -} - -func (k Keeper) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - if k.hooks != nil { - k.hooks.OnDelegationSharesModified(ctx, delAddr, valAddr) - } -} - -func (k Keeper) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - if k.hooks != nil { - k.hooks.OnDelegationRemoved(ctx, delAddr, valAddr) - } -} diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index 82170a4aed..0f700f9ab8 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -14,7 +14,7 @@ type Keeper struct { storeTKey sdk.StoreKey cdc *codec.Codec bankKeeper bank.Keeper - hooks sdk.StakingHooks + hooks sdk.ValidatorHooks // codespace codespace sdk.CodespaceType @@ -33,7 +33,7 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespa } // Set the validator hooks -func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { +func (k Keeper) WithValidatorHooks(sh sdk.ValidatorHooks) Keeper { if k.hooks != nil { panic("cannot set validator hooks twice") } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index af7d77e207..d4fe76b70e 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -681,11 +681,6 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // remove the validator record and associated indexes func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { - // call the hook if present - if k.hooks != nil { - k.hooks.OnValidatorRemoved(ctx, address) - } - // first retrieve the old validator record validator, found := k.GetValidator(ctx, address) if !found { @@ -745,36 +740,3 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr)) } } - -//__________________________________________________________________________ - -// XXX remove this code - this is should be superceded by commission work that bez is doing -// get a single validator -func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { - - // call the hook if present - if k.hooks != nil { - k.hooks.OnValidatorCommissionChange(ctx, addr) - } - - validator, found := k.GetValidator(ctx, addr) - - // check for errors - switch { - case !found: - return types.ErrNoValidatorFound(k.Codespace()) - case newCommission.LT(sdk.ZeroDec()): - return types.ErrCommissionNegative(k.Codespace()) - case newCommission.GT(validator.CommissionMax): - return types.ErrCommissionBeyondMax(k.Codespace()) - //case rateChange(Commission) > CommissionMaxChange: // XXX XXX XXX TODO implementation - //return types.ErrCommissionPastRate(k.Codespace()) - } - - // TODO adjust all the commission terms appropriately - - validator.Commission = newCommission - - k.SetValidator(ctx, validator) - return nil -} diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index c15d43396c..38cc127b0b 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -474,7 +474,7 @@ func (v Validator) GetJailed() bool { return v.Jailed } func (v Validator) GetMoniker() string { return v.Description.Moniker } func (v Validator) GetStatus() sdk.BondStatus { return v.Status } func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } -func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } +func (v Validator) GetConsPubKey() crypto.PubKey { return v.ConsPubKey } func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) } func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } func (v Validator) GetTokens() sdk.Dec { return v.Tokens } From 9e2b8e413d6bf6e3358ff04f3f5a3be9b6fe7257 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 21:22:28 -0400 Subject: [PATCH 36/99] revert some gov changes --- types/stake.go | 4 ++-- x/gov/endblocker_test.go | 51 ++++++++++++++++++++++++++++++++-------- x/gov/genesis.go | 6 +++-- x/gov/handler.go | 8 +++---- x/gov/keeper.go | 19 +++++++-------- x/gov/keeper_test.go | 9 +++---- x/gov/procedures.go | 8 ++++--- x/gov/proposals.go | 27 +++++++++++---------- x/gov/simulation/msgs.go | 5 ++-- x/gov/tally_test.go | 2 +- 10 files changed, 88 insertions(+), 51 deletions(-) diff --git a/types/stake.go b/types/stake.go index b8740a3cb9..ade96843dd 100644 --- a/types/stake.go +++ b/types/stake.go @@ -41,8 +41,8 @@ type Validator interface { GetMoniker() string // moniker of the validator GetStatus() BondStatus // status of the validator GetOperator() ValAddress // operator address to receive/return validators coins - GetConsPubKey() crypto.PubKey // validation pubkey - GetConsAddr() ConsAddress // validation pubkey + GetConsPubKey() crypto.PubKey // validation consensus pubkey + GetConsAddr() ConsAddress // validation consensus address GetPower() Dec // validation power GetTokens() Dec // validation tokens GetDelegatorShares() Dec // Total out standing delegator shares diff --git a/x/gov/endblocker_test.go b/x/gov/endblocker_test.go index 710ecb1dba..4cbd1d7588 100644 --- a/x/gov/endblocker_test.go +++ b/x/gov/endblocker_test.go @@ -2,6 +2,7 @@ package gov import ( "testing" + "time" "github.com/stretchr/testify/require" @@ -28,12 +29,18 @@ func TestTickExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(250) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -59,7 +66,10 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -68,14 +78,20 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { res = govHandler(ctx, newProposalMsg2) require.True(t, res.IsOK()) - ctx = ctx.WithBlockHeight(205) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(215) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -105,7 +121,10 @@ func TestTickPassedDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -146,14 +165,20 @@ func TestTickPassedVotingPeriod(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)}) res = govHandler(ctx, newDepositMsg) require.True(t, res.IsOK()) EndBlocker(ctx, keeper) - ctx = ctx.WithBlockHeight(215) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) + ctx = ctx.WithBlockHeader(newHeader) + require.True(t, shouldPopActiveProposalQueue(ctx, keeper)) depositsIterator := keeper.GetDeposits(ctx, proposalID) require.True(t, depositsIterator.Valid()) @@ -197,7 +222,10 @@ func TestSlashing(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) newVoteMsg := NewMsgVote(addrs[0], proposalID, OptionYes) @@ -206,7 +234,10 @@ func TestSlashing(t *testing.T) { EndBlocker(ctx, keeper) - ctx = ctx.WithBlockHeight(215) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) + ctx = ctx.WithBlockHeader(newHeader) + require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) EndBlocker(ctx, keeper) diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 15f952c000..58273c8e84 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -1,6 +1,8 @@ package gov import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -27,10 +29,10 @@ func DefaultGenesisState() GenesisState { StartingProposalID: 1, DepositProcedure: DepositProcedure{ MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)}, - MaxDepositPeriod: 200, + MaxDepositPeriod: time.Duration(172800) * time.Second, }, VotingProcedure: VotingProcedure{ - VotingPeriod: 200, + VotingPeriod: time.Duration(172800) * time.Second, }, TallyingProcedure: TallyingProcedure{ Threshold: sdk.NewDecWithPrec(5, 1), diff --git a/x/gov/handler.go b/x/gov/handler.go index 84964b20f6..00eaf37440 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -128,9 +128,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { for shouldPopActiveProposalQueue(ctx, keeper) { activeProposal := keeper.ActiveProposalQueuePop(ctx) - proposalStartBlock := activeProposal.GetVotingStartBlock() + proposalStartTime := activeProposal.GetVotingStartTime() votingPeriod := keeper.GetVotingProcedure(ctx).VotingPeriod - if ctx.BlockHeight() < proposalStartBlock+votingPeriod { + if ctx.BlockHeader().Time.Before(proposalStartTime.Add(votingPeriod)) { continue } @@ -178,7 +178,7 @@ func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { return false } else if peekProposal.GetStatus() != StatusDepositPeriod { return true - } else if ctx.BlockHeight() >= peekProposal.GetSubmitBlock()+depositProcedure.MaxDepositPeriod { + } else if !ctx.BlockHeader().Time.Before(peekProposal.GetSubmitTime().Add(depositProcedure.MaxDepositPeriod)) { return true } return false @@ -190,7 +190,7 @@ func shouldPopActiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { if peekProposal == nil { return false - } else if ctx.BlockHeight() >= peekProposal.GetVotingStartBlock()+votingProcedure.VotingPeriod { + } else if !ctx.BlockHeader().Time.Before(peekProposal.GetVotingStartTime().Add(votingProcedure.VotingPeriod)) { return true } return false diff --git a/x/gov/keeper.go b/x/gov/keeper.go index bebcf51e78..8af2d1fd3a 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -66,15 +66,14 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description return nil } var proposal Proposal = &TextProposal{ - ProposalID: proposalID, - Title: title, - Description: description, - ProposalType: proposalType, - Status: StatusDepositPeriod, - TallyResult: EmptyTallyResult(), - TotalDeposit: sdk.Coins{}, - SubmitBlock: ctx.BlockHeight(), - VotingStartBlock: -1, // TODO: Make Time + ProposalID: proposalID, + Title: title, + Description: description, + ProposalType: proposalType, + Status: StatusDepositPeriod, + TallyResult: EmptyTallyResult(), + TotalDeposit: sdk.Coins{}, + SubmitTime: ctx.BlockHeader().Time, } keeper.SetProposal(ctx, proposal) keeper.InactiveProposalQueuePush(ctx, proposal) @@ -200,7 +199,7 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e } func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) { - proposal.SetVotingStartBlock(ctx.BlockHeight()) + proposal.SetVotingStartTime(ctx.BlockHeader().Time) proposal.SetStatus(StatusVotingPeriod) keeper.SetProposal(ctx, proposal) keeper.ActiveProposalQueuePush(ctx, proposal) diff --git a/x/gov/keeper_test.go b/x/gov/keeper_test.go index a61292b93e..91c41d7d7d 100644 --- a/x/gov/keeper_test.go +++ b/x/gov/keeper_test.go @@ -2,6 +2,7 @@ package gov import ( "testing" + "time" "github.com/stretchr/testify/require" @@ -45,12 +46,12 @@ func TestActivateVotingPeriod(t *testing.T) { proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) - require.Equal(t, int64(-1), proposal.GetVotingStartBlock()) + require.True(t, proposal.GetVotingStartTime().Equal(time.Time{})) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) keeper.activateVotingPeriod(ctx, proposal) - require.Equal(t, proposal.GetVotingStartBlock(), ctx.BlockHeight()) + require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time)) require.Equal(t, proposal.GetProposalID(), keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) } @@ -77,7 +78,7 @@ func TestDeposits(t *testing.T) { // Check no deposits at beginning deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1]) require.False(t, found) - require.Equal(t, keeper.GetProposal(ctx, proposalID).GetVotingStartBlock(), int64(-1)) + require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{})) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) // Check first deposit @@ -114,7 +115,7 @@ func TestDeposits(t *testing.T) { require.Equal(t, addr1Initial.Minus(fourSteak), keeper.ck.GetCoins(ctx, addrs[1])) // Check that proposal moved to voting period - require.Equal(t, ctx.BlockHeight(), keeper.GetProposal(ctx, proposalID).GetVotingStartBlock()) + require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time)) require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx)) require.Equal(t, proposalID, keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) diff --git a/x/gov/procedures.go b/x/gov/procedures.go index f74091c74f..e453add791 100644 --- a/x/gov/procedures.go +++ b/x/gov/procedures.go @@ -1,13 +1,15 @@ package gov import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" ) // Procedure around Deposits for governance type DepositProcedure struct { - MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod int64 `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months + MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. + MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months } // Procedure around Tallying votes in governance @@ -19,5 +21,5 @@ type TallyingProcedure struct { // Procedure around Voting in governance type VotingProcedure struct { - VotingPeriod int64 `json:"voting_period"` // Length of the voting period. + VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period. } diff --git a/x/gov/proposals.go b/x/gov/proposals.go index b4c6783673..e680699575 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -3,6 +3,7 @@ package gov import ( "encoding/json" "fmt" + "time" "github.com/pkg/errors" @@ -30,14 +31,14 @@ type Proposal interface { GetTallyResult() TallyResult SetTallyResult(TallyResult) - GetSubmitBlock() int64 - SetSubmitBlock(int64) + GetSubmitTime() time.Time + SetSubmitTime(time.Time) GetTotalDeposit() sdk.Coins SetTotalDeposit(sdk.Coins) - GetVotingStartBlock() int64 - SetVotingStartBlock(int64) + GetVotingStartTime() time.Time + SetVotingStartTime(time.Time) } // checks if two proposals are equal @@ -48,9 +49,9 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool { proposalA.GetProposalType() == proposalB.GetProposalType() && proposalA.GetStatus() == proposalB.GetStatus() && proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) && - proposalA.GetSubmitBlock() == proposalB.GetSubmitBlock() && + proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) && proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) && - proposalA.GetVotingStartBlock() == proposalB.GetVotingStartBlock() { + proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) { return true } return false @@ -67,10 +68,10 @@ type TextProposal struct { Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected} TallyResult TallyResult `json:"tally_result"` // Result of Tallys - SubmitBlock int64 `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included + SubmitTime time.Time `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit - VotingStartBlock int64 `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached + VotingStartTime time.Time `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached } // Implements Proposal Interface @@ -89,13 +90,13 @@ func (tp TextProposal) GetStatus() ProposalStatus { return tp.S func (tp *TextProposal) SetStatus(status ProposalStatus) { tp.Status = status } func (tp TextProposal) GetTallyResult() TallyResult { return tp.TallyResult } func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult } -func (tp TextProposal) GetSubmitBlock() int64 { return tp.SubmitBlock } -func (tp *TextProposal) SetSubmitBlock(submitBlock int64) { tp.SubmitBlock = submitBlock } +func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime } +func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime } func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit } func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit } -func (tp TextProposal) GetVotingStartBlock() int64 { return tp.VotingStartBlock } -func (tp *TextProposal) SetVotingStartBlock(votingStartBlock int64) { - tp.VotingStartBlock = votingStartBlock +func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime } +func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) { + tp.VotingStartTime = votingStartTime } //----------------------------------------------------------- diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 168081b188..f46fe995e1 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "math/rand" + "time" "github.com/tendermint/tendermint/crypto" @@ -68,8 +69,8 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe votingPeriod := k.GetVotingProcedure(ctx).VotingPeriod fops := make([]simulation.FutureOperation, numVotes+1) for i := 0; i < numVotes; i++ { - whenVote := ctx.BlockHeight() + r.Int63n(votingPeriod) - fops[i] = simulation.FutureOperation{BlockHeight: int(whenVote), Op: operationSimulateMsgVote(k, sk, keys[whoVotes[i]], proposalID)} + whenVote := ctx.BlockHeader().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second) + fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, sk, keys[whoVotes[i]], proposalID)} } // 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant) // TODO: Find a way to check if a validator was slashed other than just checking their balance a block diff --git a/x/gov/tally_test.go b/x/gov/tally_test.go index 9c5348b2c7..6c6d64aa67 100644 --- a/x/gov/tally_test.go +++ b/x/gov/tally_test.go @@ -440,7 +440,7 @@ func TestTallyJailedValidator(t *testing.T) { val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1])) require.True(t, found) - sk.Jail(ctx, sdk.ConsAddress(val2.ConsPubKey.Address())) + sk.Jail(ctx, val2.ConsPubKey) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() From 12435070989e253d3ac8c6e01bd1326c913bd8fd Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 22:09:27 -0400 Subject: [PATCH 37/99] no more compile errors in tests --- examples/democoin/mock/validator.go | 22 ++++++++++++++++------ x/gov/tally_test.go | 2 +- x/mock/simulation/constants.go | 4 ++-- x/slashing/keeper_test.go | 6 +++--- x/stake/simulation/invariants.go | 2 +- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index 9f84786adf..a54cdfedf6 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -24,7 +24,12 @@ func (v Validator) GetOperator() sdk.ValAddress { } // Implements sdk.Validator -func (v Validator) GetPubKey() crypto.PubKey { +func (v Validator) GetConsPubKey() crypto.PubKey { + return nil +} + +// Implements sdk.Validator +func (v Validator) GetConsAddr() sdk.ConsAddress { return nil } @@ -88,7 +93,12 @@ func (vs *ValidatorSet) Validator(ctx sdk.Context, addr sdk.ValAddress) sdk.Vali } // ValidatorByPubKey implements sdk.ValidatorSet -func (vs *ValidatorSet) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Validator { +func (vs *ValidatorSet) ValidatorByConsPubKey(_ sdk.Context, _ crypto.PubKey) sdk.Validator { + panic("not implemented") +} + +// ValidatorByPubKey implements sdk.ValidatorSet +func (vs *ValidatorSet) ValidatorByConsAddr(_ sdk.Context, _ sdk.ConsAddress) sdk.Validator { panic("not implemented") } @@ -122,21 +132,21 @@ func (vs *ValidatorSet) RemoveValidator(addr sdk.AccAddress) { } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Dec) { +func (vs *ValidatorSet) Slash(_ sdk.Context, _ sdk.ConsAddress, _ int64, _ int64, _ sdk.Dec) { panic("not implemented") } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Jail(ctx sdk.Context, pubkey crypto.PubKey) { +func (vs *ValidatorSet) Jail(_ sdk.Context, _ sdk.ConsAddress) { panic("not implemented") } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { +func (vs *ValidatorSet) Unjail(_ sdk.Context, _ sdk.ConsAddress) { panic("not implemented") } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk.ValAddress) sdk.Delegation { +func (vs *ValidatorSet) Delegation(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) sdk.Delegation { panic("not implemented") } diff --git a/x/gov/tally_test.go b/x/gov/tally_test.go index 6c6d64aa67..9c5348b2c7 100644 --- a/x/gov/tally_test.go +++ b/x/gov/tally_test.go @@ -440,7 +440,7 @@ func TestTallyJailedValidator(t *testing.T) { val2, found := sk.GetValidator(ctx, sdk.ValAddress(addrs[1])) require.True(t, found) - sk.Jail(ctx, val2.ConsPubKey) + sk.Jail(ctx, sdk.ConsAddress(val2.ConsPubKey.Address())) proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) proposalID := proposal.GetProposalID() diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go index 544da50e3e..985a22dcac 100644 --- a/x/mock/simulation/constants.go +++ b/x/mock/simulation/constants.go @@ -5,10 +5,10 @@ const ( pastEvidenceFraction float64 = 0.5 // Minimum time per block - minTimePerBlock int64 = 1000 / 2 + minTimePerBlock int64 = 86400 / 2 // Maximum time per block - maxTimePerBlock int64 = 1000 + maxTimePerBlock int64 = 86400 // Number of keys numKeys int = 250 diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 1d69f714f0..9a3ff537c2 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -27,7 +27,7 @@ func TestHandleDoubleSign(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithHooks(keeper.Hooks()) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) @@ -69,7 +69,7 @@ func TestSlashingPeriodCap(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithHooks(keeper.Hooks()) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, amt := addrs[0], sdk.NewInt(amtInt) valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address()) @@ -125,7 +125,7 @@ func TestHandleAbsentValidator(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithHooks(keeper.Hooks()) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) diff --git a/x/stake/simulation/invariants.go b/x/stake/simulation/invariants.go index 2ab0717042..cdd80a8c41 100644 --- a/x/stake/simulation/invariants.go +++ b/x/stake/simulation/invariants.go @@ -80,7 +80,7 @@ func PositivePowerInvariant(k stake.Keeper) simulation.Invariant { var err error k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool { if !validator.GetPower().GT(sdk.ZeroDec()) { - err = fmt.Errorf("validator with non-positive power stored. (pubkey %v)", validator.GetPubKey()) + err = fmt.Errorf("validator with non-positive power stored. (pubkey %v)", validator.GetConsPubKey()) return true } return false From 787a2f990e596a3e5bb225412c384e938903121d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 22:36:33 -0400 Subject: [PATCH 38/99] fix using cons address, also remove old commented distr code --- x/distribution/keeper.go | 91 -------------------------- x/distribution/keeper_test.go | 31 --------- x/distribution/movement.go | 72 --------------------- x/distribution/types.go | 107 ------------------------------- x/stake/keeper/slash.go | 2 +- x/stake/keeper/slash_test.go | 1 + x/stake/keeper/validator.go | 2 +- x/stake/keeper/validator_test.go | 9 +++ 8 files changed, 12 insertions(+), 303 deletions(-) delete mode 100644 x/distribution/keeper.go delete mode 100644 x/distribution/keeper_test.go delete mode 100644 x/distribution/movement.go delete mode 100644 x/distribution/types.go diff --git a/x/distribution/keeper.go b/x/distribution/keeper.go deleted file mode 100644 index 937a4674cf..0000000000 --- a/x/distribution/keeper.go +++ /dev/null @@ -1,91 +0,0 @@ -package stake - -//// keeper of the staking store -//type Keeper struct { -//storeKey sdk.StoreKey -//cdc *codec.Codec -//bankKeeper bank.Keeper - -//// codespace -//codespace sdk.CodespaceType -//} - -//func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { -//keeper := Keeper{ -//storeKey: key, -//cdc: cdc, -//bankKeeper: ck, -//codespace: codespace, -//} -//return keeper -//} - -////_________________________________________________________________________ - -//// cummulative power of the non-absent prevotes -//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Dec { -//store := ctx.KVStore(k.storeKey) - -//// get absent prevote indexes -//absents := ctx.AbsentValidators() - -//TotalPower := sdk.ZeroDec() -//i := int32(0) -//iterator := store.SubspaceIterator(ValidatorsBondedKey) -//for ; iterator.Valid(); iterator.Next() { - -//skip := false -//for j, absentIndex := range absents { -//if absentIndex > i { -//break -//} - -//// if non-voting validator found, skip adding its power -//if absentIndex == i { -//absents = append(absents[:j], absents[j+1:]...) // won't need again -//skip = true -//break -//} -//} -//if skip { -//continue -//} - -//bz := iterator.Value() -//var validator Validator -//k.cdc.MustUnmarshalBinary(bz, &validator) -//TotalPower = TotalPower.Add(validator.Power) -//i++ -//} -//iterator.Close() -//return TotalPower -//} - -////_______________________________________________________________________ - -//// XXX TODO trim functionality - -//// retrieve all the power changes which occur after a height -//func (k Keeper) GetPowerChangesAfterHeight(ctx sdk.Context, earliestHeight int64) (pcs []PowerChange) { -//store := ctx.KVStore(k.storeKey) - -//iterator := store.SubspaceIterator(PowerChangeKey) //smallest to largest -//for ; iterator.Valid(); iterator.Next() { -//pcBytes := iterator.Value() -//var pc PowerChange -//k.cdc.MustUnmarshalBinary(pcBytes, &pc) -//if pc.Height < earliestHeight { -//break -//} -//pcs = append(pcs, pc) -//} -//iterator.Close() -//return -//} - -//// set a power change -//func (k Keeper) setPowerChange(ctx sdk.Context, pc PowerChange) { -//store := ctx.KVStore(k.storeKey) -//b := k.cdc.MustMarshalBinary(pc) -//store.Set(GetPowerChangeKey(pc.Height), b) -//} diff --git a/x/distribution/keeper_test.go b/x/distribution/keeper_test.go deleted file mode 100644 index 8902680604..0000000000 --- a/x/distribution/keeper_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package stake - -//// test if is a gotValidator from the last update -//func TestGetTotalPrecommitVotingPower(t *testing.T) { -//ctx, _, keeper := createTestInput(t, false, 0) - -//amts := []int64{10000, 1000, 100, 10, 1} -//var candidatesIn [5]Candidate -//for i, amt := range amts { -//candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{}) -//candidatesIn[i].BondedShares = sdk.NewDec(amt) -//candidatesIn[i].DelegatorShares = sdk.NewDec(amt) -//keeper.setCandidate(ctx, candidatesIn[i]) -//} - -//// test that an empty gotValidator set doesn't have any gotValidators -//gotValidators := keeper.GetValidators(ctx) -//require.Equal(t, 5, len(gotValidators)) - -//totPow := keeper.GetTotalPrecommitVotingPower(ctx) -//exp := sdk.NewDec(11111) -//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow) - -//// set absent gotValidators to be the 1st and 3rd record sorted by pubKey address -//ctx = ctx.WithAbsentValidators([]int32{1, 3}) -//totPow = keeper.GetTotalPrecommitVotingPower(ctx) - -//// XXX verify that this order should infact exclude these two records -//exp = sdk.NewDec(11100) -//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow) -//} diff --git a/x/distribution/movement.go b/x/distribution/movement.go deleted file mode 100644 index 399a25a681..0000000000 --- a/x/distribution/movement.go +++ /dev/null @@ -1,72 +0,0 @@ -package stake - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// burn burn burn -func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} - -//// Handle fee distribution to the validators and delegators -//func (k Keeper) FeeHandler(ctx sdk.Context, collectedFees sdk.Coins) { -//pool := k.GetPool(ctx) -//params := k.GetParams(ctx) - -//// XXX determine -//candidate := NewCandidate(addrs[0], pks[0], Description{}) - -//// calculate the proposer reward -//precommitPower := k.GetTotalPrecommitVotingPower(ctx) -//toProposer := coinsMulRat(collectedFees, (sdk.NewDec(1, 100).Add(sdk.NewDec(4, 100).Mul(precommitPower).Quo(pool.BondedShares)))) -//candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer) - -//toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee) -//pool.FeeReservePool = pool.FeeReservePool.Plus(toReservePool) - -//distributedReward := (collectedFees.Minus(toProposer)).Minus(toReservePool) -//pool.FeePool = pool.FeePool.Plus(distributedReward) -//pool.FeeSumReceived = pool.FeeSumReceived.Plus(distributedReward) -//pool.FeeRecent = distributedReward - -//// lastly update the FeeRecent term -//pool.FeeRecent = collectedFees - -//k.setPool(ctx, pool) -//} - -//func coinsMulRat(coins sdk.Coins, rat sdk.Dec) sdk.Coins { -//var res sdk.Coins -//for _, coin := range coins { -//coinMulAmt := rat.Mul(sdk.NewDec(coin.Amount)).Evaluate() -//coinMul := sdk.Coins{{coin.Denom, coinMulAmt}} -//res = res.Plus(coinMul) -//} -//return res -//} - -////____________________________________________________________________________- - -//// calculate adjustment changes for a candidate at a height -//func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) { - -//heightRat := sdk.NewDec(height) -//lastHeightRat := sdk.NewDec(height - 1) -//candidateFeeCount := candidate.BondedShares.Mul(heightRat) -//poolFeeCount := pool.BondedShares.Mul(heightRat) - -//for i, denom := range denoms { -//poolFeeSumReceived := sdk.NewDec(pool.FeeSumReceived.AmountOf(denom)) -//poolFeeRecent := sdk.NewDec(pool.FeeRecent.AmountOf(denom)) -//// calculate simple and projected pools -//simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived) -//calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent) -//calc2 := candidate.BondedShares.Quo(pool.BondedShares).Mul(poolFeeRecent) -//projectedPool := calc1.Add(calc2) - -//AdjustmentChange := simplePool.Sub(projectedPool) -//candidate.FeeAdjustments[i] = candidate.FeeAdjustments[i].Add(AdjustmentChange) -//pool.FeeAdjustments[i] = pool.FeeAdjustments[i].Add(AdjustmentChange) -//} - -//return candidate, pool -//} diff --git a/x/distribution/types.go b/x/distribution/types.go deleted file mode 100644 index 2234104717..0000000000 --- a/x/distribution/types.go +++ /dev/null @@ -1,107 +0,0 @@ -package stake - -//// GenesisState - all staking state that must be provided at genesis -//type GenesisState struct { -//Pool Pool `json:"pool"` -//Params Params `json:"params"` -//} - -//func NewGenesisState(pool Pool, params Params, candidates []Candidate, bonds []Delegation) GenesisState { -//return GenesisState{ -//Pool: pool, -//Params: params, -//} -//} - -//// get raw genesis raw message for testing -//func DefaultGenesisState() GenesisState { -//return GenesisState{ -//Pool: initialPool(), -//Params: defaultParams(), -//} -//} - -//// fee information for a validator -//type Validator struct { -//Adjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms -//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // total shares of a global hold pools -//} - -////_________________________________________________________________________ - -//// Params defines the high level settings for staking -//type Params struct { -//FeeDenoms []string `json:"fee_denoms"` // accepted fee denoms -//ReservePoolFee sdk.Dec `json:"reserve_pool_fee"` // percent of fees which go to reserve pool -//} - -//func (p Params) equal(p2 Params) bool { -//return p.BondDenom == p2.BondDenom && -//p.ReservePoolFee.Equal(p2.ReservePoolFee) -//} - -//func defaultParams() Params { -//return Params{ -//FeeDenoms: []string{"steak"}, -//ReservePoolFee: sdk.NewDec(5, 100), -//} -//} - -////_________________________________________________________________________ - -//// Pool - dynamic parameters of the current state -//type Pool struct { -//FeeReservePool sdk.Coins `json:"fee_reserve_pool"` // XXX reserve pool of collected fees for use by governance -//FeePool sdk.Coins `json:"fee_pool"` // XXX fee pool for all the fee shares which have already been distributed -//FeeSumReceived sdk.Coins `json:"fee_sum_received"` // XXX sum of all fees received, post reserve pool `json:"fee_sum_received"` -//FeeRecent sdk.Coins `json:"fee_recent"` // XXX most recent fee collected -//FeeAdjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms -//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // XXX last recorded bonded shares -//} - -//func (p Pool) equal(p2 Pool) bool { -//return p.FeeReservePool.IsEqual(p2.FeeReservePool) && -//p.FeePool.IsEqual(p2.FeePool) && -//p.FeeSumReceived.IsEqual(p2.FeeSumReceived) && -//p.FeeRecent.IsEqual(p2.FeeRecent) && -//sdk.DecsEqual(p.FeeAdjustments, p2.FeeAdjustments) && -//p.PrevBondedShares.Equal(p2.PrevBondedShares) -//} - -//// initial pool for testing -//func initialPool() Pool { -//return Pool{ -//FeeReservePool: sdk.Coins(nil), -//FeePool: sdk.Coins(nil), -//FeeSumReceived: sdk.Coins(nil), -//FeeRecent: sdk.Coins(nil), -//FeeAdjustments: []sdk.Dec{sdk.ZeroDec()}, -//PrevBondedShares: sdk.ZeroDec(), -//} -//} - -////_________________________________________________________________________ - -//// Used in calculation of fee shares, added to a queue for each block where a power change occures -//type PowerChange struct { -//Height int64 `json:"height"` // block height at change -//Power sdk.Dec `json:"power"` // total power at change -//PrevPower sdk.Dec `json:"prev_power"` // total power at previous height-1 -//FeesIn sdk.Coins `json:"fees_in"` // fees in at block height -//PrevFeePool sdk.Coins `json:"prev_fee_pool"` // total fees in at previous block height -//} - -////_________________________________________________________________________ -//// KEY MANAGEMENT - -//var ( -//// Keys for store prefixes -//PowerChangeKey = []byte{0x09} // prefix for power change object -//) - -//// get the key for the accumulated update validators -//func GetPowerChangeKey(height int64) []byte { -//heightBytes := make([]byte, binary.MaxVarintLen64) -//binary.BigEndian.PutUint64(heightBytes, ^uint64(height)) // invert height (older validators first) -//return append(PowerChangeKey, heightBytes...) -//} diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index ea378678ae..29adec06a7 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -143,7 +143,7 @@ func (k Keeper) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) { // set the jailed flag on a validator func (k Keeper) setJailed(ctx sdk.Context, consAddr sdk.ConsAddress, isJailed bool) { - validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(consAddr)) + validator, found := k.GetValidatorByConsAddr(ctx, consAddr) if !found { panic(fmt.Errorf("validator with consensus-Address %s not found, cannot set jailed to %v", consAddr, isJailed)) } diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index c4a1edd415..7d2f2f785c 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -14,6 +14,7 @@ import ( // TODO integrate with test_common.go helper (CreateTestInput) // setup helper function - creates two validators func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) { + // setup ctx, _, keeper := CreateTestInput(t, false, amt) params := keeper.GetParams(ctx) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index d4fe76b70e..ef2256e083 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -90,7 +90,7 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { // TODO change to SetValidatorByConsAddr? used for retrieving from ConsPubkey as well- kinda confusing func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - consAddr := sdk.ConsAddress(validator.OperatorAddr.Bytes()) + consAddr := sdk.ConsAddress(validator.ConsPubKey.Address()) store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr) } diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index a541600d9f..356170189a 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -305,10 +305,19 @@ func TestValidatorBasics(t *testing.T) { // set and retrieve a record validators[0] = keeper.UpdateValidator(ctx, validators[0]) + keeper.SetValidatorByConsAddr(ctx, validators[0]) resVal, found := keeper.GetValidator(ctx, addrVals[0]) require.True(t, found) assert.True(ValEq(t, validators[0], resVal)) + // retrieve from consensus + resVal, found = keeper.GetValidatorByConsAddr(ctx, sdk.ConsAddress(PKs[0].Address())) + require.True(t, found) + assert.True(ValEq(t, validators[0], resVal)) + resVal, found = keeper.GetValidatorByConsPubKey(ctx, PKs[0]) + require.True(t, found) + assert.True(ValEq(t, validators[0], resVal)) + resVals = keeper.GetValidatorsBonded(ctx) require.Equal(t, 1, len(resVals)) assert.True(ValEq(t, validators[0], resVals[0])) From 72e302548102ef941dd9da29292ca52121c3cbab Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 22:43:11 -0400 Subject: [PATCH 39/99] doc update --- docs/spec/staking/state.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/spec/staking/state.md b/docs/spec/staking/state.md index f2d6f98541..9d5e129237 100644 --- a/docs/spec/staking/state.md +++ b/docs/spec/staking/state.md @@ -43,12 +43,13 @@ type Params struct { Validators are identified according to the `OperatorAddr`, an SDK validator address for the operator of the validator. -Validators also have a `ConsPubKey`, the public key of the validator. - -Validators are indexed in the store using the following maps: +Validators also have a `ConsPubKey`, the public key of the validator. The +validator can be retrieved from it's `ConsPubKey` once it can be converted into +the corresponding `ConsAddr`. Validators are indexed in the store using the +following maps: - Validators: `0x02 | OperatorAddr -> amino(validator)` -- ValidatorsByPubKey: `0x03 | ConsPubKey -> OperatorAddr` +- ValidatorsByConsAddr: `0x03 | ConsAddr -> OperatorAddr` - ValidatorsByPower: `0x05 | power | blockHeight | blockTx -> OperatorAddr` `Validators` is the primary index - it ensures that each operator can have only one @@ -69,7 +70,7 @@ validator. ```golang type Validator struct { - ConsensusPubKey crypto.PubKey // Tendermint consensus pubkey of validator + ConsPubKey crypto.PubKey // Tendermint consensus pubkey of validator Jailed bool // has the validator been jailed? Status sdk.BondStatus // validator status (bonded/unbonding/unbonded) From b212470d31482607a0a5655f6810b5dd66e37fb6 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 20 Sep 2018 22:49:51 -0400 Subject: [PATCH 40/99] revert some accidental stuff --- x/mock/simulation/constants.go | 4 ++-- x/stake/types/errors.go | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go index 985a22dcac..544da50e3e 100644 --- a/x/mock/simulation/constants.go +++ b/x/mock/simulation/constants.go @@ -5,10 +5,10 @@ const ( pastEvidenceFraction float64 = 0.5 // Minimum time per block - minTimePerBlock int64 = 86400 / 2 + minTimePerBlock int64 = 1000 / 2 // Maximum time per block - maxTimePerBlock int64 = 86400 + maxTimePerBlock int64 = 1000 // Number of keys numKeys int = 250 diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 541ad3d7b9..366012bbfb 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -65,14 +65,6 @@ func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%") } -func ErrCommissionBeyondMax(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than preset commission maximum") -} - -func ErrCommissionPastRate(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission change is greater than the commission rate, please wait before changing your commission more") -} - func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil") } From 14792f2b23a33219c13bd7ea0c819caf14ae7baf Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 22 Sep 2018 13:50:26 -0400 Subject: [PATCH 41/99] val comments --- docs/spec/staking/state.md | 8 ++++---- x/stake/keeper/validator.go | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/spec/staking/state.md b/docs/spec/staking/state.md index 9d5e129237..9454aca7dd 100644 --- a/docs/spec/staking/state.md +++ b/docs/spec/staking/state.md @@ -43,10 +43,10 @@ type Params struct { Validators are identified according to the `OperatorAddr`, an SDK validator address for the operator of the validator. -Validators also have a `ConsPubKey`, the public key of the validator. The -validator can be retrieved from it's `ConsPubKey` once it can be converted into -the corresponding `ConsAddr`. Validators are indexed in the store using the -following maps: +Validators also have a `ConsPubKey`, the public key of the validator used in +Tendermint consensus. The validator can be retrieved from it's `ConsPubKey` +once it can be converted into the corresponding `ConsAddr`. Validators are +indexed in the store using the following maps: - Validators: `0x02 | OperatorAddr -> amino(validator)` - ValidatorsByConsAddr: `0x03 | ConsAddr -> OperatorAddr` diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index ef2256e083..f7c43757ff 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -87,7 +87,6 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { } // validator index -// TODO change to SetValidatorByConsAddr? used for retrieving from ConsPubkey as well- kinda confusing func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) consAddr := sdk.ConsAddress(validator.ConsPubKey.Address()) From d428317f91f0686f50f6fd45db668418a57087f3 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 22 Sep 2018 13:56:48 -0400 Subject: [PATCH 42/99] import decimal from fee-distr PR --- types/decimal.go | 26 ++++++++++++++++++++++++++ types/decimal_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/types/decimal.go b/types/decimal.go index 8e7db1340b..d6c93f617a 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -323,6 +323,32 @@ func (d Dec) RoundInt() Int { //___________________________________________________________________________________ +// similar to chopPrecisionAndRound, but always rounds down +func chopPrecisionAndTruncate(d *big.Int) *big.Int { + return d.Quo(d, precisionReuse) +} + +func chopPrecisionAndTruncateNonMutative(d *big.Int) *big.Int { + tmp := new(big.Int).Set(d) + return chopPrecisionAndTruncate(tmp) +} + +// RoundInt64 rounds the decimal using bankers rounding +func (d Dec) TruncateInt64() int64 { + chopped := chopPrecisionAndTruncateNonMutative(d.Int) + if !chopped.IsInt64() { + panic("Int64() out of bound") + } + return chopped.Int64() +} + +// RoundInt round the decimal using bankers rounding +func (d Dec) TruncateInt() Int { + return NewIntFromBigInt(chopPrecisionAndTruncateNonMutative(d.Int)) +} + +//___________________________________________________________________________________ + // reuse nil values var ( nilAmino string diff --git a/types/decimal_test.go b/types/decimal_test.go index 779460c253..161215467f 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -202,6 +202,32 @@ func TestBankerRoundChop(t *testing.T) { } } +func TestTruncate(t *testing.T) { + tests := []struct { + d1 Dec + exp int64 + }{ + {mustNewDecFromStr(t, "0"), 0}, + {mustNewDecFromStr(t, "0.25"), 0}, + {mustNewDecFromStr(t, "0.75"), 0}, + {mustNewDecFromStr(t, "1"), 1}, + {mustNewDecFromStr(t, "1.5"), 1}, + {mustNewDecFromStr(t, "7.5"), 7}, + {mustNewDecFromStr(t, "7.6"), 7}, + {mustNewDecFromStr(t, "7.4"), 7}, + {mustNewDecFromStr(t, "100.1"), 100}, + {mustNewDecFromStr(t, "1000.1"), 1000}, + } + + for tcIndex, tc := range tests { + resNeg := tc.d1.Neg().TruncateInt64() + require.Equal(t, -1*tc.exp, resNeg, "negative tc %d", tcIndex) + + resPos := tc.d1.TruncateInt64() + require.Equal(t, tc.exp, resPos, "positive tc %d", tcIndex) + } +} + func TestToLeftPadded(t *testing.T) { tests := []struct { dec Dec From 79cfee96236c00ed41bb9c4d005592a65547362b Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 22 Sep 2018 14:51:38 -0400 Subject: [PATCH 43/99] pending --- PENDING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PENDING.md b/PENDING.md index 4d494f3779..700abff649 100644 --- a/PENDING.md +++ b/PENDING.md @@ -89,6 +89,7 @@ FEATURES * [simulation] [\#1924](https://github.com/cosmos/cosmos-sdk/issues/1924) allow operations to specify future operations * [simulation] [\#1924](https://github.com/cosmos/cosmos-sdk/issues/1924) Add benchmarking capabilities, with makefile commands "test_sim_gaia_benchmark, test_sim_gaia_profile" * [simulation] [\#2349](https://github.com/cosmos/cosmos-sdk/issues/2349) Add time-based future scheduled operations to simulator + * [] [\#2349](https://github.com/cosmos/cosmos-sdk/issues/2349) Add time-based future scheduled operations to simulator * Tendermint @@ -125,6 +126,7 @@ IMPROVEMENTS * [simulation] Logs get written to file if large, and also get printed on panics \#2285 * [gaiad] \#1992 Add optional flag to `gaiad testnet` to make config directory of daemon (default `gaiad`) and cli (default `gaiacli`) configurable * [x/stake] Add stake `Queriers` for Gaia-lite endpoints. This increases the staking endpoints performance by reusing the staking `keeper` logic for queries. [#2249](https://github.com/cosmos/cosmos-sdk/pull/2149) + * [types/decimal] \#2378 - Added truncate functionality to decimal * Tendermint From 6012a252bbf0c5a04c08a517927bd914b3d255ba Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 22 Sep 2018 14:52:47 -0400 Subject: [PATCH 44/99] ... --- PENDING.md | 1 - 1 file changed, 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index 700abff649..5cf80cd6f6 100644 --- a/PENDING.md +++ b/PENDING.md @@ -89,7 +89,6 @@ FEATURES * [simulation] [\#1924](https://github.com/cosmos/cosmos-sdk/issues/1924) allow operations to specify future operations * [simulation] [\#1924](https://github.com/cosmos/cosmos-sdk/issues/1924) Add benchmarking capabilities, with makefile commands "test_sim_gaia_benchmark, test_sim_gaia_profile" * [simulation] [\#2349](https://github.com/cosmos/cosmos-sdk/issues/2349) Add time-based future scheduled operations to simulator - * [] [\#2349](https://github.com/cosmos/cosmos-sdk/issues/2349) Add time-based future scheduled operations to simulator * Tendermint From 6f35822d7dc45c70e2e8a1b5579ff0f91ca14743 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 22 Sep 2018 16:29:42 -0400 Subject: [PATCH 45/99] import hook from fee-distr --- cmd/gaia/app/app.go | 2 +- types/stake.go | 25 +++++++++++++---- x/slashing/hooks.go | 12 ++++++-- x/slashing/keeper_test.go | 6 ++-- x/stake/handler.go | 8 ++++++ x/stake/keeper/delegation.go | 9 ++++++ x/stake/keeper/hooks.go | 54 ++++++++++++++++++++++++++++++++++++ x/stake/keeper/keeper.go | 4 +-- x/stake/keeper/validator.go | 30 ++++++++++++++------ 9 files changed, 128 insertions(+), 22 deletions(-) create mode 100644 x/stake/keeper/hooks.go diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 353825121a..31b912a9de 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -91,7 +91,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace)) - app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks()) + app.stakeKeeper = app.stakeKeeper.WithHooks(app.slashingKeeper.Hooks()) app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace)) app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) diff --git a/types/stake.go b/types/stake.go index ade96843dd..03bf5e3bf3 100644 --- a/types/stake.go +++ b/types/stake.go @@ -102,12 +102,25 @@ type DelegationSet interface { fn func(index int64, delegation Delegation) (stop bool)) } -// validator event hooks -// These can be utilized to communicate between a staking keeper -// and another keeper which must take particular actions when -// validators are bonded and unbonded. The second keeper must implement -// this interface, which then the staking keeper can call. -type ValidatorHooks interface { +//_______________________________________________________________________________ +// Event Hooks +// These can be utilized to communicate between a staking keeper and another +// keeper which must take particular actions when validators/delegators change +// state. The second keeper must implement this interface, which then the +// staking keeper can call. + +// TODO refactor event hooks out to the receiver modules + +// event hooks for staking validator object +type StakingHooks interface { + OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created + OnValidatorCommissionChange(ctx Context, address ValAddress) // Must be called when a validator's commission is modified + OnValidatorRemoved(ctx Context, address ValAddress) // Must be called when a validator is deleted + OnValidatorBonded(ctx Context, address ConsAddress) // Must be called when a validator is bonded OnValidatorBeginUnbonding(ctx Context, address ConsAddress) // Must be called when a validator begins unbonding + + OnDelegationCreated(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is created + OnDelegationSharesModified(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation's shares are modified + OnDelegationRemoved(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is removed } diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index 92c4cf85f8..701a6b2cde 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -29,10 +29,10 @@ type Hooks struct { k Keeper } -var _ sdk.ValidatorHooks = Hooks{} +var _ sdk.StakingHooks = Hooks{} // Return the wrapper struct -func (k Keeper) ValidatorHooks() Hooks { +func (k Keeper) Hooks() Hooks { return Hooks{k} } @@ -45,3 +45,11 @@ func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { h.k.onValidatorBeginUnbonding(ctx, address) } + +// nolint - unused hooks +func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnValidatorCommissionChange(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} +func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 9a3ff537c2..1d69f714f0 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -27,7 +27,7 @@ func TestHandleDoubleSign(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) @@ -69,7 +69,7 @@ func TestSlashingPeriodCap(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) addr, amt := addrs[0], sdk.NewInt(amtInt) valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address()) @@ -125,7 +125,7 @@ func TestHandleAbsentValidator(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) + sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) diff --git a/x/stake/handler.go b/x/stake/handler.go index f4864a14a6..b3bf4c018b 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -87,6 +87,11 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k return err.Result() } + // call hooks + k.OnValidatorCreated(ctx, validator.OperatorAddr) + accAddr := sdk.AccAddress(validator.OperatorAddr) + k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) + tags := sdk.NewTags( tags.Action, tags.ActionCreateValidator, tags.DstValidator, []byte(msg.ValidatorAddr.String()), @@ -146,6 +151,9 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) return err.Result() } + // call the hook if present + k.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) + tags := sdk.NewTags( tags.Action, tags.ActionDelegate, tags.Delegator, []byte(msg.DelegatorAddr.String()), diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 6efa4c8ed3..a2392ac587 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -67,6 +67,9 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { // remove a delegation from store func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { + // call hook + k.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr) + store := ctx.KVStore(k.storeKey) store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) } @@ -283,6 +286,9 @@ 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) { + // call hook + k.OnDelegationSharesModified(ctx, delAddr, valAddr) + // check if delegation has any shares in it unbond delegation, found := k.GetDelegation(ctx, delAddr, valAddr) if !found { @@ -334,6 +340,9 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA k.RemoveValidator(ctx, validator.OperatorAddr) } + // call hook + k.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) + return amount, nil } diff --git a/x/stake/keeper/hooks.go b/x/stake/keeper/hooks.go new file mode 100644 index 0000000000..81bf5594ba --- /dev/null +++ b/x/stake/keeper/hooks.go @@ -0,0 +1,54 @@ +//nolint +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Expose the hooks if present +func (k Keeper) OnValidatorCreated(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorCreated(ctx, address) + } +} +func (k Keeper) OnValidatorCommissionChange(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorCommissionChange(ctx, address) + } +} + +func (k Keeper) OnValidatorRemoved(ctx sdk.Context, address sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnValidatorRemoved(ctx, address) + } +} + +func (k Keeper) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { + if k.hooks != nil { + k.hooks.OnValidatorBonded(ctx, address) + } +} + +func (k Keeper) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { + if k.hooks != nil { + k.hooks.OnValidatorBeginUnbonding(ctx, address) + } +} + +func (k Keeper) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationCreated(ctx, delAddr, valAddr) + } +} + +func (k Keeper) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationSharesModified(ctx, delAddr, valAddr) + } +} + +func (k Keeper) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + if k.hooks != nil { + k.hooks.OnDelegationRemoved(ctx, delAddr, valAddr) + } +} diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index 0f700f9ab8..82170a4aed 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -14,7 +14,7 @@ type Keeper struct { storeTKey sdk.StoreKey cdc *codec.Codec bankKeeper bank.Keeper - hooks sdk.ValidatorHooks + hooks sdk.StakingHooks // codespace codespace sdk.CodespaceType @@ -33,7 +33,7 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespa } // Set the validator hooks -func (k Keeper) WithValidatorHooks(sh sdk.ValidatorHooks) Keeper { +func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { if k.hooks != nil { panic("cannot set validator hooks twice") } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index f7c43757ff..69bab0f8ec 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -633,10 +633,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat // also remove from the Bonded types.Validators Store store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) - // call the unbond hook if present - if k.hooks != nil { - k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) - } + // call hook + k.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) // return updated validator return validator @@ -668,10 +666,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. tstore := ctx.TransientStore(k.storeTKey) tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI) - // call the bond hook if present - if k.hooks != nil { - k.hooks.OnValidatorBonded(ctx, validator.ConsAddress()) - } + // call hook + k.OnValidatorBonded(ctx, validator.ConsAddress()) // return updated validator return validator @@ -680,6 +676,9 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // remove the validator record and associated indexes func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { + // call hook + k.OnValidatorRemoved(ctx, address) + // first retrieve the old validator record validator, found := k.GetValidator(ctx, address) if !found { @@ -739,3 +738,18 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr)) } } + +//__________________________________________________________________________ + +// XXX remove this code - this is should be superceded by commission work that bez is doing +// get a single validator +func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { + + // call hook + k.OnValidatorCommissionChange(ctx, addr) + + validator, _ := k.GetValidator(ctx, addr) + validator.Commission = newCommission + k.SetValidator(ctx, validator) + return nil +} From 1b485bb3c851dafd9f10150d9ad64ad2aa04f9b2 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 22 Sep 2018 16:38:33 -0400 Subject: [PATCH 46/99] pending --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index 5cf80cd6f6..04b7b23f28 100644 --- a/PENDING.md +++ b/PENDING.md @@ -52,6 +52,7 @@ BREAKING CHANGES * [types] \#2343 Make sdk.Msg have a names field, to facilitate automatic tagging. * [baseapp] \#2366 Automatically add action tags to all messages * [x/staking] \#2244 staking now holds a consensus-address-index instead of a consensus-pubkey-index + * [x/staking] \#2236 more distribution hooks for distribution * Tendermint From df0d5825be5bb1d81a0b2e8cadb8069f6a4a3dca Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 22 Sep 2018 16:43:29 -0400 Subject: [PATCH 47/99] add staking hooks to staking spec --- docs/spec/staking/hooks.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 docs/spec/staking/hooks.md diff --git a/docs/spec/staking/hooks.md b/docs/spec/staking/hooks.md new file mode 100644 index 0000000000..bcc496e3d6 --- /dev/null +++ b/docs/spec/staking/hooks.md @@ -0,0 +1,19 @@ +## Receiver Hooks + +The staking module allow for the following hooks to be registered with staking events: + +``` golang +// event hooks for staking validator object +type StakingHooks interface { + OnValidatorCreated(ctx Context, address ValAddress) // called when a validator is created + OnValidatorCommissionChange(ctx Context, address ValAddress) // called when a validator's commission is modified + OnValidatorRemoved(ctx Context, address ValAddress) // called when a validator is deleted + + OnValidatorBonded(ctx Context, address ConsAddress) // called when a validator is bonded + OnValidatorBeginUnbonding(ctx Context, address ConsAddress) // called when a validator begins unbonding + + OnDelegationCreated(ctx Context, delAddr AccAddress, valAddr ValAddress) // called when a delegation is created + OnDelegationSharesModified(ctx Context, delAddr AccAddress, valAddr ValAddress) // called when a delegation's shares are modified + OnDelegationRemoved(ctx Context, delAddr AccAddress, valAddr ValAddress) // called when a delegation is removed +} +``` From 9dfeeb0d7bea7e5d6920db80eb0029240e44d4b4 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 24 Sep 2018 18:54:49 -0400 Subject: [PATCH 48/99] address bez comments --- x/stake/handler.go | 1 - x/stake/keeper/delegation.go | 6 ------ x/stake/keeper/validator.go | 8 -------- 3 files changed, 15 deletions(-) diff --git a/x/stake/handler.go b/x/stake/handler.go index b3bf4c018b..21800ffe2c 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -87,7 +87,6 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k return err.Result() } - // call hooks k.OnValidatorCreated(ctx, validator.OperatorAddr) accAddr := sdk.AccAddress(validator.OperatorAddr) k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index a2392ac587..cc46646a73 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -66,10 +66,7 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { // remove a delegation from store func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { - - // call hook k.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr) - store := ctx.KVStore(k.storeKey) store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) } @@ -286,7 +283,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) { - // call hook k.OnDelegationSharesModified(ctx, delAddr, valAddr) // check if delegation has any shares in it unbond @@ -340,9 +336,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA k.RemoveValidator(ctx, validator.OperatorAddr) } - // call hook k.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) - return amount, nil } diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 69bab0f8ec..6e9427d475 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -633,10 +633,7 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat // also remove from the Bonded types.Validators Store store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) - // call hook k.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) - - // return updated validator return validator } @@ -666,17 +663,13 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. tstore := ctx.TransientStore(k.storeTKey) tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI) - // call hook k.OnValidatorBonded(ctx, validator.ConsAddress()) - - // return updated validator return validator } // remove the validator record and associated indexes func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { - // call hook k.OnValidatorRemoved(ctx, address) // first retrieve the old validator record @@ -745,7 +738,6 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { // get a single validator func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { - // call hook k.OnValidatorCommissionChange(ctx, addr) validator, _ := k.GetValidator(ctx, addr) From afe179ebb38657c3765dc74da9a459a4f1a5b139 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 24 Sep 2018 21:51:18 -0400 Subject: [PATCH 49/99] remove GetValidatorByConsPubKey --- types/address.go | 5 +++++ types/stake.go | 7 +++---- x/slashing/keeper_test.go | 16 ++++++++-------- x/slashing/tick_test.go | 2 +- x/stake/handler.go | 2 +- x/stake/keeper/sdk_types.go | 10 ---------- x/stake/keeper/slash_test.go | 4 ++-- x/stake/keeper/validator.go | 12 ------------ x/stake/keeper/validator_test.go | 2 +- 9 files changed, 21 insertions(+), 39 deletions(-) diff --git a/types/address.go b/types/address.go index 58b694f5da..ae13b2ad0a 100644 --- a/types/address.go +++ b/types/address.go @@ -292,6 +292,11 @@ func ConsAddressFromBech32(address string) (addr ConsAddress, err error) { return ConsAddress(bz), nil } +// get ConsAddress from pubkey +func GetConsAddress(pubkey crypto.PubKey) ConsAddress { + return ConsAddress(pubkey.Address()) +} + // Returns boolean for whether two ConsAddress are Equal func (ca ConsAddress) Equals(ca2 ConsAddress) bool { if ca.Empty() && ca2.Empty() { diff --git a/types/stake.go b/types/stake.go index ade96843dd..e794ea7349 100644 --- a/types/stake.go +++ b/types/stake.go @@ -68,10 +68,9 @@ type ValidatorSet interface { IterateValidatorsBonded(Context, func(index int64, validator Validator) (stop bool)) - Validator(Context, ValAddress) Validator // get a particular validator by operator address - ValidatorByConsPubKey(Context, crypto.PubKey) Validator // get a particular validator by consensus PubKey - ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address - TotalPower(Context) Dec // total power of the validator set + Validator(Context, ValAddress) Validator // get a particular validator by operator address + ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address + TotalPower(Context) Dec // total power of the validator set // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction Slash(Context, ConsAddress, int64, int64, Dec) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 9a3ff537c2..d4b1af3d51 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -167,7 +167,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter) // validator should be bonded still - validator, _ := sk.GetValidatorByConsPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) require.Equal(t, amtInt, pool.BondedTokens.RoundInt64()) @@ -181,7 +181,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter) // validator should have been jailed - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // unrevocation should fail prior to jail expiration @@ -194,7 +194,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.True(t, got.IsOK()) // validator should be rebonded now - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) // validator should have been slashed @@ -212,7 +212,7 @@ func TestHandleAbsentValidator(t *testing.T) { height++ ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) // 500 signed blocks @@ -228,7 +228,7 @@ func TestHandleAbsentValidator(t *testing.T) { ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) } - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } @@ -263,7 +263,7 @@ func TestHandleNewValidator(t *testing.T) { require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil) // validator should be bonded still, should not have been jailed or slashed - validator, _ := sk.GetValidatorByConsPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) require.Equal(t, int64(100), pool.BondedTokens.RoundInt64()) @@ -297,7 +297,7 @@ func TestHandleAlreadyJailed(t *testing.T) { } // validator should have been jailed and slashed - validator, _ := sk.GetValidatorByConsPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // validator should have been slashed @@ -308,7 +308,7 @@ func TestHandleAlreadyJailed(t *testing.T) { keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) // validator should not have been slashed twice - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64()) } diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index fe273be5eb..8225c96347 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -78,7 +78,7 @@ func TestBeginBlocker(t *testing.T) { } // validator should be jailed - validator, found := sk.GetValidatorByConsPubKey(ctx, pk) + validator, found := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)) require.True(t, found) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } diff --git a/x/stake/handler.go b/x/stake/handler.go index f4864a14a6..4d74c8a7bf 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -68,7 +68,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k if found { return ErrValidatorOwnerExists(k.Codespace()).Result() } - _, found = k.GetValidatorByConsPubKey(ctx, msg.PubKey) + _, found = k.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(msg.PubKey)) if found { return ErrValidatorPubKeyExists(k.Codespace()).Result() } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 9872630a4e..d702e845da 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -5,7 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" - "github.com/tendermint/tendermint/crypto" ) // Implements ValidatorSet @@ -67,15 +66,6 @@ func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) sdk.V return val } -// get the sdk.validator for a particular pubkey -func (k Keeper) ValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) sdk.Validator { - val, found := k.GetValidatorByConsPubKey(ctx, consPubKey) - if !found { - return nil - } - return val -} - // total power from the bond func (k Keeper) TotalPower(ctx sdk.Context) sdk.Dec { pool := k.GetPool(ctx) diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index 7d2f2f785c..0a6cccac2a 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -473,7 +473,7 @@ func TestSlashBoth(t *testing.T) { // slash validator ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByConsPubKey(ctx, PKs[0]) + validator, found := keeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0])) require.True(t, found) consAddr0 := sdk.ConsAddress(PKs[0].Address()) keeper.Slash(ctx, consAddr0, 10, 10, fraction) @@ -490,7 +490,7 @@ func TestSlashBoth(t *testing.T) { // bonded tokens burned require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByConsPubKey(ctx, PKs[0]) + validator, found = keeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0])) require.True(t, found) // power not decreased, all stake was bonded since require.Equal(t, sdk.NewDec(10), validator.GetPower()) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index f7c43757ff..00d465cff1 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -6,7 +6,6 @@ import ( "fmt" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" @@ -68,17 +67,6 @@ func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress return k.GetValidator(ctx, opAddr) } -// get a single validator by pubkey -func (k Keeper) GetValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) (validator types.Validator, found bool) { - store := ctx.KVStore(k.storeKey) - consAddr := sdk.ConsAddress(consPubKey.Address()) - opAddr := store.Get(GetValidatorByConsAddrKey(consAddr)) - if opAddr == nil { - return validator, false - } - return k.GetValidator(ctx, opAddr) -} - // set the main record holding validator details func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 356170189a..c21336f9f3 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -314,7 +314,7 @@ func TestValidatorBasics(t *testing.T) { resVal, found = keeper.GetValidatorByConsAddr(ctx, sdk.ConsAddress(PKs[0].Address())) require.True(t, found) assert.True(ValEq(t, validators[0], resVal)) - resVal, found = keeper.GetValidatorByConsPubKey(ctx, PKs[0]) + resVal, found = keeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0])) require.True(t, found) assert.True(ValEq(t, validators[0], resVal)) From dad4253957b943b1f0d742c223ef86f1f6177cae Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 24 Sep 2018 22:27:09 -0400 Subject: [PATCH 50/99] merge fix --- x/stake/types/validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 30cf1f17c0..051ffa9e51 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -458,6 +458,6 @@ func (v Validator) GetConsPubKey() crypto.PubKey { return v.ConsPubKey } func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) } func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } func (v Validator) GetTokens() sdk.Dec { return v.Tokens } -func (v Validator) GetCommission() sdk.Dec { return v.Commission } +func (v Validator) GetCommission() sdk.Dec { return v.Commission.Rate } func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } func (v Validator) GetBondHeight() int64 { return v.BondHeight } From ca2fc77af7c1030ad9fa6889e236ff2298197205 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 24 Sep 2018 22:58:26 -0400 Subject: [PATCH 51/99] update commission hook for new commission work --- x/stake/keeper/validator.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 406093cbdf..b812e6a20a 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -699,6 +699,7 @@ func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, validator types.Valid validator.Commission.UpdateTime = blockTime k.SetValidator(ctx, validator) + k.OnValidatorCommissionChange(ctx, addr) return nil } @@ -736,17 +737,3 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr)) } } - -//__________________________________________________________________________ - -// XXX remove this code - this is should be superceded by commission work that bez is doing -// get a single validator -func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { - - k.OnValidatorCommissionChange(ctx, addr) - - validator, _ := k.GetValidator(ctx, addr) - validator.Commission = newCommission - k.SetValidator(ctx, validator) - return nil -} From 5be5ea3b4cfb70f43e7034012daa80c6ffb6a4a8 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 24 Sep 2018 23:07:55 -0400 Subject: [PATCH 52/99] comment update --- types/decimal.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/decimal.go b/types/decimal.go index 79ada9559d..13a494ba0c 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -335,7 +335,7 @@ func chopPrecisionAndTruncateNonMutative(d *big.Int) *big.Int { return chopPrecisionAndTruncate(tmp) } -// RoundInt64 rounds the decimal using bankers rounding +// TruncateInt64 truncates the decimals from the number and returns an int64 func (d Dec) TruncateInt64() int64 { chopped := chopPrecisionAndTruncateNonMutative(d.Int) if !chopped.IsInt64() { @@ -344,7 +344,7 @@ func (d Dec) TruncateInt64() int64 { return chopped.Int64() } -// RoundInt round the decimal using bankers rounding +// TruncateInt truncates the decimals from the number and returns an Int func (d Dec) TruncateInt() Int { return NewIntFromBigInt(chopPrecisionAndTruncateNonMutative(d.Int)) } From 380d3e1c5ac6536c2ba4099531918ab3d03de150 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 25 Sep 2018 17:43:26 -0400 Subject: [PATCH 53/99] pull a bunch from develop --- examples/democoin/mock/validator.go | 17 +-- types/address.go | 5 + types/address_test.go | 2 +- types/decimal.go | 10 +- types/errors.go | 1 - types/stake.go | 61 +++----- x/gov/client/cli/tx.go | 1 - x/gov/client/rest/rest.go | 3 - x/gov/endblocker_test.go | 95 +++++-------- x/gov/genesis.go | 6 +- x/gov/handler.go | 22 +-- x/gov/keeper.go | 31 ++-- x/gov/keeper_test.go | 9 +- x/gov/procedures.go | 8 +- x/gov/proposals.go | 40 +++--- x/gov/proposals_test.go | 40 ++++++ x/gov/queryable.go | 6 +- x/gov/simulation/msgs.go | 44 +++--- x/gov/simulation/sim_test.go | 7 +- x/gov/tally.go | 17 +-- x/gov/tally_test.go | 47 +++--- x/slashing/app_test.go | 5 +- x/slashing/client/rest/tx.go | 1 - x/slashing/genesis.go | 2 +- x/slashing/handler.go | 2 +- x/slashing/hooks.go | 12 +- x/slashing/keeper.go | 1 - x/slashing/keeper_test.go | 22 +-- x/slashing/simulation/msgs.go | 8 +- x/slashing/test_common.go | 6 +- x/slashing/tick_test.go | 2 +- x/stake/app_test.go | 14 +- x/stake/client/cli/flags.go | 10 ++ x/stake/client/cli/tx.go | 86 +++++------ x/stake/client/cli/utils.go | 88 ++++++++++++ x/stake/client/rest/query.go | 1 - x/stake/client/rest/tx.go | 1 - x/stake/client/rest/utils.go | 3 +- x/stake/genesis.go | 2 +- x/stake/handler.go | 36 +++-- x/stake/handler_test.go | 5 +- x/stake/keeper/delegation.go | 15 -- x/stake/keeper/keeper.go | 4 +- x/stake/keeper/sdk_types.go | 10 -- x/stake/keeper/slash.go | 4 +- x/stake/keeper/slash_test.go | 5 +- x/stake/keeper/validator.go | 74 +++------- x/stake/keeper/validator_test.go | 63 +++++++++ x/stake/simulation/invariants.go | 2 +- x/stake/simulation/msgs.go | 107 ++++++++------ x/stake/simulation/sim_test.go | 5 +- x/stake/stake.go | 18 ++- x/stake/types/commission.go | 128 +++++++++++++++++ x/stake/types/errors.go | 20 ++- x/stake/types/inflation_test.go | 1 - x/stake/types/msg.go | 34 +++-- x/stake/types/msg_test.go | 57 +++++--- x/stake/types/validator.go | 212 +++++++++++++--------------- x/stake/types/validator_test.go | 34 +++++ 59 files changed, 917 insertions(+), 655 deletions(-) create mode 100644 x/gov/proposals_test.go create mode 100644 x/stake/client/cli/utils.go create mode 100644 x/stake/types/commission.go diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index fd5ec85b14..a54cdfedf6 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -24,13 +24,13 @@ func (v Validator) GetOperator() sdk.ValAddress { } // Implements sdk.Validator -func (v Validator) GetPubKey() crypto.PubKey { +func (v Validator) GetConsPubKey() crypto.PubKey { return nil } // Implements sdk.Validator func (v Validator) GetConsAddr() sdk.ConsAddress { - return sdk.ConsAddress{} + return nil } // Implements sdk.Validator @@ -48,11 +48,6 @@ 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 @@ -98,12 +93,12 @@ func (vs *ValidatorSet) Validator(ctx sdk.Context, addr sdk.ValAddress) sdk.Vali } // ValidatorByPubKey implements sdk.ValidatorSet -func (vs *ValidatorSet) ValidatorByConsPubKey(ctx sdk.Context, _ crypto.PubKey) sdk.Validator { +func (vs *ValidatorSet) ValidatorByConsPubKey(_ sdk.Context, _ crypto.PubKey) sdk.Validator { panic("not implemented") } // ValidatorByPubKey implements sdk.ValidatorSet -func (vs *ValidatorSet) ValidatorByConsAddr(ctx sdk.Context, _ sdk.ConsAddress) sdk.Validator { +func (vs *ValidatorSet) ValidatorByConsAddr(_ sdk.Context, _ sdk.ConsAddress) sdk.Validator { panic("not implemented") } @@ -137,7 +132,7 @@ func (vs *ValidatorSet) RemoveValidator(addr sdk.AccAddress) { } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Slash(ctx sdk.Context, _ sdk.ConsAddress, height int64, power int64, amt sdk.Dec) { +func (vs *ValidatorSet) Slash(_ sdk.Context, _ sdk.ConsAddress, _ int64, _ int64, _ sdk.Dec) { panic("not implemented") } @@ -152,6 +147,6 @@ func (vs *ValidatorSet) Unjail(_ sdk.Context, _ sdk.ConsAddress) { } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk.ValAddress) sdk.Delegation { +func (vs *ValidatorSet) Delegation(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) sdk.Delegation { panic("not implemented") } diff --git a/types/address.go b/types/address.go index 58b694f5da..ae13b2ad0a 100644 --- a/types/address.go +++ b/types/address.go @@ -292,6 +292,11 @@ func ConsAddressFromBech32(address string) (addr ConsAddress, err error) { return ConsAddress(bz), nil } +// get ConsAddress from pubkey +func GetConsAddress(pubkey crypto.PubKey) ConsAddress { + return ConsAddress(pubkey.Address()) +} + // Returns boolean for whether two ConsAddress are Equal func (ca ConsAddress) Equals(ca2 ConsAddress) bool { if ca.Empty() && ca2.Empty() { diff --git a/types/address_test.go b/types/address_test.go index e2ec36876c..6c6c78d6ec 100644 --- a/types/address_test.go +++ b/types/address_test.go @@ -10,7 +10,7 @@ import ( "github.com/tendermint/tendermint/crypto/ed25519" "github.com/cosmos/cosmos-sdk/types" -) + ) var invalidStrs = []string{ "", diff --git a/types/decimal.go b/types/decimal.go index d6c93f617a..13a494ba0c 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -174,13 +174,15 @@ func NewDecFromStr(str string) (d Dec, err Error) { //______________________________________________________________________________________________ //nolint -func (d Dec) IsZero() bool { return (d.Int).Sign() == 0 } // Is equal to zero -func (d Dec) Equal(d2 Dec) bool { return (d.Int).Cmp(d2.Int) == 0 } +func (d Dec) IsNil() bool { return d.Int == nil } // is decimal nil +func (d Dec) IsZero() bool { return (d.Int).Sign() == 0 } // is equal to zero +func (d Dec) Equal(d2 Dec) bool { return (d.Int).Cmp(d2.Int) == 0 } // equal decimals func (d Dec) GT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) > 0 } // greater than func (d Dec) GTE(d2 Dec) bool { return (d.Int).Cmp(d2.Int) >= 0 } // greater than or equal func (d Dec) LT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) < 0 } // less than func (d Dec) LTE(d2 Dec) bool { return (d.Int).Cmp(d2.Int) <= 0 } // less than or equal func (d Dec) Neg() Dec { return Dec{new(big.Int).Neg(d.Int)} } // reverse the decimal sign +func (d Dec) Abs() Dec { return Dec{new(big.Int).Abs(d.Int)} } // absolute value // addition func (d Dec) Add(d2 Dec) Dec { @@ -333,7 +335,7 @@ func chopPrecisionAndTruncateNonMutative(d *big.Int) *big.Int { return chopPrecisionAndTruncate(tmp) } -// RoundInt64 rounds the decimal using bankers rounding +// TruncateInt64 truncates the decimals from the number and returns an int64 func (d Dec) TruncateInt64() int64 { chopped := chopPrecisionAndTruncateNonMutative(d.Int) if !chopped.IsInt64() { @@ -342,7 +344,7 @@ func (d Dec) TruncateInt64() int64 { return chopped.Int64() } -// RoundInt round the decimal using bankers rounding +// TruncateInt truncates the decimals from the number and returns an Int func (d Dec) TruncateInt() Int { return NewIntFromBigInt(chopPrecisionAndTruncateNonMutative(d.Int)) } diff --git a/types/errors.go b/types/errors.go index 1d4900d3c2..46bf748f48 100644 --- a/types/errors.go +++ b/types/errors.go @@ -73,7 +73,6 @@ func unknownCodeMsg(code CodeType) string { } // NOTE: Don't stringer this, we'll put better messages in later. -// nolint: gocyclo func CodeToDefaultMsg(code CodeType) string { switch code { case CodeInternal: diff --git a/types/stake.go b/types/stake.go index ded7715486..e794ea7349 100644 --- a/types/stake.go +++ b/types/stake.go @@ -37,24 +37,23 @@ func (b BondStatus) Equal(b2 BondStatus) bool { // validator for a delegated proof of stake system type Validator interface { - GetJailed() bool // whether the validator is jailed - GetMoniker() string // moniker of the validator - GetStatus() BondStatus // status of the validator - GetOperator() ValAddress // operator address to receive/return validators coins - GetPubKey() crypto.PubKey // validation pubkey - GetConsAddr() ConsAddress // validation consensus address - GetPower() Dec // validation power - GetTokens() Dec // validation tokens - GetCommission() Dec // validator commission rate - GetDelegatorShares() Dec // Total delegator shares - GetBondHeight() int64 // height in which the validator became active + GetJailed() bool // whether the validator is jailed + GetMoniker() string // moniker of the validator + GetStatus() BondStatus // status of the validator + GetOperator() ValAddress // operator address to receive/return validators coins + GetConsPubKey() crypto.PubKey // validation consensus pubkey + GetConsAddr() ConsAddress // validation consensus address + GetPower() Dec // validation power + GetTokens() Dec // validation tokens + GetDelegatorShares() Dec // Total out standing delegator shares + GetBondHeight() int64 // height in which the validator became active } // validator which fulfills abci validator interface for use in Tendermint func ABCIValidator(v Validator) abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.GetPubKey()), - Address: v.GetPubKey().Address(), + PubKey: tmtypes.TM2PB.PubKey(v.GetConsPubKey()), + Address: v.GetConsPubKey().Address(), Power: v.GetPower().RoundInt64(), } } @@ -69,10 +68,9 @@ type ValidatorSet interface { IterateValidatorsBonded(Context, func(index int64, validator Validator) (stop bool)) - Validator(Context, ValAddress) Validator // get a particular validator by operator - ValidatorByConsPubKey(Context, crypto.PubKey) Validator // get a particular validator by consensus address - ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address - TotalPower(Context) Dec // total power of the validator set + Validator(Context, ValAddress) Validator // get a particular validator by operator address + ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address + TotalPower(Context) Dec // total power of the validator set // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction Slash(Context, ConsAddress, int64, int64, Dec) @@ -89,8 +87,8 @@ type ValidatorSet interface { // delegation bond for a delegated proof of stake system type Delegation interface { GetDelegator() AccAddress // delegator AccAddress for the bond - GetValidator() ValAddress // validator operator address TODO change to GetValAddr - GetShares() Dec // amount of validator's shares + GetValidator() ValAddress // validator operator address + GetShares() Dec // amount of validator's shares held in this delegation } // properties for the set of all delegations for a particular @@ -103,25 +101,12 @@ type DelegationSet interface { fn func(index int64, delegation Delegation) (stop bool)) } -//_______________________________________________________________________________ -// Event Hooks -// These can be utilized to communicate between a staking keeper and another -// keeper which must take particular actions when validators/delegators change -// state. The second keeper must implement this interface, which then the -// staking keeper can call. - -// TODO refactor event hooks out to the receiver modules - -// event hooks for staking validator object -type StakingHooks interface { - OnValidatorCreated(ctx Context, address ValAddress) // Must be called when a validator is created - OnValidatorCommissionChange(ctx Context, address ValAddress) // Must be called when a validator's commission is modified - OnValidatorRemoved(ctx Context, address ValAddress) // Must be called when a validator is deleted - +// validator event hooks +// These can be utilized to communicate between a staking keeper +// and another keeper which must take particular actions when +// validators are bonded and unbonded. The second keeper must implement +// this interface, which then the staking keeper can call. +type ValidatorHooks interface { OnValidatorBonded(ctx Context, address ConsAddress) // Must be called when a validator is bonded OnValidatorBeginUnbonding(ctx Context, address ConsAddress) // Must be called when a validator begins unbonding - - OnDelegationCreated(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is created - OnDelegationSharesModified(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation's shares are modified - OnDelegationRemoved(ctx Context, delAddr AccAddress, valAddr ValAddress) // Must be called when a delegation is removed } diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 77364665a1..1bd01b58ab 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -285,7 +285,6 @@ func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command { return cmd } -// nolint: gocyclo // GetCmdQueryProposals implements a query proposals command. func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 059c0bb1cf..3f62691c74 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -334,7 +334,6 @@ func queryVoteHandlerFn(cdc *codec.Codec) http.HandlerFunc { } } -// nolint: gocyclo // todo: Split this functionality into helper functions to remove the above func queryVotesOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { @@ -373,7 +372,6 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc { } } -// nolint: gocyclo // todo: Split this functionality into helper functions to remove the above func queryProposalsWithParameterFn(cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { @@ -439,7 +437,6 @@ func queryProposalsWithParameterFn(cdc *codec.Codec) http.HandlerFunc { } } -// nolint: gocyclo // todo: Split this functionality into helper functions to remove the above func queryTallyOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { diff --git a/x/gov/endblocker_test.go b/x/gov/endblocker_test.go index 710ecb1dba..27eff15f64 100644 --- a/x/gov/endblocker_test.go +++ b/x/gov/endblocker_test.go @@ -2,11 +2,11 @@ package gov import ( "testing" + "time" "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/stake" abci "github.com/tendermint/tendermint/abci/types" ) @@ -28,12 +28,18 @@ func TestTickExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(250) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -59,7 +65,10 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -68,14 +77,20 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { res = govHandler(ctx, newProposalMsg2) require.True(t, res.IsOK()) - ctx = ctx.WithBlockHeight(205) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(215) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.True(t, shouldPopInactiveProposalQueue(ctx, keeper)) EndBlocker(ctx, keeper) @@ -105,7 +120,10 @@ func TestTickPassedDepositPeriod(t *testing.T) { require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + EndBlocker(ctx, keeper) require.NotNil(t, keeper.InactiveProposalQueuePeek(ctx)) require.False(t, shouldPopInactiveProposalQueue(ctx, keeper)) @@ -146,14 +164,20 @@ func TestTickPassedVotingPeriod(t *testing.T) { var proposalID int64 keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - ctx = ctx.WithBlockHeight(10) + newHeader := ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) + ctx = ctx.WithBlockHeader(newHeader) + newDepositMsg := NewMsgDeposit(addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin("steak", 5)}) res = govHandler(ctx, newDepositMsg) require.True(t, res.IsOK()) EndBlocker(ctx, keeper) - ctx = ctx.WithBlockHeight(215) + newHeader = ctx.BlockHeader() + newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod) + ctx = ctx.WithBlockHeader(newHeader) + require.True(t, shouldPopActiveProposalQueue(ctx, keeper)) depositsIterator := keeper.GetDeposits(ctx, proposalID) require.True(t, depositsIterator.Valid()) @@ -169,56 +193,3 @@ func TestTickPassedVotingPeriod(t *testing.T) { require.Equal(t, StatusRejected, keeper.GetProposal(ctx, proposalID).GetStatus()) require.True(t, keeper.GetProposal(ctx, proposalID).GetTallyResult().Equals(EmptyTallyResult())) } - -func TestSlashing(t *testing.T) { - mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10) - SortAddresses(addrs) - mapp.BeginBlock(abci.RequestBeginBlock{}) - ctx := mapp.BaseApp.NewContext(false, abci.Header{}) - govHandler := NewHandler(keeper) - stakeHandler := stake.NewHandler(sk) - - valAddrs := make([]sdk.ValAddress, len(addrs[:3])) - for i, addr := range addrs[:3] { - valAddrs[i] = sdk.ValAddress(addr) - } - - createValidators(t, stakeHandler, ctx, valAddrs, []int64{25, 6, 7}) - - initTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx) - val0Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[0])).GetPower().Quo(initTotalPower) - val1Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[1])).GetPower().Quo(initTotalPower) - val2Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[2])).GetPower().Quo(initTotalPower) - - newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 15)}) - - res := govHandler(ctx, newProposalMsg) - require.True(t, res.IsOK()) - var proposalID int64 - keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID) - - ctx = ctx.WithBlockHeight(10) - require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) - - newVoteMsg := NewMsgVote(addrs[0], proposalID, OptionYes) - res = govHandler(ctx, newVoteMsg) - require.True(t, res.IsOK()) - - EndBlocker(ctx, keeper) - - ctx = ctx.WithBlockHeight(215) - require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus()) - - EndBlocker(ctx, keeper) - - require.False(t, keeper.GetProposal(ctx, proposalID).GetTallyResult().Equals(EmptyTallyResult())) - - endTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx) - val0End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[0])).GetPower().Quo(endTotalPower) - val1End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[1])).GetPower().Quo(endTotalPower) - val2End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[2])).GetPower().Quo(endTotalPower) - - require.True(t, val0End.GTE(val0Initial)) - require.True(t, val1End.LT(val1Initial)) - require.True(t, val2End.LT(val2Initial)) -} diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 15f952c000..58273c8e84 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -1,6 +1,8 @@ package gov import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -27,10 +29,10 @@ func DefaultGenesisState() GenesisState { StartingProposalID: 1, DepositProcedure: DepositProcedure{ MinDeposit: sdk.Coins{sdk.NewInt64Coin("steak", 10)}, - MaxDepositPeriod: 200, + MaxDepositPeriod: time.Duration(172800) * time.Second, }, VotingProcedure: VotingProcedure{ - VotingPeriod: 200, + VotingPeriod: time.Duration(172800) * time.Second, }, TallyingProcedure: TallyingProcedure{ Threshold: sdk.NewDecWithPrec(5, 1), diff --git a/x/gov/handler.go b/x/gov/handler.go index 84964b20f6..3f8cd312b6 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -128,13 +128,13 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { for shouldPopActiveProposalQueue(ctx, keeper) { activeProposal := keeper.ActiveProposalQueuePop(ctx) - proposalStartBlock := activeProposal.GetVotingStartBlock() + proposalStartTime := activeProposal.GetVotingStartTime() votingPeriod := keeper.GetVotingProcedure(ctx).VotingPeriod - if ctx.BlockHeight() < proposalStartBlock+votingPeriod { + if ctx.BlockHeader().Time.Before(proposalStartTime.Add(votingPeriod)) { continue } - passes, tallyResults, nonVotingVals := tally(ctx, keeper, activeProposal) + passes, tallyResults := tally(ctx, keeper, activeProposal) proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(activeProposal.GetProposalID()) var action []byte if passes { @@ -152,18 +152,6 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { logger.Info(fmt.Sprintf("proposal %d (%s) tallied; passed: %v", activeProposal.GetProposalID(), activeProposal.GetTitle(), passes)) - for _, valAddr := range nonVotingVals { - val := keeper.ds.GetValidatorSet().Validator(ctx, valAddr) - keeper.ds.GetValidatorSet().Slash(ctx, - val.GetConsAddr(), - ctx.BlockHeight(), - val.GetPower().RoundInt64(), - keeper.GetTallyingProcedure(ctx).GovernancePenalty) - - logger.Info(fmt.Sprintf("validator %s failed to vote on proposal %d; slashing", - val.GetOperator(), activeProposal.GetProposalID())) - } - resTags.AppendTag(tags.Action, action) resTags.AppendTag(tags.ProposalID, proposalIDBytes) } @@ -178,7 +166,7 @@ func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { return false } else if peekProposal.GetStatus() != StatusDepositPeriod { return true - } else if ctx.BlockHeight() >= peekProposal.GetSubmitBlock()+depositProcedure.MaxDepositPeriod { + } else if !ctx.BlockHeader().Time.Before(peekProposal.GetSubmitTime().Add(depositProcedure.MaxDepositPeriod)) { return true } return false @@ -190,7 +178,7 @@ func shouldPopActiveProposalQueue(ctx sdk.Context, keeper Keeper) bool { if peekProposal == nil { return false - } else if ctx.BlockHeight() >= peekProposal.GetVotingStartBlock()+votingProcedure.VotingPeriod { + } else if !ctx.BlockHeader().Time.Before(peekProposal.GetVotingStartTime().Add(votingProcedure.VotingPeriod)) { return true } return false diff --git a/x/gov/keeper.go b/x/gov/keeper.go index bebcf51e78..80e5a205cd 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -38,7 +38,11 @@ type Keeper struct { codespace sdk.CodespaceType } -// NewGovernanceMapper returns a mapper that uses go-codec to (binary) encode and decode gov types. +// NewKeeper returns a governance keeper. It handles: +// - submitting governance proposals +// - depositing funds into proposals, and activating upon sufficient funds being deposited +// - users voting on proposals, with weight proportional to stake in the system +// - and tallying the result of the vote. func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ps params.Setter, ck bank.Keeper, ds sdk.DelegationSet, codespace sdk.CodespaceType) Keeper { return Keeper{ storeKey: key, @@ -51,11 +55,6 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ps params.Setter, ck bank.Kee } } -// Returns the go-codec codec. -func (keeper Keeper) WireCodec() *codec.Codec { - return keeper.cdc -} - // ===================================================== // Proposals @@ -66,15 +65,14 @@ func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description return nil } var proposal Proposal = &TextProposal{ - ProposalID: proposalID, - Title: title, - Description: description, - ProposalType: proposalType, - Status: StatusDepositPeriod, - TallyResult: EmptyTallyResult(), - TotalDeposit: sdk.Coins{}, - SubmitBlock: ctx.BlockHeight(), - VotingStartBlock: -1, // TODO: Make Time + ProposalID: proposalID, + Title: title, + Description: description, + ProposalType: proposalType, + Status: StatusDepositPeriod, + TallyResult: EmptyTallyResult(), + TotalDeposit: sdk.Coins{}, + SubmitTime: ctx.BlockHeader().Time, } keeper.SetProposal(ctx, proposal) keeper.InactiveProposalQueuePush(ctx, proposal) @@ -108,7 +106,6 @@ func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposal Proposal) { store.Delete(KeyProposal(proposal.GetProposalID())) } -// nolint: gocyclo // Get Proposal from store by ProposalID func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositerAddr sdk.AccAddress, status ProposalStatus, numLatest int64) []Proposal { @@ -200,7 +197,7 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e } func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) { - proposal.SetVotingStartBlock(ctx.BlockHeight()) + proposal.SetVotingStartTime(ctx.BlockHeader().Time) proposal.SetStatus(StatusVotingPeriod) keeper.SetProposal(ctx, proposal) keeper.ActiveProposalQueuePush(ctx, proposal) diff --git a/x/gov/keeper_test.go b/x/gov/keeper_test.go index a61292b93e..91c41d7d7d 100644 --- a/x/gov/keeper_test.go +++ b/x/gov/keeper_test.go @@ -2,6 +2,7 @@ package gov import ( "testing" + "time" "github.com/stretchr/testify/require" @@ -45,12 +46,12 @@ func TestActivateVotingPeriod(t *testing.T) { proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText) - require.Equal(t, int64(-1), proposal.GetVotingStartBlock()) + require.True(t, proposal.GetVotingStartTime().Equal(time.Time{})) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) keeper.activateVotingPeriod(ctx, proposal) - require.Equal(t, proposal.GetVotingStartBlock(), ctx.BlockHeight()) + require.True(t, proposal.GetVotingStartTime().Equal(ctx.BlockHeader().Time)) require.Equal(t, proposal.GetProposalID(), keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) } @@ -77,7 +78,7 @@ func TestDeposits(t *testing.T) { // Check no deposits at beginning deposit, found := keeper.GetDeposit(ctx, proposalID, addrs[1]) require.False(t, found) - require.Equal(t, keeper.GetProposal(ctx, proposalID).GetVotingStartBlock(), int64(-1)) + require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(time.Time{})) require.Nil(t, keeper.ActiveProposalQueuePeek(ctx)) // Check first deposit @@ -114,7 +115,7 @@ func TestDeposits(t *testing.T) { require.Equal(t, addr1Initial.Minus(fourSteak), keeper.ck.GetCoins(ctx, addrs[1])) // Check that proposal moved to voting period - require.Equal(t, ctx.BlockHeight(), keeper.GetProposal(ctx, proposalID).GetVotingStartBlock()) + require.True(t, keeper.GetProposal(ctx, proposalID).GetVotingStartTime().Equal(ctx.BlockHeader().Time)) require.NotNil(t, keeper.ActiveProposalQueuePeek(ctx)) require.Equal(t, proposalID, keeper.ActiveProposalQueuePeek(ctx).GetProposalID()) diff --git a/x/gov/procedures.go b/x/gov/procedures.go index f74091c74f..e453add791 100644 --- a/x/gov/procedures.go +++ b/x/gov/procedures.go @@ -1,13 +1,15 @@ package gov import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" ) // Procedure around Deposits for governance type DepositProcedure struct { - MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. - MaxDepositPeriod int64 `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months + MinDeposit sdk.Coins `json:"min_deposit"` // Minimum deposit for a proposal to enter voting period. + MaxDepositPeriod time.Duration `json:"max_deposit_period"` // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months } // Procedure around Tallying votes in governance @@ -19,5 +21,5 @@ type TallyingProcedure struct { // Procedure around Voting in governance type VotingProcedure struct { - VotingPeriod int64 `json:"voting_period"` // Length of the voting period. + VotingPeriod time.Duration `json:"voting_period"` // Length of the voting period. } diff --git a/x/gov/proposals.go b/x/gov/proposals.go index b4c6783673..37e29df704 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -3,6 +3,7 @@ package gov import ( "encoding/json" "fmt" + "time" "github.com/pkg/errors" @@ -30,14 +31,14 @@ type Proposal interface { GetTallyResult() TallyResult SetTallyResult(TallyResult) - GetSubmitBlock() int64 - SetSubmitBlock(int64) + GetSubmitTime() time.Time + SetSubmitTime(time.Time) GetTotalDeposit() sdk.Coins SetTotalDeposit(sdk.Coins) - GetVotingStartBlock() int64 - SetVotingStartBlock(int64) + GetVotingStartTime() time.Time + SetVotingStartTime(time.Time) } // checks if two proposals are equal @@ -48,9 +49,9 @@ func ProposalEqual(proposalA Proposal, proposalB Proposal) bool { proposalA.GetProposalType() == proposalB.GetProposalType() && proposalA.GetStatus() == proposalB.GetStatus() && proposalA.GetTallyResult().Equals(proposalB.GetTallyResult()) && - proposalA.GetSubmitBlock() == proposalB.GetSubmitBlock() && + proposalA.GetSubmitTime().Equal(proposalB.GetSubmitTime()) && proposalA.GetTotalDeposit().IsEqual(proposalB.GetTotalDeposit()) && - proposalA.GetVotingStartBlock() == proposalB.GetVotingStartBlock() { + proposalA.GetVotingStartTime().Equal(proposalB.GetVotingStartTime()) { return true } return false @@ -67,10 +68,10 @@ type TextProposal struct { Status ProposalStatus `json:"proposal_status"` // Status of the Proposal {Pending, Active, Passed, Rejected} TallyResult TallyResult `json:"tally_result"` // Result of Tallys - SubmitBlock int64 `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included + SubmitTime time.Time `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit - VotingStartBlock int64 `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached + VotingStartTime time.Time `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached } // Implements Proposal Interface @@ -89,13 +90,13 @@ func (tp TextProposal) GetStatus() ProposalStatus { return tp.S func (tp *TextProposal) SetStatus(status ProposalStatus) { tp.Status = status } func (tp TextProposal) GetTallyResult() TallyResult { return tp.TallyResult } func (tp *TextProposal) SetTallyResult(tallyResult TallyResult) { tp.TallyResult = tallyResult } -func (tp TextProposal) GetSubmitBlock() int64 { return tp.SubmitBlock } -func (tp *TextProposal) SetSubmitBlock(submitBlock int64) { tp.SubmitBlock = submitBlock } +func (tp TextProposal) GetSubmitTime() time.Time { return tp.SubmitTime } +func (tp *TextProposal) SetSubmitTime(submitTime time.Time) { tp.SubmitTime = submitTime } func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit } func (tp *TextProposal) SetTotalDeposit(totalDeposit sdk.Coins) { tp.TotalDeposit = totalDeposit } -func (tp TextProposal) GetVotingStartBlock() int64 { return tp.VotingStartBlock } -func (tp *TextProposal) SetVotingStartBlock(votingStartBlock int64) { - tp.VotingStartBlock = votingStartBlock +func (tp TextProposal) GetVotingStartTime() time.Time { return tp.VotingStartTime } +func (tp *TextProposal) SetVotingStartTime(votingStartTime time.Time) { + tp.VotingStartTime = votingStartTime } //----------------------------------------------------------- @@ -191,8 +192,9 @@ func (pt ProposalKind) String() string { func (pt ProposalKind) Format(s fmt.State, verb rune) { switch verb { case 's': - s.Write([]byte(fmt.Sprintf("%s", pt.String()))) + s.Write([]byte(pt.String())) default: + // TODO: Do this conversion more directly s.Write([]byte(fmt.Sprintf("%v", byte(pt)))) } } @@ -294,8 +296,9 @@ func (status ProposalStatus) String() string { func (status ProposalStatus) Format(s fmt.State, verb rune) { switch verb { case 's': - s.Write([]byte(fmt.Sprintf("%s", status.String()))) + s.Write([]byte(status.String())) default: + // TODO: Do this conversion more directly s.Write([]byte(fmt.Sprintf("%v", byte(status)))) } } @@ -321,11 +324,8 @@ func EmptyTallyResult() TallyResult { // checks if two proposals are equal func (resultA TallyResult) Equals(resultB TallyResult) bool { - if resultA.Yes.Equal(resultB.Yes) && + return (resultA.Yes.Equal(resultB.Yes) && resultA.Abstain.Equal(resultB.Abstain) && resultA.No.Equal(resultB.No) && - resultA.NoWithVeto.Equal(resultB.NoWithVeto) { - return true - } - return false + resultA.NoWithVeto.Equal(resultB.NoWithVeto)) } diff --git a/x/gov/proposals_test.go b/x/gov/proposals_test.go new file mode 100644 index 0000000000..1d5f2cf389 --- /dev/null +++ b/x/gov/proposals_test.go @@ -0,0 +1,40 @@ +package gov + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestProposalKind_Format(t *testing.T) { + typeText, _ := ProposalTypeFromString("Text") + tests := []struct { + pt ProposalKind + sprintFArgs string + expectedStringOutput string + }{ + {typeText, "%s", "Text"}, + {typeText, "%v", "1"}, + } + for _, tt := range tests { + got := fmt.Sprintf(tt.sprintFArgs, tt.pt) + require.Equal(t, tt.expectedStringOutput, got) + } +} + +func TestProposalStatus_Format(t *testing.T) { + statusDepositPeriod, _ := ProposalStatusFromString("DepositPeriod") + tests := []struct { + pt ProposalStatus + sprintFArgs string + expectedStringOutput string + }{ + {statusDepositPeriod, "%s", "DepositPeriod"}, + {statusDepositPeriod, "%v", "1"}, + } + for _, tt := range tests { + got := fmt.Sprintf(tt.sprintFArgs, tt.pt) + require.Equal(t, tt.expectedStringOutput, got) + } +} diff --git a/x/gov/queryable.go b/x/gov/queryable.go index f20bb46f78..606f73a9ca 100644 --- a/x/gov/queryable.go +++ b/x/gov/queryable.go @@ -205,12 +205,12 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke var proposalID int64 err2 := keeper.cdc.UnmarshalJSON(req.Data, proposalID) if err2 != nil { - return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) + return res, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) } proposal := keeper.GetProposal(ctx, proposalID) if proposal == nil { - return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) + return res, ErrUnknownProposal(DefaultCodespace, proposalID) } var tallyResult TallyResult @@ -220,7 +220,7 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke } else if proposal.GetStatus() == StatusPassed || proposal.GetStatus() == StatusRejected { tallyResult = proposal.GetTallyResult() } else { - _, tallyResult, _ = tally(ctx, keeper, proposal) + _, tallyResult = tally(ctx, keeper, proposal) } bz, err2 := codec.MarshalJSONIndent(keeper.cdc, tallyResult) diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 168081b188..d5ff1881e4 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -4,8 +4,7 @@ import ( "fmt" "math" "math/rand" - - "github.com/tendermint/tendermint/crypto" + "time" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -44,9 +43,9 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe }) statePercentageArray := []float64{1, .9, .75, .4, .15, 0} curNumVotesState := 1 - return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { // 1) submit proposal now - sender := simulation.RandomKey(r, keys) + sender := simulation.RandomAcc(r, accs) msg, err := simulationCreateMsgSubmitProposal(r, sender) if err != nil { return "", nil, err @@ -60,16 +59,16 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe // 2) Schedule operations for votes // 2.1) first pick a number of people to vote. curNumVotesState = numVotesTransitionMatrix.NextState(r, curNumVotesState) - numVotes := int(math.Ceil(float64(len(keys)) * statePercentageArray[curNumVotesState])) + numVotes := int(math.Ceil(float64(len(accs)) * statePercentageArray[curNumVotesState])) // 2.2) select who votes and when - whoVotes := r.Perm(len(keys)) + whoVotes := r.Perm(len(accs)) // didntVote := whoVotes[numVotes:] whoVotes = whoVotes[:numVotes] votingPeriod := k.GetVotingProcedure(ctx).VotingPeriod fops := make([]simulation.FutureOperation, numVotes+1) for i := 0; i < numVotes; i++ { - whenVote := ctx.BlockHeight() + r.Int63n(votingPeriod) - fops[i] = simulation.FutureOperation{BlockHeight: int(whenVote), Op: operationSimulateMsgVote(k, sk, keys[whoVotes[i]], proposalID)} + whenVote := ctx.BlockHeader().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second) + fops[i] = simulation.FutureOperation{BlockTime: whenVote, Op: operationSimulateMsgVote(k, sk, accs[whoVotes[i]], proposalID)} } // 3) Make an operation to ensure slashes were done correctly. (Really should be a future invariant) // TODO: Find a way to check if a validator was slashed other than just checking their balance a block @@ -83,8 +82,8 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe // Note: Currently doesn't ensure that the proposal txt is in JSON form func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation { handler := gov.NewHandler(k) - return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { - sender := simulation.RandomKey(r, keys) + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOps []simulation.FutureOperation, err error) { + sender := simulation.RandomAcc(r, accs) msg, err := simulationCreateMsgSubmitProposal(r, sender) if err != nil { return "", nil, err @@ -110,14 +109,13 @@ func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, sk stake.Keeper, return } -func simulationCreateMsgSubmitProposal(r *rand.Rand, sender crypto.PrivKey) (msg gov.MsgSubmitProposal, err error) { - addr := sdk.AccAddress(sender.PubKey().Address()) +func simulationCreateMsgSubmitProposal(r *rand.Rand, sender simulation.Account) (msg gov.MsgSubmitProposal, err error) { deposit := randomDeposit(r) msg = gov.NewMsgSubmitProposal( simulation.RandStringOfLength(r, 5), simulation.RandStringOfLength(r, 5), gov.ProposalTypeText, - addr, + sender.Address, deposit, ) if msg.ValidateBasic() != nil { @@ -128,15 +126,14 @@ func simulationCreateMsgSubmitProposal(r *rand.Rand, sender crypto.PrivKey) (msg // SimulateMsgDeposit func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { - key := simulation.RandomKey(r, keys) - addr := sdk.AccAddress(key.PubKey().Address()) + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { + acc := simulation.RandomAcc(r, accs) proposalID, ok := randomProposalID(r, k, ctx) if !ok { return "no-operation", nil, nil } deposit := randomDeposit(r) - msg := gov.NewMsgDeposit(addr, proposalID, deposit) + msg := gov.NewMsgDeposit(acc.Address, proposalID, deposit) if msg.ValidateBasic() != nil { return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } @@ -158,14 +155,14 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { // SimulateMsgVote // nolint: unparam func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { - return operationSimulateMsgVote(k, sk, nil, -1) + return operationSimulateMsgVote(k, sk, simulation.Account{}, -1) } // nolint: unparam -func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation { - return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { - if key == nil { - key = simulation.RandomKey(r, keys) +func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, acc simulation.Account, proposalID int64) simulation.Operation { + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { + if acc.Equals(simulation.Account{}) { + acc = simulation.RandomAcc(r, accs) } var ok bool @@ -176,10 +173,9 @@ func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, return "no-operation", nil, nil } } - addr := sdk.AccAddress(key.PubKey().Address()) option := randomVotingOption(r) - msg := gov.NewMsgVote(addr, proposalID, option) + msg := gov.NewMsgVote(acc.Address, proposalID, option) if msg.ValidateBasic() != nil { return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index 35a11fb078..b0317d1161 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -6,7 +6,6 @@ import ( "testing" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/bank" @@ -43,12 +42,12 @@ func TestGovWithRandomMessages(t *testing.T) { panic(err) } - appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { - mock.RandomSetGenesis(r, mapp, accs, []string{"stake"}) + appStateFn := func(r *rand.Rand, accs []simulation.Account) json.RawMessage { + simulation.RandomSetGenesis(r, mapp, accs, []string{"stake"}) return json.RawMessage("{}") } - setup := func(r *rand.Rand, privKeys []crypto.PrivKey) { + setup := func(r *rand.Rand, accs []simulation.Account) { ctx := mapp.NewContext(false, abci.Header{}) stake.InitGenesis(ctx, stakeKeeper, stake.DefaultGenesisState()) gov.InitGenesis(ctx, govKeeper, gov.DefaultGenesisState()) diff --git a/x/gov/tally.go b/x/gov/tally.go index 55fd81da24..c5751258a0 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -13,7 +13,7 @@ type validatorGovInfo struct { Vote VoteOption // Vote of the validator } -func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.ValAddress) { +func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult) { results := make(map[VoteOption]sdk.Dec) results[OptionYes] = sdk.ZeroDec() results[OptionAbstain] = sdk.ZeroDec() @@ -70,12 +70,9 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall keeper.deleteVote(ctx, vote.ProposalID, vote.Voter) } - // iterate over the validators again to tally their voting power and see - // who didn't vote - nonVoting = []sdk.ValAddress{} + // iterate over the validators again to tally their voting power for _, val := range currValidators { if val.Vote == OptionEmpty { - nonVoting = append(nonVoting, val.Address) continue } @@ -98,19 +95,17 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall // If no one votes, proposal fails if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroDec()) { - return false, tallyResults, nonVoting + return false, tallyResults } // If more than 1/3 of voters veto, proposal fails if results[OptionNoWithVeto].Quo(totalVotingPower).GT(tallyingProcedure.Veto) { - return false, tallyResults, nonVoting + return false, tallyResults } // If more than 1/2 of non-abstaining voters vote Yes, proposal passes if results[OptionYes].Quo(totalVotingPower.Sub(results[OptionAbstain])).GT(tallyingProcedure.Threshold) { - return true, tallyResults, nonVoting + return true, tallyResults } // If more than 1/2 of non-abstaining voters vote No, proposal fails - SortValAddresses(nonVoting) - - return false, tallyResults, nonVoting + return false, tallyResults } diff --git a/x/gov/tally_test.go b/x/gov/tally_test.go index 9c5348b2c7..28fe0cb599 100644 --- a/x/gov/tally_test.go +++ b/x/gov/tally_test.go @@ -15,13 +15,19 @@ import ( var ( pubkeys = []crypto.PubKey{ed25519.GenPrivKey().PubKey(), ed25519.GenPrivKey().PubKey(), ed25519.GenPrivKey().PubKey()} + + testDescription = stake.NewDescription("T", "E", "S", "T") + testCommissionMsg = stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) ) func createValidators(t *testing.T, stakeHandler sdk.Handler, ctx sdk.Context, addrs []sdk.ValAddress, coinAmt []int64) { require.True(t, len(addrs) <= len(pubkeys), "Not enough pubkeys specified at top of file.") - dummyDescription := stake.NewDescription("T", "E", "S", "T") + for i := 0; i < len(addrs); i++ { - valCreateMsg := stake.NewMsgCreateValidator(addrs[i], pubkeys[i], sdk.NewInt64Coin("steak", coinAmt[i]), dummyDescription) + valCreateMsg := stake.NewMsgCreateValidator( + addrs[i], pubkeys[i], sdk.NewInt64Coin("steak", coinAmt[i]), testDescription, testCommissionMsg, + ) + res := stakeHandler(ctx, valCreateMsg) require.True(t, res.IsOK()) } @@ -45,7 +51,7 @@ func TestTallyNoOneVotes(t *testing.T) { proposal.SetStatus(StatusVotingPeriod) keeper.SetProposal(ctx, proposal) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.False(t, passes) require.True(t, tallyResults.Equals(EmptyTallyResult())) @@ -74,7 +80,7 @@ func TestTallyOnlyValidatorsAllYes(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.True(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) @@ -103,7 +109,7 @@ func TestTallyOnlyValidators51No(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[1], OptionNo) require.Nil(t, err) - passes, _, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.False(t, passes) } @@ -133,7 +139,7 @@ func TestTallyOnlyValidators51Yes(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.True(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) @@ -164,7 +170,7 @@ func TestTallyOnlyValidatorsVetoed(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNoWithVeto) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.False(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) @@ -195,7 +201,7 @@ func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[2], OptionYes) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.True(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) @@ -226,7 +232,7 @@ func TestTallyOnlyValidatorsAbstainFails(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.False(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) @@ -255,11 +261,9 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo) require.Nil(t, err) - passes, tallyResults, nonVoting := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.False(t, passes) - require.Equal(t, 1, len(nonVoting)) - require.Equal(t, sdk.ValAddress(addrs[0]), nonVoting[0]) require.False(t, tallyResults.Equals(EmptyTallyResult())) } @@ -293,7 +297,7 @@ func TestTallyDelgatorOverride(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[3], OptionNo) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.False(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) @@ -327,10 +331,9 @@ func TestTallyDelgatorInherit(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[2], OptionYes) require.Nil(t, err) - passes, tallyResults, nonVoting := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.True(t, passes) - require.Equal(t, 0, len(nonVoting)) require.False(t, tallyResults.Equals(EmptyTallyResult())) } @@ -366,7 +369,7 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[3], OptionNo) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.False(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) @@ -378,20 +381,18 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) { ctx := mapp.BaseApp.NewContext(false, abci.Header{}) stakeHandler := stake.NewHandler(sk) - dummyDescription := stake.NewDescription("T", "E", "S", "T") - val1CreateMsg := stake.NewMsgCreateValidator( - sdk.ValAddress(addrs[0]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 25), dummyDescription, + sdk.ValAddress(addrs[0]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 25), testDescription, testCommissionMsg, ) stakeHandler(ctx, val1CreateMsg) val2CreateMsg := stake.NewMsgCreateValidator( - sdk.ValAddress(addrs[1]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 6), dummyDescription, + sdk.ValAddress(addrs[1]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 6), testDescription, testCommissionMsg, ) stakeHandler(ctx, val2CreateMsg) val3CreateMsg := stake.NewMsgCreateValidator( - sdk.ValAddress(addrs[2]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 7), dummyDescription, + sdk.ValAddress(addrs[2]), ed25519.GenPrivKey().PubKey(), sdk.NewInt64Coin("steak", 7), testDescription, testCommissionMsg, ) stakeHandler(ctx, val3CreateMsg) @@ -413,7 +414,7 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.False(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) @@ -454,7 +455,7 @@ func TestTallyJailedValidator(t *testing.T) { err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo) require.Nil(t, err) - passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) + passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID)) require.True(t, passes) require.False(t, tallyResults.Equals(EmptyTallyResult())) diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 497440a085..a3370b1d87 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -99,9 +99,12 @@ func TestSlashingMsgs(t *testing.T) { } accs := []auth.Account{acc1} mock.SetGenesis(mapp, accs) + description := stake.NewDescription("foo_moniker", "", "", "") + commission := stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) + createValidatorMsg := stake.NewMsgCreateValidator( - sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, + sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, commission, ) mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{createValidatorMsg}, []int64{0}, []int64{0}, true, true, priv1) mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin.Minus(bondCoin)}) diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index 45b1b6471a..94537c2eb3 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -38,7 +38,6 @@ type UnjailBody struct { ValidatorAddr string `json:"validator_addr"` } -// nolint: gocyclo func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var m UnjailBody diff --git a/x/slashing/genesis.go b/x/slashing/genesis.go index 6e2809bfcb..43ae6b0d0a 100644 --- a/x/slashing/genesis.go +++ b/x/slashing/genesis.go @@ -8,7 +8,7 @@ import ( // InitGenesis initializes the keeper's address to pubkey map. func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { for _, validator := range data.Validators { - keeper.addPubkey(ctx, validator.GetPubKey()) + keeper.addPubkey(ctx, validator.GetConsPubKey()) } return } diff --git a/x/slashing/handler.go b/x/slashing/handler.go index 4f342f62a0..740166d2af 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -34,7 +34,7 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { return ErrValidatorNotJailed(k.codespace).Result() } - consAddr := sdk.ConsAddress(validator.GetPubKey().Address()) + consAddr := sdk.ConsAddress(validator.GetConsPubKey().Address()) info, found := k.getValidatorSigningInfo(ctx, consAddr) if !found { diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index 701a6b2cde..92c4cf85f8 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -29,10 +29,10 @@ type Hooks struct { k Keeper } -var _ sdk.StakingHooks = Hooks{} +var _ sdk.ValidatorHooks = Hooks{} // Return the wrapper struct -func (k Keeper) Hooks() Hooks { +func (k Keeper) ValidatorHooks() Hooks { return Hooks{k} } @@ -45,11 +45,3 @@ func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { h.k.onValidatorBeginUnbonding(ctx, address) } - -// nolint - unused hooks -func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {} -func (h Hooks) OnValidatorCommissionChange(_ sdk.Context, _ sdk.ValAddress) {} -func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {} -func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} -func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} -func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {} diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index e639182e18..6a5fa30148 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -79,7 +79,6 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio // handle a validator signature, must be called once per validator per block // TODO refactor to take in a consensus address, additionally should maybe just take in the pubkey too -// nolint gocyclo func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) { logger := ctx.Logger().With("module", "x/slashing") height := ctx.BlockHeight() diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 1d69f714f0..d4b1af3d51 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -27,7 +27,7 @@ func TestHandleDoubleSign(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithHooks(keeper.Hooks()) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) @@ -69,7 +69,7 @@ func TestSlashingPeriodCap(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithHooks(keeper.Hooks()) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, amt := addrs[0], sdk.NewInt(amtInt) valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address()) @@ -125,7 +125,7 @@ func TestHandleAbsentValidator(t *testing.T) { // initial setup ctx, ck, sk, _, keeper := createTestInput(t) - sk = sk.WithHooks(keeper.Hooks()) + sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) sh := stake.NewHandler(sk) @@ -167,7 +167,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter) // validator should be bonded still - validator, _ := sk.GetValidatorByConsPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) require.Equal(t, amtInt, pool.BondedTokens.RoundInt64()) @@ -181,7 +181,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter) // validator should have been jailed - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // unrevocation should fail prior to jail expiration @@ -194,7 +194,7 @@ func TestHandleAbsentValidator(t *testing.T) { require.True(t, got.IsOK()) // validator should be rebonded now - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) // validator should have been slashed @@ -212,7 +212,7 @@ func TestHandleAbsentValidator(t *testing.T) { height++ ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) // 500 signed blocks @@ -228,7 +228,7 @@ func TestHandleAbsentValidator(t *testing.T) { ctx = ctx.WithBlockHeight(height) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) } - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } @@ -263,7 +263,7 @@ func TestHandleNewValidator(t *testing.T) { require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil) // validator should be bonded still, should not have been jailed or slashed - validator, _ := sk.GetValidatorByConsPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) pool := sk.GetPool(ctx) require.Equal(t, int64(100), pool.BondedTokens.RoundInt64()) @@ -297,7 +297,7 @@ func TestHandleAlreadyJailed(t *testing.T) { } // validator should have been jailed and slashed - validator, _ := sk.GetValidatorByConsPubKey(ctx, val) + validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // validator should have been slashed @@ -308,7 +308,7 @@ func TestHandleAlreadyJailed(t *testing.T) { keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) // validator should not have been slashed twice - validator, _ = sk.GetValidatorByConsPubKey(ctx, val) + validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64()) } diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go index da9340baf4..2b09226f23 100644 --- a/x/slashing/simulation/msgs.go +++ b/x/slashing/simulation/msgs.go @@ -4,8 +4,6 @@ import ( "fmt" "math/rand" - "github.com/tendermint/tendermint/crypto" - "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mock/simulation" @@ -14,9 +12,9 @@ import ( // SimulateMsgUnjail func SimulateMsgUnjail(k slashing.Keeper) simulation.Operation { - return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { - key := simulation.RandomKey(r, keys) - address := sdk.ValAddress(key.PubKey().Address()) + return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) { + acc := simulation.RandomAcc(r, accs) + address := sdk.ValAddress(acc.Address) msg := slashing.NewMsgUnjail(address) if msg.ValidateBasic() != nil { return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index db2293a2f9..7c97a85372 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -103,12 +103,14 @@ func testAddr(addr string) sdk.AccAddress { } 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{}, + Commission: commission, DelegatorAddr: sdk.AccAddress(address), ValidatorAddr: address, PubKey: pubKey, - Delegation: sdk.Coin{"steak", amt}, + Delegation: sdk.NewCoin("steak", amt), } } @@ -116,6 +118,6 @@ func newTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, delAmoun return stake.MsgDelegate{ DelegatorAddr: delAddr, ValidatorAddr: valAddr, - Delegation: sdk.Coin{"steak", delAmount}, + Delegation: sdk.NewCoin("steak", delAmount), } } diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index fe273be5eb..8225c96347 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -78,7 +78,7 @@ func TestBeginBlocker(t *testing.T) { } // validator should be jailed - validator, found := sk.GetValidatorByConsPubKey(ctx, pk) + validator, found := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)) require.True(t, found) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } diff --git a/x/stake/app_test.go b/x/stake/app_test.go index 922ce8ac3a..f96408c11f 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -21,10 +21,12 @@ var ( priv4 = ed25519.GenPrivKey() addr4 = sdk.AccAddress(priv4.PubKey().Address()) coins = sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(10))} - fee = auth.StdFee{ - sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(0))}, + 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. @@ -129,7 +131,7 @@ func TestStakeMsgs(t *testing.T) { // create validator description := NewDescription("foo_moniker", "", "", "") createValidatorMsg := NewMsgCreateValidator( - sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, + sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, commissionMsg, ) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{createValidatorMsg}, []int64{0}, []int64{0}, true, true, priv1) @@ -143,7 +145,7 @@ func TestStakeMsgs(t *testing.T) { // addr1 create validator on behalf of addr2 createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf( - addr1, sdk.ValAddress(addr2), priv2.PubKey(), bondCoin, description, + addr1, sdk.ValAddress(addr2), priv2.PubKey(), bondCoin, description, commissionMsg, ) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{createValidatorMsgOnBehalfOf}, []int64{0, 1}, []int64{1, 0}, true, true, priv1, priv2) @@ -160,7 +162,7 @@ func TestStakeMsgs(t *testing.T) { // edit the validator description = NewDescription("bar_moniker", "", "", "") - editValidatorMsg := NewMsgEditValidator(sdk.ValAddress(addr1), description) + editValidatorMsg := NewMsgEditValidator(sdk.ValAddress(addr1), description, nil) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{editValidatorMsg}, []int64{0}, []int64{2}, true, true, priv1) validator = checkValidator(t, mApp, keeper, sdk.ValAddress(addr1), true) diff --git a/x/stake/client/cli/flags.go b/x/stake/client/cli/flags.go index 4c36be0b54..bec76298f3 100644 --- a/x/stake/client/cli/flags.go +++ b/x/stake/client/cli/flags.go @@ -21,6 +21,10 @@ const ( FlagIdentity = "identity" FlagWebsite = "website" FlagDetails = "details" + + FlagCommissionRate = "commission-rate" + FlagCommissionMaxRate = "commission-max-rate" + FlagCommissionMaxChangeRate = "commission-max-change-rate" ) // common flagsets to add to various functions @@ -29,6 +33,8 @@ var ( fsAmount = flag.NewFlagSet("", flag.ContinueOnError) fsShares = flag.NewFlagSet("", flag.ContinueOnError) fsDescriptionCreate = flag.NewFlagSet("", flag.ContinueOnError) + fsCommissionCreate = flag.NewFlagSet("", flag.ContinueOnError) + fsCommissionUpdate = flag.NewFlagSet("", flag.ContinueOnError) fsDescriptionEdit = flag.NewFlagSet("", flag.ContinueOnError) fsValidator = flag.NewFlagSet("", flag.ContinueOnError) fsDelegator = flag.NewFlagSet("", flag.ContinueOnError) @@ -44,6 +50,10 @@ func init() { fsDescriptionCreate.String(FlagIdentity, "", "optional identity signature (ex. UPort or Keybase)") fsDescriptionCreate.String(FlagWebsite, "", "optional website") fsDescriptionCreate.String(FlagDetails, "", "optional details") + fsCommissionUpdate.String(FlagCommissionRate, "", "The new commission rate percentage") + fsCommissionCreate.String(FlagCommissionRate, "", "The initial commission rate percentage") + fsCommissionCreate.String(FlagCommissionMaxRate, "", "The maximum commission rate percentage") + fsCommissionCreate.String(FlagCommissionMaxChangeRate, "", "The maximum commission change rate percentage (per day)") fsDescriptionEdit.String(FlagMoniker, types.DoNotModifyDesc, "validator name") fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)") fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website") diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index f917173283..74f4c6d6e7 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -12,9 +12,7 @@ import ( 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/stake" - "github.com/cosmos/cosmos-sdk/x/stake/types" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -66,6 +64,15 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command { Details: viper.GetString(FlagDetails), } + // get the initial validator commission parameters + rateStr := viper.GetString(FlagCommissionRate) + maxRateStr := viper.GetString(FlagCommissionMaxRate) + maxChangeRateStr := viper.GetString(FlagCommissionMaxChangeRate) + commissionMsg, err := buildCommissionMsg(rateStr, maxRateStr, maxChangeRateStr) + if err != nil { + return err + } + var msg sdk.Msg if viper.GetString(FlagAddressDelegator) != "" { delAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressDelegator)) @@ -73,13 +80,19 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command { return err } - msg = stake.NewMsgCreateValidatorOnBehalfOf(delAddr, sdk.ValAddress(valAddr), pk, amount, description) + msg = stake.NewMsgCreateValidatorOnBehalfOf( + delAddr, sdk.ValAddress(valAddr), pk, amount, description, commissionMsg, + ) } else { - msg = stake.NewMsgCreateValidator(sdk.ValAddress(valAddr), pk, amount, description) + msg = stake.NewMsgCreateValidator( + sdk.ValAddress(valAddr), pk, amount, description, commissionMsg, + ) } + if cliCtx.GenerateOnly { return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } + // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, @@ -88,6 +101,7 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command { cmd.Flags().AddFlagSet(fsPk) cmd.Flags().AddFlagSet(fsAmount) cmd.Flags().AddFlagSet(fsDescriptionCreate) + cmd.Flags().AddFlagSet(fsCommissionCreate) cmd.Flags().AddFlagSet(fsDelegator) return cmd @@ -117,17 +131,31 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command { Details: viper.GetString(FlagDetails), } - msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description) + var newRate *sdk.Dec + + commissionRate := viper.GetString(FlagCommissionRate) + if commissionRate != "" { + rate, err := sdk.NewDecFromStr(commissionRate) + if err != nil { + return fmt.Errorf("invalid new commission rate: %v", err) + } + + newRate = &rate + } + + msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description, newRate) if cliCtx.GenerateOnly { return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) } + // build and sign the transaction, then broadcast to Tendermint return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) }, } cmd.Flags().AddFlagSet(fsDescriptionEdit) + cmd.Flags().AddFlagSet(fsCommissionUpdate) return cmd } @@ -247,54 +275,6 @@ func GetCmdBeginRedelegate(storeName string, cdc *codec.Codec) *cobra.Command { return cmd } -// nolint: gocyclo -// TODO: Make this pass gocyclo linting -func getShares( - storeName string, cdc *codec.Codec, sharesAmountStr, - sharesPercentStr string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, -) (sharesAmount sdk.Dec, err error) { - switch { - case sharesAmountStr != "" && sharesPercentStr != "": - return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both") - case sharesAmountStr == "" && sharesPercentStr == "": - return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both") - case sharesAmountStr != "": - sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr) - if err != nil { - return sharesAmount, err - } - if !sharesAmount.GT(sdk.ZeroDec()) { - return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)") - } - case sharesPercentStr != "": - var sharesPercent sdk.Dec - sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr) - if err != nil { - return sharesAmount, err - } - if !sharesPercent.GT(sdk.ZeroDec()) || !sharesPercent.LTE(sdk.OneDec()) { - return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)") - } - - // make a query to get the existing delegation shares - key := stake.GetDelegationKey(delAddr, valAddr) - cliCtx := context.NewCLIContext(). - WithCodec(cdc). - WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) - - resQuery, err := cliCtx.QueryStore(key, storeName) - if err != nil { - return sharesAmount, errors.Errorf("cannot find delegation to determine percent Error: %v", err) - } - delegation, err := types.UnmarshalDelegation(cdc, key, resQuery) - if err != nil { - return sdk.ZeroDec(), err - } - sharesAmount = sharesPercent.Mul(delegation.Shares) - } - return -} - // GetCmdCompleteRedelegate implements the complete redelegation command. func GetCmdCompleteRedelegate(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ diff --git a/x/stake/client/cli/utils.go b/x/stake/client/cli/utils.go new file mode 100644 index 0000000000..9aca2d8995 --- /dev/null +++ b/x/stake/client/cli/utils.go @@ -0,0 +1,88 @@ +package cli + +import ( + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" + "github.com/cosmos/cosmos-sdk/x/stake" + "github.com/cosmos/cosmos-sdk/x/stake/types" + "github.com/pkg/errors" +) + +func getShares( + storeName string, cdc *codec.Codec, sharesAmountStr, + sharesPercentStr string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, +) (sharesAmount sdk.Dec, err error) { + + switch { + case sharesAmountStr != "" && sharesPercentStr != "": + return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both") + + case sharesAmountStr == "" && sharesPercentStr == "": + return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both") + + case sharesAmountStr != "": + sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr) + if err != nil { + return sharesAmount, err + } + if !sharesAmount.GT(sdk.ZeroDec()) { + return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)") + } + + case sharesPercentStr != "": + var sharesPercent sdk.Dec + sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr) + if err != nil { + return sharesAmount, err + } + if !sharesPercent.GT(sdk.ZeroDec()) || !sharesPercent.LTE(sdk.OneDec()) { + return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)") + } + + // make a query to get the existing delegation shares + key := stake.GetDelegationKey(delAddr, valAddr) + cliCtx := context.NewCLIContext(). + WithCodec(cdc). + WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) + + resQuery, err := cliCtx.QueryStore(key, storeName) + if err != nil { + return sharesAmount, errors.Errorf("cannot find delegation to determine percent Error: %v", err) + } + + delegation, err := types.UnmarshalDelegation(cdc, key, resQuery) + if err != nil { + return sdk.ZeroDec(), err + } + + sharesAmount = sharesPercent.Mul(delegation.Shares) + } + + return +} + +func buildCommissionMsg(rateStr, maxRateStr, maxChangeRateStr string) (commission types.CommissionMsg, err error) { + if rateStr == "" || maxRateStr == "" || maxChangeRateStr == "" { + return commission, errors.Errorf("must specify all validator commission parameters") + } + + rate, err := sdk.NewDecFromStr(rateStr) + if err != nil { + return commission, err + } + + maxRate, err := sdk.NewDecFromStr(maxRateStr) + if err != nil { + return commission, err + } + + maxChangeRate, err := sdk.NewDecFromStr(maxChangeRateStr) + if err != nil { + return commission, err + } + + commission = types.NewCommissionMsg(rate, maxRate, maxChangeRate) + return commission, nil +} diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 8d55bed8cf..a8fbfecf4d 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -120,7 +120,6 @@ func delegatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handle } } -// nolint gocyclo // HTTP request handler to query all staking txs (msgs) from a delegator func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index b716843602..324e0c914f 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -69,7 +69,6 @@ type EditDelegationsBody struct { CompleteRedelegates []msgCompleteRedelegateInput `json:"complete_redelegates"` } -// nolint: gocyclo // TODO: Split this up into several smaller functions, and remove the above nolint // TODO: use sdk.ValAddress instead of sdk.AccAddress for validators in messages func delegationsRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc { diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index 8ab5655009..e7b8891eab 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -3,11 +3,12 @@ package rest import ( "fmt" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/stake/tags" + rpcclient "github.com/tendermint/tendermint/rpc/client" - "github.com/cosmos/cosmos-sdk/client/context" ) // contains checks if the a given query contains one of the tx types diff --git a/x/stake/genesis.go b/x/stake/genesis.go index a7f8493081..58b7ed1b4f 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -75,7 +75,7 @@ func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisValidator) { keeper.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) (stop bool) { vals = append(vals, tmtypes.GenesisValidator{ - PubKey: validator.GetPubKey(), + PubKey: validator.GetConsPubKey(), Power: validator.GetPower().RoundInt64(), Name: validator.GetMoniker(), }) diff --git a/x/stake/handler.go b/x/stake/handler.go index 005b3af7d0..0524b2c117 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -62,49 +62,55 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid // now we just perform action and save func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k keeper.Keeper) sdk.Result { - // check to see if the pubkey or sender has been registered before _, found := k.GetValidator(ctx, msg.ValidatorAddr) if found { return ErrValidatorOwnerExists(k.Codespace()).Result() } - _, found = k.GetValidatorByConsPubKey(ctx, msg.PubKey) + + _, found = k.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(msg.PubKey)) if found { return ErrValidatorPubKeyExists(k.Codespace()).Result() } + if msg.Delegation.Denom != k.GetParams(ctx).BondDenom { return ErrBadDenom(k.Codespace()).Result() } validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description) + commission := NewCommissionWithTime( + msg.Commission.Rate, msg.Commission.MaxChangeRate, + msg.Commission.MaxChangeRate, ctx.BlockHeader().Time, + ) + + validator, err := validator.SetInitialCommission(commission) + if err != nil { + return err.Result() + } + k.SetValidator(ctx, validator) k.SetValidatorByConsAddr(ctx, validator) // move coins from the msg.Address account to a (self-delegation) delegator account // the validator account and global shares are updated within here - _, err := k.Delegate(ctx, msg.DelegatorAddr, msg.Delegation, validator, true) + _, err = k.Delegate(ctx, msg.DelegatorAddr, msg.Delegation, validator, true) if err != nil { return err.Result() } - // call the hook if present - k.OnValidatorCreated(ctx, validator.OperatorAddr) - accAddr := sdk.AccAddress(validator.OperatorAddr) - k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr) - tags := sdk.NewTags( tags.Action, tags.ActionCreateValidator, tags.DstValidator, []byte(msg.ValidatorAddr.String()), tags.Moniker, []byte(msg.Description.Moniker), tags.Identity, []byte(msg.Description.Identity), ) + return sdk.Result{ Tags: tags, } } func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keeper.Keeper) sdk.Result { - // validator must already be registered validator, found := k.GetValidator(ctx, msg.ValidatorAddr) if !found { @@ -116,17 +122,26 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe if err != nil { return err.Result() } + validator.Description = description + if msg.CommissionRate != nil { + if err := k.UpdateValidatorCommission(ctx, validator, *msg.CommissionRate); err != nil { + return err.Result() + } + } + // We don't need to run through all the power update logic within k.UpdateValidator // We just need to override the entry in state, since only the description has changed. k.SetValidator(ctx, validator) + tags := sdk.NewTags( tags.Action, tags.ActionEditValidator, tags.DstValidator, []byte(msg.ValidatorAddr.String()), tags.Moniker, []byte(description.Moniker), tags.Identity, []byte(description.Identity), ) + return sdk.Result{ Tags: tags, } @@ -151,9 +166,6 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) return err.Result() } - // call the hook if present - k.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr) - tags := sdk.NewTags( tags.Action, tags.ActionDelegate, tags.Delegator, []byte(msg.DelegatorAddr.String()), diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 4bc92c0b73..5780bf5431 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -17,7 +17,9 @@ import ( //______________________________________________________________________ func newTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator { - return types.NewMsgCreateValidator(address, pubKey, sdk.NewCoin("steak", sdk.NewInt(amt)), Description{}) + return types.NewMsgCreateValidator( + address, pubKey, sdk.NewCoin("steak", sdk.NewInt(amt)), Description{}, commissionMsg, + ) } func newTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt int64) MsgDelegate { @@ -31,6 +33,7 @@ func newTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt int6 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, diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 6ac51ac196..6efa4c8ed3 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -67,11 +67,6 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { // remove a delegation from store func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { - // call the hook if present - if k.hooks != nil { - k.hooks.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr) - } - store := ctx.KVStore(k.storeKey) store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) } @@ -281,11 +276,6 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co k.SetDelegation(ctx, delegation) k.UpdateValidator(ctx, validator) - // call the hook if present - if k.hooks != nil { - k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) - } - return } @@ -344,11 +334,6 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA k.RemoveValidator(ctx, validator.OperatorAddr) } - // call the hook if present - if k.hooks != nil { - k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr) - } - return amount, nil } diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index 82170a4aed..0f700f9ab8 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -14,7 +14,7 @@ type Keeper struct { storeTKey sdk.StoreKey cdc *codec.Codec bankKeeper bank.Keeper - hooks sdk.StakingHooks + hooks sdk.ValidatorHooks // codespace codespace sdk.CodespaceType @@ -33,7 +33,7 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespa } // Set the validator hooks -func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper { +func (k Keeper) WithValidatorHooks(sh sdk.ValidatorHooks) Keeper { if k.hooks != nil { panic("cannot set validator hooks twice") } diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 9872630a4e..d702e845da 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -5,7 +5,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" - "github.com/tendermint/tendermint/crypto" ) // Implements ValidatorSet @@ -67,15 +66,6 @@ func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) sdk.V return val } -// get the sdk.validator for a particular pubkey -func (k Keeper) ValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) sdk.Validator { - val, found := k.GetValidatorByConsPubKey(ctx, consPubKey) - if !found { - return nil - } - return val -} - // total power from the bond func (k Keeper) TotalPower(ctx sdk.Context) sdk.Dec { pool := k.GetPool(ctx) diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index ea378678ae..486dc32869 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -21,8 +21,6 @@ import ( // CONTRACT: // Infraction committed at the current height or at a past height, // not at a height in the future -// -// nolint: gocyclo func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeight int64, power int64, slashFactor sdk.Dec) { logger := ctx.Logger().With("module", "x/stake") @@ -143,7 +141,7 @@ func (k Keeper) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) { // set the jailed flag on a validator func (k Keeper) setJailed(ctx sdk.Context, consAddr sdk.ConsAddress, isJailed bool) { - validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(consAddr)) + validator, found := k.GetValidatorByConsAddr(ctx, consAddr) if !found { panic(fmt.Errorf("validator with consensus-Address %s not found, cannot set jailed to %v", consAddr, isJailed)) } diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index c4a1edd415..0a6cccac2a 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -14,6 +14,7 @@ import ( // TODO integrate with test_common.go helper (CreateTestInput) // setup helper function - creates two validators func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) { + // setup ctx, _, keeper := CreateTestInput(t, false, amt) params := keeper.GetParams(ctx) @@ -472,7 +473,7 @@ func TestSlashBoth(t *testing.T) { // slash validator ctx = ctx.WithBlockHeight(12) oldPool := keeper.GetPool(ctx) - validator, found := keeper.GetValidatorByConsPubKey(ctx, PKs[0]) + validator, found := keeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0])) require.True(t, found) consAddr0 := sdk.ConsAddress(PKs[0].Address()) keeper.Slash(ctx, consAddr0, 10, 10, fraction) @@ -489,7 +490,7 @@ func TestSlashBoth(t *testing.T) { // bonded tokens burned require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) // read updated validator - validator, found = keeper.GetValidatorByConsPubKey(ctx, PKs[0]) + validator, found = keeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0])) require.True(t, found) // power not decreased, all stake was bonded since require.Equal(t, sdk.NewDec(10), validator.GetPower()) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index af7d77e207..9d8fb4362a 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -6,7 +6,6 @@ import ( "fmt" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" @@ -68,17 +67,6 @@ func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress return k.GetValidator(ctx, opAddr) } -// get a single validator by pubkey -func (k Keeper) GetValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) (validator types.Validator, found bool) { - store := ctx.KVStore(k.storeKey) - consAddr := sdk.ConsAddress(consPubKey.Address()) - opAddr := store.Get(GetValidatorByConsAddrKey(consAddr)) - if opAddr == nil { - return validator, false - } - return k.GetValidator(ctx, opAddr) -} - // set the main record holding validator details func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) @@ -87,10 +75,9 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { } // validator index -// TODO change to SetValidatorByConsAddr? used for retrieving from ConsPubkey as well- kinda confusing func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - consAddr := sdk.ConsAddress(validator.OperatorAddr.Bytes()) + consAddr := sdk.ConsAddress(validator.ConsPubKey.Address()) store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr) } @@ -245,7 +232,6 @@ func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Valid // It may kick out validators if a new validator is entering the bonded validator // group. // -// nolint: gocyclo // TODO: Remove above nolint, function needs to be simplified! func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) types.Validator { tstore := ctx.TransientStore(k.storeTKey) @@ -435,9 +421,6 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato // updated in store with the ValidatorsBondedIndexKey. This store is used to // determine if a validator is a validator without needing to iterate over all // validators. -// -// nolint: gocyclo -// TODO: Remove the above golint func (k Keeper) UpdateBondedValidators( ctx sdk.Context, affectedValidator types.Validator) ( updatedVal types.Validator, updated bool) { @@ -681,11 +664,6 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // remove the validator record and associated indexes func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { - // call the hook if present - if k.hooks != nil { - k.hooks.OnValidatorRemoved(ctx, address) - } - // first retrieve the old validator record validator, found := k.GetValidator(ctx, address) if !found { @@ -711,6 +689,23 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { tstore.Set(GetTendermintUpdatesTKey(address), bz) } +// UpdateValidatorCommission attempts to update a validator's commission rate. +// An error is returned if the new commission rate is invalid. +func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, validator types.Validator, newRate sdk.Dec) sdk.Error { + commission := validator.Commission + blockTime := ctx.BlockHeader().Time + + if err := commission.ValidateNewRate(newRate, blockTime); err != nil { + return err + } + + validator.Commission.Rate = newRate + validator.Commission.UpdateTime = blockTime + + k.SetValidator(ctx, validator) + return nil +} + //__________________________________________________________________________ // get the current validator on the cliff @@ -745,36 +740,3 @@ func ensureValidatorFound(found bool, ownerAddr []byte) { panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr)) } } - -//__________________________________________________________________________ - -// XXX remove this code - this is should be superceded by commission work that bez is doing -// get a single validator -func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error { - - // call the hook if present - if k.hooks != nil { - k.hooks.OnValidatorCommissionChange(ctx, addr) - } - - validator, found := k.GetValidator(ctx, addr) - - // check for errors - switch { - case !found: - return types.ErrNoValidatorFound(k.Codespace()) - case newCommission.LT(sdk.ZeroDec()): - return types.ErrCommissionNegative(k.Codespace()) - case newCommission.GT(validator.CommissionMax): - return types.ErrCommissionBeyondMax(k.Codespace()) - //case rateChange(Commission) > CommissionMaxChange: // XXX XXX XXX TODO implementation - //return types.ErrCommissionPastRate(k.Codespace()) - } - - // TODO adjust all the commission terms appropriately - - validator.Commission = newCommission - - k.SetValidator(ctx, validator) - return nil -} diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index a541600d9f..73a391acc7 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -3,9 +3,11 @@ package keeper import ( "fmt" "testing" + "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" + abci "github.com/tendermint/tendermint/abci/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -305,10 +307,19 @@ func TestValidatorBasics(t *testing.T) { // set and retrieve a record validators[0] = keeper.UpdateValidator(ctx, validators[0]) + keeper.SetValidatorByConsAddr(ctx, validators[0]) resVal, found := keeper.GetValidator(ctx, addrVals[0]) require.True(t, found) assert.True(ValEq(t, validators[0], resVal)) + // retrieve from consensus + resVal, found = keeper.GetValidatorByConsAddr(ctx, sdk.ConsAddress(PKs[0].Address())) + require.True(t, found) + assert.True(ValEq(t, validators[0], resVal)) + resVal, found = keeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0])) + require.True(t, found) + assert.True(ValEq(t, validators[0], resVal)) + resVals = keeper.GetValidatorsBonded(ctx) require.Equal(t, 1, len(resVals)) assert.True(ValEq(t, validators[0], resVals[0])) @@ -1044,3 +1055,55 @@ func TestGetValidTendermintUpdatesBondTransition(t *testing.T) { clearTendermintUpdates(ctx, keeper) require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx))) } + +func TestUpdateValidatorCommission(t *testing.T) { + ctx, _, keeper := CreateTestInput(t, false, 1000) + ctx = ctx.WithBlockHeader(abci.Header{Time: time.Now().UTC()}) + + commission1 := types.NewCommissionWithTime( + sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(3, 1), + sdk.NewDecWithPrec(1, 1), time.Now().UTC().Add(time.Duration(-1)*time.Hour), + ) + commission2 := types.NewCommission(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(3, 1), sdk.NewDecWithPrec(1, 1)) + + val1 := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + val2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) + + val1, _ = val1.SetInitialCommission(commission1) + val2, _ = val2.SetInitialCommission(commission2) + + testCases := []struct { + validator types.Validator + newRate sdk.Dec + expectedErr bool + }{ + {val1, sdk.ZeroDec(), true}, + {val2, sdk.NewDecWithPrec(-1, 1), true}, + {val2, sdk.NewDecWithPrec(4, 1), true}, + {val2, sdk.NewDecWithPrec(3, 1), true}, + {val2, sdk.NewDecWithPrec(2, 1), false}, + } + + for i, tc := range testCases { + err := keeper.UpdateValidatorCommission(ctx, tc.validator, tc.newRate) + + if tc.expectedErr { + require.Error(t, err, "expected error for test case #%d with rate: %s", i, tc.newRate) + } else { + val, found := keeper.GetValidator(ctx, tc.validator.OperatorAddr) + + require.True(t, found, + "expected to find validator for test case #%d with rate: %s", i, tc.newRate, + ) + require.NoError(t, err, + "unexpected error for test case #%d with rate: %s", i, tc.newRate, + ) + require.Equal(t, tc.newRate, val.Commission.Rate, + "expected new validator commission rate for test case #%d with rate: %s", i, tc.newRate, + ) + require.Equal(t, ctx.BlockHeader().Time, val.Commission.UpdateTime, + "expected new validator commission update time for test case #%d with rate: %s", i, tc.newRate, + ) + } + } +} diff --git a/x/stake/simulation/invariants.go b/x/stake/simulation/invariants.go index 2ab0717042..cdd80a8c41 100644 --- a/x/stake/simulation/invariants.go +++ b/x/stake/simulation/invariants.go @@ -80,7 +80,7 @@ func PositivePowerInvariant(k stake.Keeper) simulation.Invariant { var err error k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool { if !validator.GetPower().GT(sdk.ZeroDec()) { - err = fmt.Errorf("validator with non-positive power stored. (pubkey %v)", validator.GetPubKey()) + err = fmt.Errorf("validator with non-positive power stored. (pubkey %v)", validator.GetConsPubKey()) return true } return false diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index 5b2bc1ee81..0cd4e08a92 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -11,44 +11,57 @@ import ( "github.com/cosmos/cosmos-sdk/x/mock/simulation" "github.com/cosmos/cosmos-sdk/x/stake" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" ) // 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, keys []crypto.PrivKey, 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{ Moniker: simulation.RandStringOfLength(r, 10), } - key := simulation.RandomKey(r, keys) - pubkey := key.PubKey() - address := sdk.ValAddress(pubkey.Address()) - amount := m.GetAccount(ctx, sdk.AccAddress(address)).GetCoins().AmountOf(denom) + + maxCommission := sdk.NewInt(10) + commission := stake.NewCommissionMsg( + sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1), + sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1), + sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1), + ) + + acc := simulation.RandomAcc(r, accs) + address := sdk.ValAddress(acc.Address) + amount := m.GetAccount(ctx, acc.Address).GetCoins().AmountOf(denom) if amount.GT(sdk.ZeroInt()) { amount = simulation.RandomAmount(r, amount) } + if amount.Equal(sdk.ZeroInt()) { return "no-operation", nil, nil } + msg := stake.MsgCreateValidator{ Description: description, + Commission: commission, ValidatorAddr: address, - DelegatorAddr: sdk.AccAddress(address), - PubKey: pubkey, + DelegatorAddr: acc.Address, + PubKey: acc.PubKey, Delegation: sdk.NewCoin(denom, amount), } + if msg.ValidateBasic() != nil { return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } + ctx, write := ctx.CacheContext() result := handler(ctx, msg) if result.IsOK() { write() } + event(fmt.Sprintf("stake/MsgCreateValidator/%v", result.IsOK())) + // require.True(t, result.IsOK(), "expected OK result but instead got %v", result) action = fmt.Sprintf("TestMsgCreateValidator: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) return action, nil, nil @@ -58,7 +71,7 @@ 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, keys []crypto.PrivKey, 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), @@ -66,16 +79,22 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { Website: simulation.RandStringOfLength(r, 10), Details: simulation.RandStringOfLength(r, 10), } - key := simulation.RandomKey(r, keys) - pubkey := key.PubKey() - address := sdk.ValAddress(pubkey.Address()) + + maxCommission := sdk.NewInt(10) + newCommissionRate := sdk.NewDecWithPrec(simulation.RandomAmount(r, maxCommission).Int64(), 1) + + acc := simulation.RandomAcc(r, accs) + address := sdk.ValAddress(acc.Address) msg := stake.MsgEditValidator{ - Description: description, - ValidatorAddr: address, + Description: description, + ValidatorAddr: address, + CommissionRate: &newCommissionRate, } + if msg.ValidateBasic() != nil { return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) } + ctx, write := ctx.CacheContext() result := handler(ctx, msg) if result.IsOK() { @@ -90,13 +109,13 @@ 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, keys []crypto.PrivKey, 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 - validatorKey := simulation.RandomKey(r, keys) - validatorAddress := sdk.ValAddress(validatorKey.PubKey().Address()) - delegatorKey := simulation.RandomKey(r, keys) - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + validatorAcc := simulation.RandomAcc(r, accs) + validatorAddress := sdk.ValAddress(validatorAcc.Address) + delegatorAcc := simulation.RandomAcc(r, accs) + delegatorAddress := delegatorAcc.Address amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) if amount.GT(sdk.ZeroInt()) { amount = simulation.RandomAmount(r, amount) @@ -126,13 +145,13 @@ 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, keys []crypto.PrivKey, 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 - validatorKey := simulation.RandomKey(r, keys) - validatorAddress := sdk.ValAddress(validatorKey.PubKey().Address()) - delegatorKey := simulation.RandomKey(r, keys) - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + validatorAcc := simulation.RandomAcc(r, accs) + validatorAddress := sdk.ValAddress(validatorAcc.Address) + delegatorAcc := simulation.RandomAcc(r, accs) + delegatorAddress := delegatorAcc.Address amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) if amount.GT(sdk.ZeroInt()) { amount = simulation.RandomAmount(r, amount) @@ -162,12 +181,12 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. // SimulateMsgCompleteUnbonding func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, 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) { - validatorKey := simulation.RandomKey(r, keys) - validatorAddress := sdk.ValAddress(validatorKey.PubKey().Address()) - delegatorKey := simulation.RandomKey(r, keys) - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + validatorAcc := simulation.RandomAcc(r, accs) + validatorAddress := sdk.ValAddress(validatorAcc.Address) + delegatorAcc := simulation.RandomAcc(r, accs) + delegatorAddress := delegatorAcc.Address msg := stake.MsgCompleteUnbonding{ DelegatorAddr: delegatorAddress, ValidatorAddr: validatorAddress, @@ -189,15 +208,15 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { // 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, keys []crypto.PrivKey, 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 - sourceValidatorKey := simulation.RandomKey(r, keys) - sourceValidatorAddress := sdk.ValAddress(sourceValidatorKey.PubKey().Address()) - destValidatorKey := simulation.RandomKey(r, keys) - destValidatorAddress := sdk.ValAddress(destValidatorKey.PubKey().Address()) - delegatorKey := simulation.RandomKey(r, keys) - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + sourceValidatorAcc := simulation.RandomAcc(r, accs) + sourceValidatorAddress := sdk.ValAddress(sourceValidatorAcc.Address) + destValidatorAcc := simulation.RandomAcc(r, accs) + destValidatorAddress := sdk.ValAddress(destValidatorAcc.Address) + delegatorAcc := simulation.RandomAcc(r, accs) + delegatorAddress := delegatorAcc.Address // TODO amount := m.GetAccount(ctx, delegatorAddress).GetCoins().AmountOf(denom) if amount.GT(sdk.ZeroInt()) { @@ -229,14 +248,14 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation // SimulateMsgCompleteRedelegate func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { handler := stake.NewHandler(k) - return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, 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) { - validatorSrcKey := simulation.RandomKey(r, keys) - validatorSrcAddress := sdk.ValAddress(validatorSrcKey.PubKey().Address()) - validatorDstKey := simulation.RandomKey(r, keys) - validatorDstAddress := sdk.ValAddress(validatorDstKey.PubKey().Address()) - delegatorKey := simulation.RandomKey(r, keys) - delegatorAddress := sdk.AccAddress(delegatorKey.PubKey().Address()) + validatorSrcAcc := simulation.RandomAcc(r, accs) + validatorSrcAddress := sdk.ValAddress(validatorSrcAcc.Address) + validatorDstAcc := simulation.RandomAcc(r, accs) + validatorDstAddress := sdk.ValAddress(validatorDstAcc.Address) + delegatorAcc := simulation.RandomAcc(r, accs) + delegatorAddress := delegatorAcc.Address msg := stake.MsgCompleteRedelegate{ DelegatorAddr: delegatorAddress, ValidatorSrcAddr: validatorSrcAddress, @@ -259,7 +278,7 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { // Setup // nolint: errcheck func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup { - return func(r *rand.Rand, privKeys []crypto.PrivKey) { + return func(r *rand.Rand, accs []simulation.Account) { ctx := mapp.NewContext(false, abci.Header{}) gen := stake.DefaultGenesisState() gen.Params.InflationMax = sdk.NewDec(0) diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 53b9d826ce..b81555f030 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -6,7 +6,6 @@ import ( "testing" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/bank" @@ -38,8 +37,8 @@ func TestStakeWithRandomMessages(t *testing.T) { panic(err) } - appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { - mock.RandomSetGenesis(r, mapp, accs, []string{"stake"}) + appStateFn := func(r *rand.Rand, accs []simulation.Account) json.RawMessage { + simulation.RandomSetGenesis(r, mapp, accs, []string{"stake"}) return json.RawMessage("{}") } diff --git a/x/stake/stake.go b/x/stake/stake.go index 6b4036d281..7e60b3113a 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -12,6 +12,7 @@ type ( Keeper = keeper.Keeper Validator = types.Validator Description = types.Description + Commission = types.Commission Delegation = types.Delegation DelegationSummary = types.DelegationSummary UnbondingDelegation = types.UnbondingDelegation @@ -64,13 +65,16 @@ var ( GetREDsToValDstIndexKey = keeper.GetREDsToValDstIndexKey GetREDsByDelToValDstIndexKey = keeper.GetREDsByDelToValDstIndexKey - DefaultParams = types.DefaultParams - InitialPool = types.InitialPool - NewValidator = types.NewValidator - NewDescription = types.NewDescription - NewGenesisState = types.NewGenesisState - DefaultGenesisState = types.DefaultGenesisState - RegisterCodec = types.RegisterCodec + DefaultParams = types.DefaultParams + InitialPool = types.InitialPool + NewValidator = types.NewValidator + NewDescription = types.NewDescription + NewCommission = types.NewCommission + NewCommissionMsg = types.NewCommissionMsg + NewCommissionWithTime = types.NewCommissionWithTime + NewGenesisState = types.NewGenesisState + DefaultGenesisState = types.DefaultGenesisState + RegisterCodec = types.RegisterCodec NewMsgCreateValidator = types.NewMsgCreateValidator NewMsgCreateValidatorOnBehalfOf = types.NewMsgCreateValidatorOnBehalfOf diff --git a/x/stake/types/commission.go b/x/stake/types/commission.go new file mode 100644 index 0000000000..b76971faa0 --- /dev/null +++ b/x/stake/types/commission.go @@ -0,0 +1,128 @@ +package types + +import ( + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type ( + // Commission defines a commission parameters for a given validator. + Commission struct { + Rate sdk.Dec `json:"rate"` // the commission rate charged to delegators + MaxRate sdk.Dec `json:"max_rate"` // maximum commission rate which validator can ever charge + MaxChangeRate sdk.Dec `json:"max_change_rate"` // maximum daily increase of the validator commission + UpdateTime time.Time `json:"update_time"` // the last time the commission rate was changed + } + + // CommissionMsg defines a commission message to be used for creating a + // validator. + CommissionMsg struct { + Rate sdk.Dec `json:"rate"` // the commission rate charged to delegators + MaxRate sdk.Dec `json:"max_rate"` // maximum commission rate which validator can ever charge + MaxChangeRate sdk.Dec `json:"max_change_rate"` // maximum daily increase of the validator commission + } +) + +// NewCommissionMsg returns an initialized validator commission message. +func NewCommissionMsg(rate, maxRate, maxChangeRate sdk.Dec) CommissionMsg { + return CommissionMsg{ + Rate: rate, + MaxRate: maxRate, + MaxChangeRate: maxChangeRate, + } +} + +// NewCommission returns an initialized validator commission. +func NewCommission(rate, maxRate, maxChangeRate sdk.Dec) Commission { + return Commission{ + Rate: rate, + MaxRate: maxRate, + MaxChangeRate: maxChangeRate, + UpdateTime: time.Unix(0, 0).UTC(), + } +} + +// NewCommission returns an initialized validator commission with a specified +// update time which should be the current block BFT time. +func NewCommissionWithTime(rate, maxRate, maxChangeRate sdk.Dec, updatedAt time.Time) Commission { + return Commission{ + Rate: rate, + MaxRate: maxRate, + MaxChangeRate: maxChangeRate, + UpdateTime: updatedAt, + } +} + +// Equal checks if the given Commission object is equal to the receiving +// Commission object. +func (c Commission) Equal(c2 Commission) bool { + return c.Rate.Equal(c2.Rate) && + c.MaxRate.Equal(c2.MaxRate) && + c.MaxChangeRate.Equal(c2.MaxChangeRate) && + c.UpdateTime.Equal(c2.UpdateTime) +} + +// String implements the Stringer interface for a Commission. +func (c Commission) String() string { + return fmt.Sprintf("rate: %s, maxRate: %s, maxChangeRate: %s, updateTime: %s", + c.Rate, c.MaxRate, c.MaxChangeRate, c.UpdateTime, + ) +} + +// Validate performs basic sanity validation checks of initial commission +// parameters. If validation fails, an SDK error is returned. +func (c Commission) Validate() sdk.Error { + switch { + case c.MaxRate.LT(sdk.ZeroDec()): + // max rate cannot be negative + return ErrCommissionNegative(DefaultCodespace) + + case c.MaxRate.GT(sdk.OneDec()): + // max rate cannot be greater than 100% + return ErrCommissionHuge(DefaultCodespace) + + case c.Rate.LT(sdk.ZeroDec()): + // rate cannot be negative + return ErrCommissionNegative(DefaultCodespace) + + case c.Rate.GT(c.MaxRate): + // rate cannot be greater than the max rate + return ErrCommissionGTMaxRate(DefaultCodespace) + + case c.MaxChangeRate.LT(sdk.ZeroDec()): + // change rate cannot be negative + return ErrCommissionChangeRateNegative(DefaultCodespace) + + case c.MaxChangeRate.GT(c.MaxRate): + // change rate cannot be greater than the max rate + return ErrCommissionChangeRateGTMaxRate(DefaultCodespace) + } + + return nil +} + +// ValidateNewRate performs basic sanity validation checks of a new commission +// rate. If validation fails, an SDK error is returned. +func (c Commission) ValidateNewRate(newRate sdk.Dec, blockTime time.Time) sdk.Error { + switch { + case blockTime.Sub(c.UpdateTime).Hours() < 24: + // new rate cannot be changed more than once within 24 hours + return ErrCommissionUpdateTime(DefaultCodespace) + + case newRate.LT(sdk.ZeroDec()): + // new rate cannot be negative + return ErrCommissionNegative(DefaultCodespace) + + case newRate.GT(c.MaxRate): + // new rate cannot be greater than the max rate + return ErrCommissionGTMaxRate(DefaultCodespace) + + case newRate.Sub(c.Rate).Abs().GT(c.MaxChangeRate): + // new rate % points change cannot be greater than the max change rate + return ErrCommissionGTMaxChangeRate(DefaultCodespace) + } + + return nil +} diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 541ad3d7b9..84a7e5ae68 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -65,12 +65,24 @@ func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%") } -func ErrCommissionBeyondMax(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than preset commission maximum") +func ErrCommissionGTMaxRate(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than the max rate") } -func ErrCommissionPastRate(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidValidator, "commission change is greater than the commission rate, please wait before changing your commission more") +func ErrCommissionUpdateTime(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be changed more than once in 24h") +} + +func ErrCommissionChangeRateNegative(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission change rate must be positive") +} + +func ErrCommissionChangeRateGTMaxRate(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission change rate cannot be more than the max rate") +} + +func ErrCommissionGTMaxChangeRate(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be changed more than max change rate") } func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { diff --git a/x/stake/types/inflation_test.go b/x/stake/types/inflation_test.go index fd181af3c9..159ecb4c4e 100644 --- a/x/stake/types/inflation_test.go +++ b/x/stake/types/inflation_test.go @@ -107,7 +107,6 @@ func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Dec, } // Checks that The inflation will correctly increase or decrease after an update to the pool -// nolint: gocyclo func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Dec, msg string) { inflationChange := updatedInflation.Sub(previousInflation) diff --git a/x/stake/types/msg.go b/x/stake/types/msg.go index 558c913fc7..a313dd64f4 100644 --- a/x/stake/types/msg.go +++ b/x/stake/types/msg.go @@ -20,6 +20,7 @@ var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{} // MsgCreateValidator - struct for unbonding transactions type MsgCreateValidator struct { Description + Commission CommissionMsg DelegatorAddr sdk.AccAddress `json:"delegator_address"` ValidatorAddr sdk.ValAddress `json:"validator_address"` PubKey crypto.PubKey `json:"pubkey"` @@ -28,22 +29,23 @@ type MsgCreateValidator struct { // Default way to create validator. Delegator address and validator address are the same func NewMsgCreateValidator(valAddr sdk.ValAddress, pubkey crypto.PubKey, - selfDelegation sdk.Coin, description Description) MsgCreateValidator { + selfDelegation sdk.Coin, description Description, commission CommissionMsg) MsgCreateValidator { return NewMsgCreateValidatorOnBehalfOf( - sdk.AccAddress(valAddr), valAddr, pubkey, selfDelegation, description, + sdk.AccAddress(valAddr), valAddr, pubkey, selfDelegation, description, commission, ) } // Creates validator msg by delegator address on behalf of validator address func NewMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.ValAddress, - pubkey crypto.PubKey, delegation sdk.Coin, description Description) MsgCreateValidator { + pubkey crypto.PubKey, delegation sdk.Coin, description Description, commission CommissionMsg) MsgCreateValidator { return MsgCreateValidator{ Description: description, DelegatorAddr: delAddr, ValidatorAddr: valAddr, PubKey: pubkey, Delegation: delegation, + Commission: commission, } } @@ -95,10 +97,13 @@ func (msg MsgCreateValidator) ValidateBasic() sdk.Error { if !(msg.Delegation.Amount.GT(sdk.ZeroInt())) { return ErrBadDelegationAmount(DefaultCodespace) } - empty := Description{} - if msg.Description == empty { + if msg.Description == (Description{}) { return sdk.NewError(DefaultCodespace, CodeInvalidInput, "description must be included") } + if msg.Commission == (CommissionMsg{}) { + return sdk.NewError(DefaultCodespace, CodeInvalidInput, "commission must be included") + } + return nil } @@ -108,12 +113,20 @@ func (msg MsgCreateValidator) ValidateBasic() sdk.Error { type MsgEditValidator struct { Description ValidatorAddr sdk.ValAddress `json:"address"` + + // We pass a reference to the new commission rate as it's not mandatory to + // update. If not updated, the deserialized rate will be zero with no way to + // distinguish if an update was intended. + // + // REF: #2373 + CommissionRate *sdk.Dec `json:"commission_rate"` } -func NewMsgEditValidator(valAddr sdk.ValAddress, description Description) MsgEditValidator { +func NewMsgEditValidator(valAddr sdk.ValAddress, description Description, newRate *sdk.Dec) MsgEditValidator { return MsgEditValidator{ - Description: description, - ValidatorAddr: valAddr, + Description: description, + CommissionRate: newRate, + ValidatorAddr: valAddr, } } @@ -144,10 +157,11 @@ func (msg MsgEditValidator) ValidateBasic() sdk.Error { if msg.ValidatorAddr == nil { return sdk.NewError(DefaultCodespace, CodeInvalidInput, "nil validator address") } - empty := Description{} - if msg.Description == empty { + + if msg.Description == (Description{}) { return sdk.NewError(DefaultCodespace, CodeInvalidInput, "transaction must include some information to modify") } + return nil } diff --git a/x/stake/types/msg_test.go b/x/stake/types/msg_test.go index eb66c04220..b5adbd0ad0 100644 --- a/x/stake/types/msg_test.go +++ b/x/stake/types/msg_test.go @@ -17,26 +17,30 @@ var ( // test ValidateBasic for MsgCreateValidator func TestMsgCreateValidator(t *testing.T) { + commission1 := NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) + commission2 := NewCommissionMsg(sdk.NewDec(5), sdk.NewDec(5), sdk.NewDec(5)) + tests := []struct { name, moniker, identity, website, details string + commissionMsg CommissionMsg validatorAddr sdk.ValAddress pubkey crypto.PubKey bond sdk.Coin expectPass bool }{ - {"basic good", "a", "b", "c", "d", addr1, pk1, coinPos, true}, - {"partial description", "", "", "c", "", addr1, pk1, coinPos, true}, - {"empty description", "", "", "", "", addr1, pk1, coinPos, false}, - {"empty address", "a", "b", "c", "d", emptyAddr, pk1, coinPos, false}, - {"empty pubkey", "a", "b", "c", "d", addr1, emptyPubkey, coinPos, true}, - {"empty bond", "a", "b", "c", "d", addr1, pk1, coinZero, false}, - {"negative bond", "a", "b", "c", "d", addr1, pk1, coinNeg, false}, - {"negative bond", "a", "b", "c", "d", addr1, pk1, coinNeg, false}, + {"basic good", "a", "b", "c", "d", commission1, addr1, pk1, coinPos, true}, + {"partial description", "", "", "c", "", commission1, addr1, pk1, coinPos, true}, + {"empty description", "", "", "", "", commission2, addr1, pk1, coinPos, false}, + {"empty address", "a", "b", "c", "d", commission2, emptyAddr, pk1, coinPos, false}, + {"empty pubkey", "a", "b", "c", "d", commission1, addr1, emptyPubkey, coinPos, true}, + {"empty bond", "a", "b", "c", "d", commission2, addr1, pk1, coinZero, false}, + {"negative bond", "a", "b", "c", "d", commission2, addr1, pk1, coinNeg, false}, + {"negative bond", "a", "b", "c", "d", commission1, addr1, pk1, coinNeg, false}, } for _, tc := range tests { description := NewDescription(tc.moniker, tc.identity, tc.website, tc.details) - msg := NewMsgCreateValidator(tc.validatorAddr, tc.pubkey, tc.bond, description) + msg := NewMsgCreateValidator(tc.validatorAddr, tc.pubkey, tc.bond, description, tc.commissionMsg) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) } else { @@ -60,7 +64,9 @@ func TestMsgEditValidator(t *testing.T) { for _, tc := range tests { description := NewDescription(tc.moniker, tc.identity, tc.website, tc.details) - msg := NewMsgEditValidator(tc.validatorAddr, description) + newRate := sdk.ZeroDec() + + msg := NewMsgEditValidator(tc.validatorAddr, description, &newRate) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) } else { @@ -71,28 +77,35 @@ func TestMsgEditValidator(t *testing.T) { // test ValidateBasic and GetSigners for MsgCreateValidatorOnBehalfOf func TestMsgCreateValidatorOnBehalfOf(t *testing.T) { + commission1 := NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) + commission2 := NewCommissionMsg(sdk.NewDec(5), sdk.NewDec(5), sdk.NewDec(5)) + tests := []struct { name, moniker, identity, website, details string + commissionMsg CommissionMsg delegatorAddr sdk.AccAddress validatorAddr sdk.ValAddress validatorPubKey crypto.PubKey bond sdk.Coin expectPass bool }{ - {"basic good", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, pk2, coinPos, true}, - {"partial description", "", "", "c", "", sdk.AccAddress(addr1), addr2, pk2, coinPos, true}, - {"empty description", "", "", "", "", sdk.AccAddress(addr1), addr2, pk2, coinPos, false}, - {"empty delegator address", "a", "b", "c", "d", sdk.AccAddress(emptyAddr), addr2, pk2, coinPos, false}, - {"empty validator address", "a", "b", "c", "d", sdk.AccAddress(addr1), emptyAddr, pk2, coinPos, false}, - {"empty pubkey", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, emptyPubkey, coinPos, true}, - {"empty bond", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, pk2, coinZero, false}, - {"negative bond", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, pk2, coinNeg, false}, - {"negative bond", "a", "b", "c", "d", sdk.AccAddress(addr1), addr2, pk2, coinNeg, false}, + {"basic good", "a", "b", "c", "d", commission2, sdk.AccAddress(addr1), addr2, pk2, coinPos, true}, + {"partial description", "", "", "c", "", commission2, sdk.AccAddress(addr1), addr2, pk2, coinPos, true}, + {"empty description", "", "", "", "", commission1, sdk.AccAddress(addr1), addr2, pk2, coinPos, false}, + {"empty delegator address", "a", "b", "c", "d", commission1, sdk.AccAddress(emptyAddr), addr2, pk2, coinPos, false}, + {"empty validator address", "a", "b", "c", "d", commission2, sdk.AccAddress(addr1), emptyAddr, pk2, coinPos, false}, + {"empty pubkey", "a", "b", "c", "d", commission1, sdk.AccAddress(addr1), addr2, emptyPubkey, coinPos, true}, + {"empty bond", "a", "b", "c", "d", commission2, sdk.AccAddress(addr1), addr2, pk2, coinZero, false}, + {"negative bond", "a", "b", "c", "d", commission1, sdk.AccAddress(addr1), addr2, pk2, coinNeg, false}, + {"negative bond", "a", "b", "c", "d", commission2, sdk.AccAddress(addr1), addr2, pk2, coinNeg, false}, } for _, tc := range tests { description := NewDescription(tc.moniker, tc.identity, tc.website, tc.details) - msg := NewMsgCreateValidatorOnBehalfOf(tc.delegatorAddr, tc.validatorAddr, tc.validatorPubKey, tc.bond, description) + msg := NewMsgCreateValidatorOnBehalfOf( + tc.delegatorAddr, tc.validatorAddr, tc.validatorPubKey, tc.bond, description, tc.commissionMsg, + ) + if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) } else { @@ -100,11 +113,11 @@ func TestMsgCreateValidatorOnBehalfOf(t *testing.T) { } } - msg := NewMsgCreateValidator(addr1, pk1, coinPos, Description{}) + msg := NewMsgCreateValidator(addr1, pk1, coinPos, Description{}, CommissionMsg{}) addrs := msg.GetSigners() require.Equal(t, []sdk.AccAddress{sdk.AccAddress(addr1)}, addrs, "Signers on default msg is wrong") - msg = NewMsgCreateValidatorOnBehalfOf(sdk.AccAddress(addr2), addr1, pk1, coinPos, Description{}) + msg = NewMsgCreateValidatorOnBehalfOf(sdk.AccAddress(addr2), addr1, pk1, coinPos, Description{}, CommissionMsg{}) addrs = msg.GetSigners() require.Equal(t, []sdk.AccAddress{sdk.AccAddress(addr2), sdk.AccAddress(addr1)}, addrs, "Signers for onbehalfof msg is wrong") } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index c15d43396c..051ffa9e51 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -36,68 +36,56 @@ type Validator struct { UnbondingHeight int64 `json:"unbonding_height"` // if unbonding, height at which this validator has begun unbonding UnbondingMinTime time.Time `json:"unbonding_time"` // if unbonding, min time for the validator to complete unbonding - Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators - CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge - CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission - CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) + Commission Commission `json:"commission"` // commission parameters } // NewValidator - initialize a new validator func NewValidator(operator sdk.ValAddress, pubKey crypto.PubKey, description Description) Validator { return Validator{ - OperatorAddr: operator, - ConsPubKey: pubKey, - Jailed: false, - Status: sdk.Unbonded, - Tokens: sdk.ZeroDec(), - DelegatorShares: sdk.ZeroDec(), - Description: description, - BondHeight: int64(0), - BondIntraTxCounter: int16(0), - UnbondingHeight: int64(0), - UnbondingMinTime: time.Unix(0, 0).UTC(), - Commission: sdk.ZeroDec(), - CommissionMax: sdk.ZeroDec(), - CommissionChangeRate: sdk.ZeroDec(), - CommissionChangeToday: sdk.ZeroDec(), + OperatorAddr: operator, + ConsPubKey: pubKey, + Jailed: false, + Status: sdk.Unbonded, + Tokens: sdk.ZeroDec(), + DelegatorShares: sdk.ZeroDec(), + Description: description, + BondHeight: int64(0), + BondIntraTxCounter: int16(0), + UnbondingHeight: int64(0), + UnbondingMinTime: time.Unix(0, 0).UTC(), + Commission: NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), } } // what's kept in the store value type validatorValue struct { - ConsPubKey crypto.PubKey - Jailed bool - Status sdk.BondStatus - Tokens sdk.Dec - DelegatorShares sdk.Dec - Description Description - BondHeight int64 - BondIntraTxCounter int16 - UnbondingHeight int64 - UnbondingMinTime time.Time - Commission sdk.Dec - CommissionMax sdk.Dec - CommissionChangeRate sdk.Dec - CommissionChangeToday sdk.Dec + ConsPubKey crypto.PubKey + Jailed bool + Status sdk.BondStatus + Tokens sdk.Dec + DelegatorShares sdk.Dec + Description Description + BondHeight int64 + BondIntraTxCounter int16 + UnbondingHeight int64 + UnbondingMinTime time.Time + Commission Commission } // return the redelegation without fields contained within the key for the store func MustMarshalValidator(cdc *codec.Codec, validator Validator) []byte { val := validatorValue{ - ConsPubKey: validator.ConsPubKey, - Jailed: validator.Jailed, - Status: validator.Status, - Tokens: validator.Tokens, - DelegatorShares: validator.DelegatorShares, - Description: validator.Description, - BondHeight: validator.BondHeight, - BondIntraTxCounter: validator.BondIntraTxCounter, - UnbondingHeight: validator.UnbondingHeight, - UnbondingMinTime: validator.UnbondingMinTime, - Commission: validator.Commission, - CommissionMax: validator.CommissionMax, - CommissionChangeRate: validator.CommissionChangeRate, - CommissionChangeToday: validator.CommissionChangeToday, + ConsPubKey: validator.ConsPubKey, + Jailed: validator.Jailed, + Status: validator.Status, + Tokens: validator.Tokens, + DelegatorShares: validator.DelegatorShares, + Description: validator.Description, + BondHeight: validator.BondHeight, + BondIntraTxCounter: validator.BondIntraTxCounter, + UnbondingHeight: validator.UnbondingHeight, + UnbondingMinTime: validator.UnbondingMinTime, + Commission: validator.Commission, } return cdc.MustMarshalBinary(val) } @@ -124,21 +112,18 @@ func UnmarshalValidator(cdc *codec.Codec, operatorAddr, value []byte) (validator } return Validator{ - OperatorAddr: operatorAddr, - ConsPubKey: storeValue.ConsPubKey, - Jailed: storeValue.Jailed, - Tokens: storeValue.Tokens, - Status: storeValue.Status, - DelegatorShares: storeValue.DelegatorShares, - Description: storeValue.Description, - BondHeight: storeValue.BondHeight, - BondIntraTxCounter: storeValue.BondIntraTxCounter, - UnbondingHeight: storeValue.UnbondingHeight, - UnbondingMinTime: storeValue.UnbondingMinTime, - Commission: storeValue.Commission, - CommissionMax: storeValue.CommissionMax, - CommissionChangeRate: storeValue.CommissionChangeRate, - CommissionChangeToday: storeValue.CommissionChangeToday, + OperatorAddr: operatorAddr, + ConsPubKey: storeValue.ConsPubKey, + Jailed: storeValue.Jailed, + Tokens: storeValue.Tokens, + Status: storeValue.Status, + DelegatorShares: storeValue.DelegatorShares, + Description: storeValue.Description, + BondHeight: storeValue.BondHeight, + BondIntraTxCounter: storeValue.BondIntraTxCounter, + UnbondingHeight: storeValue.UnbondingHeight, + UnbondingMinTime: storeValue.UnbondingMinTime, + Commission: storeValue.Commission, }, nil } @@ -156,16 +141,13 @@ func (v Validator) HumanReadableString() (string, error) { resp += fmt.Sprintf("Validator Consensus Pubkey: %s\n", bechConsPubKey) resp += fmt.Sprintf("Jailed: %v\n", v.Jailed) resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status)) - resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.String()) - resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.String()) + resp += fmt.Sprintf("Tokens: %s\n", v.Tokens) + resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares) resp += fmt.Sprintf("Description: %s\n", v.Description) resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight) resp += fmt.Sprintf("Unbonding Height: %d\n", v.UnbondingHeight) resp += fmt.Sprintf("Minimum Unbonding Time: %v\n", v.UnbondingMinTime) - resp += fmt.Sprintf("Commission: %s\n", v.Commission.String()) - resp += fmt.Sprintf("Max Commission Rate: %s\n", v.CommissionMax.String()) - resp += fmt.Sprintf("Commission Change Rate: %s\n", v.CommissionChangeRate.String()) - resp += fmt.Sprintf("Commission Change Today: %s\n", v.CommissionChangeToday.String()) + resp += fmt.Sprintf("Commission: {%s}\n", v.Commission) return resp, nil } @@ -189,10 +171,7 @@ type bechValidator struct { UnbondingHeight int64 `json:"unbonding_height"` // if unbonding, height at which this validator has begun unbonding UnbondingMinTime time.Time `json:"unbonding_time"` // if unbonding, min time for the validator to complete unbonding - Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators - CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge - CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission - CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) + Commission Commission `json:"commission"` // commission parameters } // MarshalJSON marshals the validator to JSON using Bech32 @@ -203,21 +182,18 @@ func (v Validator) MarshalJSON() ([]byte, error) { } return codec.Cdc.MarshalJSON(bechValidator{ - OperatorAddr: v.OperatorAddr, - ConsPubKey: bechConsPubKey, - Jailed: v.Jailed, - Status: v.Status, - Tokens: v.Tokens, - DelegatorShares: v.DelegatorShares, - Description: v.Description, - BondHeight: v.BondHeight, - BondIntraTxCounter: v.BondIntraTxCounter, - UnbondingHeight: v.UnbondingHeight, - UnbondingMinTime: v.UnbondingMinTime, - Commission: v.Commission, - CommissionMax: v.CommissionMax, - CommissionChangeRate: v.CommissionChangeRate, - CommissionChangeToday: v.CommissionChangeToday, + OperatorAddr: v.OperatorAddr, + ConsPubKey: bechConsPubKey, + Jailed: v.Jailed, + Status: v.Status, + Tokens: v.Tokens, + DelegatorShares: v.DelegatorShares, + Description: v.Description, + BondHeight: v.BondHeight, + BondIntraTxCounter: v.BondIntraTxCounter, + UnbondingHeight: v.UnbondingHeight, + UnbondingMinTime: v.UnbondingMinTime, + Commission: v.Commission, }) } @@ -232,21 +208,18 @@ func (v *Validator) UnmarshalJSON(data []byte) error { return err } *v = Validator{ - OperatorAddr: bv.OperatorAddr, - ConsPubKey: consPubKey, - Jailed: bv.Jailed, - Tokens: bv.Tokens, - Status: bv.Status, - DelegatorShares: bv.DelegatorShares, - Description: bv.Description, - BondHeight: bv.BondHeight, - BondIntraTxCounter: bv.BondIntraTxCounter, - UnbondingHeight: bv.UnbondingHeight, - UnbondingMinTime: bv.UnbondingMinTime, - Commission: bv.Commission, - CommissionMax: bv.CommissionMax, - CommissionChangeRate: bv.CommissionChangeRate, - CommissionChangeToday: bv.CommissionChangeToday, + OperatorAddr: bv.OperatorAddr, + ConsPubKey: consPubKey, + Jailed: bv.Jailed, + Tokens: bv.Tokens, + Status: bv.Status, + DelegatorShares: bv.DelegatorShares, + Description: bv.Description, + BondHeight: bv.BondHeight, + BondIntraTxCounter: bv.BondIntraTxCounter, + UnbondingHeight: bv.UnbondingHeight, + UnbondingMinTime: bv.UnbondingMinTime, + Commission: bv.Commission, } return nil } @@ -254,18 +227,14 @@ func (v *Validator) UnmarshalJSON(data []byte) error { //___________________________________________________________________ // only the vitals - does not check bond height of IntraTxCounter -// nolint gocyclo - why dis fail? -func (v Validator) Equal(c2 Validator) bool { - return v.ConsPubKey.Equals(c2.ConsPubKey) && - bytes.Equal(v.OperatorAddr, c2.OperatorAddr) && - v.Status.Equal(c2.Status) && - v.Tokens.Equal(c2.Tokens) && - v.DelegatorShares.Equal(c2.DelegatorShares) && - v.Description == c2.Description && - v.Commission.Equal(c2.Commission) && - v.CommissionMax.Equal(c2.CommissionMax) && - v.CommissionChangeRate.Equal(c2.CommissionChangeRate) && - v.CommissionChangeToday.Equal(c2.CommissionChangeToday) +func (v Validator) Equal(v2 Validator) bool { + return v.ConsPubKey.Equals(v2.ConsPubKey) && + bytes.Equal(v.OperatorAddr, v2.OperatorAddr) && + v.Status.Equal(v2.Status) && + v.Tokens.Equal(v2.Tokens) && + v.DelegatorShares.Equal(v2.DelegatorShares) && + v.Description == v2.Description && + v.Commission.Equal(v2.Commission) } // return the TM validator address @@ -400,6 +369,17 @@ func (v Validator) RemoveTokens(pool Pool, tokens sdk.Dec) (Validator, Pool) { return v, pool } +// SetInitialCommission attempts to set a validator's initial commission. An +// error is returned if the commission is invalid. +func (v Validator) SetInitialCommission(commission Commission) (Validator, sdk.Error) { + if err := commission.Validate(); err != nil { + return v, err + } + + v.Commission = commission + return v, nil +} + //_________________________________________________________________________________________________________ // AddTokensFromDel adds tokens to a validator @@ -474,10 +454,10 @@ func (v Validator) GetJailed() bool { return v.Jailed } func (v Validator) GetMoniker() string { return v.Description.Moniker } func (v Validator) GetStatus() sdk.BondStatus { return v.Status } func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } -func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } +func (v Validator) GetConsPubKey() crypto.PubKey { return v.ConsPubKey } func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) } func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } func (v Validator) GetTokens() sdk.Dec { return v.Tokens } -func (v Validator) GetCommission() sdk.Dec { return v.Commission } +func (v Validator) GetCommission() sdk.Dec { return v.Commission.Rate } func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } func (v Validator) GetBondHeight() int64 { return v.BondHeight } diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index eceffbad39..de9e184804 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -274,3 +274,37 @@ func TestValidatorMarshalUnmarshalJSON(t *testing.T) { assert.NoError(t, err) assert.Equal(t, validator, *got) } + +func TestValidatorSetInitialCommission(t *testing.T) { + val := NewValidator(addr1, pk1, Description{}) + testCases := []struct { + validator Validator + commission Commission + expectedErr bool + }{ + {val, NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), false}, + {val, NewCommission(sdk.ZeroDec(), sdk.NewDecWithPrec(-1, 1), sdk.ZeroDec()), true}, + {val, NewCommission(sdk.ZeroDec(), sdk.NewDec(15000000000), sdk.ZeroDec()), true}, + {val, NewCommission(sdk.NewDecWithPrec(-1, 1), sdk.ZeroDec(), sdk.ZeroDec()), true}, + {val, NewCommission(sdk.NewDecWithPrec(2, 1), sdk.NewDecWithPrec(1, 1), sdk.ZeroDec()), true}, + {val, NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(-1, 1)), true}, + {val, NewCommission(sdk.ZeroDec(), sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(2, 1)), true}, + } + + for i, tc := range testCases { + val, err := tc.validator.SetInitialCommission(tc.commission) + + if tc.expectedErr { + require.Error(t, err, + "expected error for test case #%d with commission: %s", i, tc.commission, + ) + } else { + require.NoError(t, err, + "unexpected error for test case #%d with commission: %s", i, tc.commission, + ) + require.Equal(t, tc.commission, val.Commission, + "invalid validator commission for test case #%d with commission: %s", i, tc.commission, + ) + } + } +} From d3146bf06d30f72e63b239ff4d07381b01195a33 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 25 Sep 2018 18:02:22 -0400 Subject: [PATCH 54/99] ... --- types/stake.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/stake.go b/types/stake.go index e794ea7349..5a8a4fd435 100644 --- a/types/stake.go +++ b/types/stake.go @@ -45,6 +45,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 } From 4929b022ceb0ac1f4ec5cd6f1c7835e4c139f7b2 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 25 Sep 2018 19:59:46 -0400 Subject: [PATCH 55/99] mini-fix --- x/stake/keeper/validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 9acdb67644..84a82dba5f 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -695,7 +695,7 @@ func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, validator types.Valid validator.Commission.UpdateTime = blockTime k.SetValidator(ctx, validator) - k.OnValidatorCommissionChange(ctx, addr) + k.OnValidatorCommissionChange(ctx, validator.OperatorAddr) return nil } From 956566d5d1a9f130edf611ff5404ab288994a687 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 27 Sep 2018 23:04:37 -0400 Subject: [PATCH 56/99] proser --- x/distribution/keeper/allocation.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 8cc61dcad5..4174f8b17a 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -10,8 +10,8 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) - proserValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) - proposerDist := k.GetValidatorDistInfo(ctx, proserValidator.GetOperator()) + proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) + proposerDist := k.GetValidatorDistInfo(ctx, proposerValidator.GetOperator()) // get the fees which have been getting collected through all the // transactions in the block @@ -26,8 +26,8 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { proposerReward := feesCollectedDec.Mul(proposerMultiplier) // apply commission - commission := proposerReward.Mul(proserValidator.GetCommission()) - remaining := proposerReward.Mul(sdk.OneDec().Sub(proserValidator.GetCommission())) + commission := proposerReward.Mul(proposerValidator.GetCommission()) + remaining := proposerReward.Mul(sdk.OneDec().Sub(proposerValidator.GetCommission())) proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission) proposerDist.Pool = proposerDist.Pool.Plus(remaining) From 60a35413805de573adf0baf33e3677cc9195fa8e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 28 Sep 2018 03:29:52 -0400 Subject: [PATCH 57/99] major debugs --- cmd/gaia/app/app.go | 2 +- x/distribution/client/cli/tx.go | 4 ++-- x/distribution/keeper/allocation.go | 10 ++++++++++ x/distribution/keeper/hooks.go | 3 +++ x/distribution/keeper/keeper.go | 2 -- x/distribution/keeper/key.go | 8 ++++---- x/distribution/keeper/validator.go | 2 +- x/distribution/types/delegator_info.go | 4 ++++ x/distribution/types/validator_info.go | 4 ++++ x/stake/genesis.go | 7 +++++-- x/stake/keeper/delegation.go | 1 - 11 files changed, 34 insertions(+), 13 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index ad9330ba9b..749588c437 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -168,7 +168,7 @@ func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.R validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) // distribute rewards - distr.EndBlocker(ctx, app.distrKeeper) + //distr.EndBlocker(ctx, app.distrKeeper) // Add these new validators to the addr -> pubkey map. app.slashingKeeper.AddValidators(ctx, validatorUpdates) diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index 2cf293d89d..d3fa22954a 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -75,7 +75,7 @@ func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command { } // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) + return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg}) }, } cmd.Flags().String(flagOnlyFromValidator, "", "only withdraw from this validator address (in bech)") @@ -110,7 +110,7 @@ func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command { msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) // build and sign the transaction, then broadcast to Tendermint - return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg}) + return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg}) }, } return cmd diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 4174f8b17a..03742fdac9 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -1,22 +1,27 @@ 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) { + fmt.Println("wackydebugoutput AllocateFees 0") // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) proposerDist := k.GetValidatorDistInfo(ctx, proposerValidator.GetOperator()) + fmt.Println("wackydebugoutput AllocateFees 1") // get the fees which have been getting collected through all the // transactions in the block feesCollected := k.feeCollectionKeeper.GetCollectedFees(ctx) feesCollectedDec := types.NewDecCoins(feesCollected) + fmt.Println("wackydebugoutput AllocateFees 2") // allocated rewards to proposer bondedTokens := k.stakeKeeper.TotalPower(ctx) @@ -24,25 +29,30 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( sumPowerPrecommitValidators).Quo(bondedTokens)) proposerReward := feesCollectedDec.Mul(proposerMultiplier) + fmt.Println("wackydebugoutput AllocateFees 3") // apply commission commission := proposerReward.Mul(proposerValidator.GetCommission()) remaining := proposerReward.Mul(sdk.OneDec().Sub(proposerValidator.GetCommission())) proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission) proposerDist.Pool = proposerDist.Pool.Plus(remaining) + fmt.Println("wackydebugoutput AllocateFees 4") // allocate community funding communityTax := k.GetCommunityTax(ctx) communityFunding := feesCollectedDec.Mul(communityTax) feePool := k.GetFeePool(ctx) feePool.CommunityPool = feePool.CommunityPool.Plus(communityFunding) + fmt.Println("wackydebugoutput AllocateFees 5") // set the global pool within the distribution module poolReceived := feesCollectedDec.Mul(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) feePool.Pool = feePool.Pool.Plus(poolReceived) + fmt.Println("wackydebugoutput AllocateFees 0") k.SetValidatorDistInfo(ctx, proposerDist) k.SetFeePool(ctx, feePool) + fmt.Println("wackydebugoutput AllocateFees 6") // clear the now distributed fees k.feeCollectionKeeper.ClearCollectedFees(ctx) diff --git a/x/distribution/keeper/hooks.go b/x/distribution/keeper/hooks.go index f13daf03af..d503d54fb2 100644 --- a/x/distribution/keeper/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -1,6 +1,8 @@ package keeper import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) @@ -41,6 +43,7 @@ func (k Keeper) onDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, WithdrawalHeight: ctx.BlockHeight(), } k.SetDelegatorDistInfo(ctx, ddi) + ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("ddi created: %v", ddi)) } // Withdrawal all validator rewards diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 31ce345b22..0803d2493a 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -46,12 +46,10 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ps params.Setter, ck ty // 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 } diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index 771343f017..6162baf6dc 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -6,10 +6,10 @@ import ( // keys/key-prefixes var ( - FeePoolKey = []byte{0x00} // key for global distribution state - ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution - DelegatorDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution - DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info + FeePoolKey = []byte{0x01} // key for global distribution state + ValidatorDistInfoKey = []byte{0x02} // prefix for each key to a validator distribution + DelegatorDistInfoKey = []byte{0x03} // prefix for each key to a delegation distribution + DelegatorWithdrawInfoKey = []byte{0x04} // prefix for each key to a delegator withdraw info // transient ProposerKey = []byte{0x00} // key for storing the proposer operator address diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 0b58ca68c9..45ff70fd96 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -13,7 +13,7 @@ func (k Keeper) GetValidatorDistInfo(ctx sdk.Context, b := store.Get(GetValidatorDistInfoKey(operatorAddr)) if b == nil { - panic("Stored delegation-distribution info should not have been nil") + panic("Stored validator-distribution info should not have been nil") } k.cdc.MustUnmarshalBinary(b, &vdi) diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index 4bb02e20c5..608ef68d44 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -14,6 +14,10 @@ func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, delegatorShares, commissionRate sdk.Dec) (DelegatorDistInfo, FeePool, DecCoins) { + if vi.DelAccum.Accum.IsZero() { + return di, fp, DecCoins{} + } + vi.UpdateTotalDelAccum(height, totalDelShares) vi, fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 7c41b7e50f..1ea5fc27e7 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -26,6 +26,10 @@ func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBo fp.UpdateTotalValAccum(height, totalBonded) + if fp.ValAccum.Accum.IsZero() { + return vi, fp + } + // update the validators pool blocks := height - vi.FeePoolWithdrawalHeight vi.FeePoolWithdrawalHeight = height diff --git a/x/stake/genesis.go b/x/stake/genesis.go index 58b7ed1b4f..cddb3fb57a 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -38,10 +38,13 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ if validator.Status == sdk.Bonded { keeper.SetValidatorBondedIndex(ctx, validator) } + + 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) } keeper.UpdateBondedValidatorsFull(ctx) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index cc46646a73..888fe15701 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -336,7 +336,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 } From 7ab02aed7638a482590bf5cd13820af60888c026 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 28 Sep 2018 04:02:07 -0400 Subject: [PATCH 58/99] lcd tests to include proposer --- client/lcd/test_helpers.go | 12 +++++++++++- cmd/gaia/app/app.go | 4 ++-- x/distribution/abci_app.go | 3 +++ x/distribution/keeper/allocation.go | 9 +-------- x/distribution/keeper/delegation.go | 10 ++++++++-- x/distribution/keeper/keeper.go | 8 ++++---- x/distribution/keeper/key.go | 8 ++++---- x/distribution/keeper/validator.go | 5 ++++- 8 files changed, 37 insertions(+), 22 deletions(-) diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index 3f60138224..24a5b94491 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -139,7 +139,17 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress panic("InitializeTestLCD must use at least one validator") } - for i := 1; i < nValidators; i++ { + // add the priv validator (actual node) to genesis validators + genDoc.Validators = append(genDoc.Validators, + tmtypes.GenesisValidator{ + PubKey: privVal.PubKey, + Power: 1, + Name: "val", + }, + ) + + // then add some randoms + for i := 2; i < nValidators; i++ { genDoc.Validators = append(genDoc.Validators, tmtypes.GenesisValidator{ PubKey: ed25519.GenPrivKey().PubKey(), diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 749588c437..9c07f895ed 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -98,7 +98,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams) app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace)) - app.distrKeeper = distr.NewKeeper(app.cdc, app.keyDistr, app.tkeyStake, + app.distrKeeper = distr.NewKeeper(app.cdc, app.keyDistr, app.tkeyDistr, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.feeCollectionKeeper, app.RegisterCodespace(stake.DefaultCodespace)) app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, @@ -168,7 +168,7 @@ func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.R validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) // distribute rewards - //distr.EndBlocker(ctx, app.distrKeeper) + distr.EndBlocker(ctx, app.distrKeeper) // Add these new validators to the addr -> pubkey map. app.slashingKeeper.AddValidators(ctx, validatorUpdates) diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index 648d70a5dc..57c10d013b 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -15,5 +15,8 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) // allocate fees func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + if ctx.BlockHeight() < 2 { + return + } k.AllocateFees(ctx) } diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 03742fdac9..4a2d820036 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -9,19 +9,17 @@ import ( // Allocate fees handles distribution of the collected fees func (k Keeper) AllocateFees(ctx sdk.Context) { - fmt.Println("wackydebugoutput AllocateFees 0") + ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("allocation height: %v", ctx.BlockHeight())) // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) proposerDist := k.GetValidatorDistInfo(ctx, proposerValidator.GetOperator()) - fmt.Println("wackydebugoutput AllocateFees 1") // get the fees which have been getting collected through all the // transactions in the block feesCollected := k.feeCollectionKeeper.GetCollectedFees(ctx) feesCollectedDec := types.NewDecCoins(feesCollected) - fmt.Println("wackydebugoutput AllocateFees 2") // allocated rewards to proposer bondedTokens := k.stakeKeeper.TotalPower(ctx) @@ -29,30 +27,25 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( sumPowerPrecommitValidators).Quo(bondedTokens)) proposerReward := feesCollectedDec.Mul(proposerMultiplier) - fmt.Println("wackydebugoutput AllocateFees 3") // apply commission commission := proposerReward.Mul(proposerValidator.GetCommission()) remaining := proposerReward.Mul(sdk.OneDec().Sub(proposerValidator.GetCommission())) proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission) proposerDist.Pool = proposerDist.Pool.Plus(remaining) - fmt.Println("wackydebugoutput AllocateFees 4") // allocate community funding communityTax := k.GetCommunityTax(ctx) communityFunding := feesCollectedDec.Mul(communityTax) feePool := k.GetFeePool(ctx) feePool.CommunityPool = feePool.CommunityPool.Plus(communityFunding) - fmt.Println("wackydebugoutput AllocateFees 5") // set the global pool within the distribution module poolReceived := feesCollectedDec.Mul(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) feePool.Pool = feePool.Pool.Plus(poolReceived) - fmt.Println("wackydebugoutput AllocateFees 0") k.SetValidatorDistInfo(ctx, proposerDist) k.SetFeePool(ctx, feePool) - fmt.Println("wackydebugoutput AllocateFees 6") // clear the now distributed fees k.feeCollectionKeeper.ClearCollectedFees(ctx) diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 34caa5c1a9..6aa0c4ee57 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -79,7 +79,10 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA k.SetFeePool(ctx, feePool) withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr) - k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) + _, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) + if err != nil { + panic(err) + } } //___________________________________________________________________________________________ @@ -89,7 +92,10 @@ func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr sdk. height := ctx.BlockHeight() withdraw := k.GetDelegatorRewardsAll(ctx, delegatorAddr, height) withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr) - k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) + _, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) + if err != nil { + panic(err) + } } // return all rewards for all delegations of a delegator diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 0803d2493a..e49793ddcd 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -65,9 +65,9 @@ func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.FeePool) { // set the proposer public key for this block func (k Keeper) GetProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress) { - store := ctx.KVStore(k.storeKey) + tstore := ctx.KVStore(k.storeTKey) - b := store.Get(ProposerKey) + b := tstore.Get(ProposerKey) if b == nil { panic("Stored fee pool should not have been nil") } @@ -78,9 +78,9 @@ func (k Keeper) GetProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress) // get the proposer public key for this block func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { - store := ctx.KVStore(k.storeKey) + tstore := ctx.KVStore(k.storeTKey) b := k.cdc.MustMarshalBinary(consAddr) - store.Set(ProposerKey, b) + tstore.Set(ProposerKey, b) } //______________________________________________________________________ diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index 6162baf6dc..771343f017 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -6,10 +6,10 @@ import ( // keys/key-prefixes var ( - FeePoolKey = []byte{0x01} // key for global distribution state - ValidatorDistInfoKey = []byte{0x02} // prefix for each key to a validator distribution - DelegatorDistInfoKey = []byte{0x03} // prefix for each key to a delegation distribution - DelegatorWithdrawInfoKey = []byte{0x04} // prefix for each key to a delegator withdraw info + FeePoolKey = []byte{0x00} // key for global distribution state + ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution + DelegatorDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution + DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info // transient ProposerKey = []byte{0x00} // key for storing the proposer operator address diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 45ff70fd96..baeb6ab311 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -53,5 +53,8 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.Va k.SetFeePool(ctx, feePool) withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, accAddr) - k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) + _, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) + if err != nil { + panic(err) + } } From 733b616c8ce0872a0179a70c1997e64dae25a092 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 28 Sep 2018 04:15:03 -0400 Subject: [PATCH 59/99] disable endblock for lcd --- client/lcd/test_helpers.go | 18 +++++++++--------- cmd/gaia/app/app.go | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index 24a5b94491..f82880fd78 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -139,17 +139,17 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress panic("InitializeTestLCD must use at least one validator") } - // add the priv validator (actual node) to genesis validators - genDoc.Validators = append(genDoc.Validators, - tmtypes.GenesisValidator{ - PubKey: privVal.PubKey, - Power: 1, - Name: "val", - }, - ) + //// add the priv validator (actual node) to genesis validators + //genDoc.Validators = append(genDoc.Validators, + //tmtypes.GenesisValidator{ + //PubKey: privVal.PubKey, + //Power: 1, + //Name: "val", + //}, + //) // then add some randoms - for i := 2; i < nValidators; i++ { + for i := 1; i < nValidators; i++ { genDoc.Validators = append(genDoc.Validators, tmtypes.GenesisValidator{ PubKey: ed25519.GenPrivKey().PubKey(), diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 9c07f895ed..5f5b542ef8 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -168,7 +168,7 @@ func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.R validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) // distribute rewards - distr.EndBlocker(ctx, app.distrKeeper) + //distr.EndBlocker(ctx, app.distrKeeper) // Add these new validators to the addr -> pubkey map. app.slashingKeeper.AddValidators(ctx, validatorUpdates) From e223eadb363302393d792d0e8f3b822f4913d102 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 28 Sep 2018 19:04:04 -0400 Subject: [PATCH 60/99] types msg tests --- x/distribution/types/msg_test.go | 93 +++++++++++++++++++++ x/distribution/types/test_utils.go | 27 ++++++ x/distribution/types/validator_info_test.go | 9 ++ 3 files changed, 129 insertions(+) create mode 100644 x/distribution/types/msg_test.go create mode 100644 x/distribution/types/test_utils.go create mode 100644 x/distribution/types/validator_info_test.go diff --git a/x/distribution/types/msg_test.go b/x/distribution/types/msg_test.go new file mode 100644 index 0000000000..24af43b2ec --- /dev/null +++ b/x/distribution/types/msg_test.go @@ -0,0 +1,93 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// test ValidateBasic for MsgCreateValidator +func TestMsgSetWithdrawAddress(t *testing.T) { + tests := []struct { + delegatorAddr sdk.AccAddress + withdrawAddr sdk.AccAddress + expectPass bool + }{ + {delAddr1, delAddr2, true}, + {delAddr1, delAddr1, true}, + {emptyDelAddr, delAddr1, false}, + {delAddr1, emptyDelAddr, false}, + {emptyDelAddr, emptyDelAddr, false}, + } + + for _, tc := range tests { + msg := NewMsgSetWithdrawAddress(tc.delegatorAddr, tc.withdrawAddr) + if tc.expectPass { + require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) + } else { + require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name) + } + } +} + +// test ValidateBasic for MsgEditValidator +func TestMsgWithdrawDelegatorReward(t *testing.T) { + tests := []struct { + delegatorAddr sdk.AccAddress + validatorAddr sdk.ValAddress + expectPass bool + }{ + {delAddr1, valAddr1, true}, + {emptyDelAddr, valAddr1, false}, + {delAddr1, emptyValAddr, false}, + {emptyDelAddr, emptyValAddr, false}, + } + for _, tc := range tests { + msg := NewMsgWithdrawDelegatorReward(tc.delegatorAddr, tc.validatorAddr) + if tc.expectPass { + require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) + } else { + require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name) + } + } +} + +// test ValidateBasic and GetSigners for MsgCreateValidatorOnBehalfOf +func TestMsgWithdrawDelegatorRewardsAll(t *testing.T) { + tests := []struct { + delegatorAddr sdk.AccAddress + expectPass bool + }{ + {delAddr, true}, + {emptyDelAddr, false}, + } + for _, tc := range tests { + msg := NewMsgWithdrawDelegatorRewardsAll(tc.delegatorAddr) + if tc.expectPass { + require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) + } else { + require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name) + } + } +} + +// test ValidateBasic for MsgDelegate +func TestMsgWithdrawValidatorRewardsAll(t *testing.T) { + tests := []struct { + validatorAddr sdk.ValAddress + expectPass bool + }{ + {valAddr1, true}, + {emptyValAddr, false}, + } + for _, tc := range tests { + msg := NewMsgWithdrawValidatorRewardsAll(tc.validatorAddr) + if tc.expectPass { + require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) + } else { + require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name) + } + } +} diff --git a/x/distribution/types/test_utils.go b/x/distribution/types/test_utils.go new file mode 100644 index 0000000000..3ea78cd792 --- /dev/null +++ b/x/distribution/types/test_utils.go @@ -0,0 +1,27 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" +) + +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()) + emptyDelAddr sdk.AccAddress + + 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()) + emptyValAddr sdk.ValAddress + + emptyPubkey crypto.PubKey +) diff --git a/x/distribution/types/validator_info_test.go b/x/distribution/types/validator_info_test.go new file mode 100644 index 0000000000..a18464be14 --- /dev/null +++ b/x/distribution/types/validator_info_test.go @@ -0,0 +1,9 @@ +package types + +import "testing" + +func TestTakeFeePoolRewards(t *testing.T) { +} + +func WithdrawCommission(t *testing.T) { +} From 064f8b0b5847f297accb45e12b2dd7375b6792d2 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 28 Sep 2018 19:23:01 -0400 Subject: [PATCH 61/99] dec coin tests --- x/distribution/types/codec.go | 2 +- x/distribution/types/dec_coin_test.go | 57 +++++++++++++++++++++ x/distribution/types/delegator_info_test.go | 6 +++ x/distribution/types/fee_pool_test.go | 6 +++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 x/distribution/types/dec_coin_test.go create mode 100644 x/distribution/types/delegator_info_test.go create mode 100644 x/distribution/types/fee_pool_test.go diff --git a/x/distribution/types/codec.go b/x/distribution/types/codec.go index edb121d20d..55d7c6cdae 100644 --- a/x/distribution/types/codec.go +++ b/x/distribution/types/codec.go @@ -12,7 +12,7 @@ func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(MsgSetWithdrawAddress{}, "cosmos-sdk/MsgModifyWithdrawAddress", nil) } -// generic sealed codec to be used throughout sdk +// generic sealed codec to be used throught module var MsgCdc *codec.Codec func init() { diff --git a/x/distribution/types/dec_coin_test.go b/x/distribution/types/dec_coin_test.go new file mode 100644 index 0000000000..ee8aa30c0d --- /dev/null +++ b/x/distribution/types/dec_coin_test.go @@ -0,0 +1,57 @@ +package types + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPlusDecCoin(t *testing.T) { + decCoinA1 := DecCoin("A", sdk.NewDecWithPrec(11, 1)) + decCoinA2 := DecCoin("A", sdk.NewDecWithPrec(22, 1)) + decCoinB1 := DecCoin("B", sdk.NewDecWithPrec(11, 1)) + decCoinC1 := DecCoin("C", sdk.NewDecWithPrec(11, 1)) + decCoinCn4 := DecCoin("C", sdk.NewDecWithPrec(-44, 1)) + decCoinC5 := DecCoin("C", sdk.NewDecWithPrec(55, 1)) + + cases := []struct { + inputOne DecCoin + inputTwo DecCoin + expected DecCoin + }{ + {decCoinA1, decCoinA1, decCoinA2}, + {decCoinA1, decCoinB1, decCoinA1}, + {decCoinCn4, decCoinC5, decCoinC1}, + } + for tcIndex, tc := range cases { + res := tc.inputOne.Plus(tc.inputTwo) + require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex) + } +} + +func TestPlusCoins(t *testing.T) { + one := sdk.NewDec(1) + zero := sdk.NewDec(0) + negone := sdk.NewDec(-1) + two := sdk.NewDec(2) + + cases := []struct { + inputOne DecCoins + inputTwo DecCoins + expected DecCoins + }{ + {DecCoins{{"A", one}, {"B", one}}, DecCoins{{"A", one}, {"B", one}}, DecCoins{{"A", two}, {"B", two}}}, + {DecCoins{{"A", zero}, {"B", one}}, DecCoins{{"A", zero}, {"B", zero}}, DecCoins{{"B", one}}}, + {DecCoins{{"A", zero}, {"B", zero}}, DecCoins{{"A", zero}, {"B", zero}}, DecCoins(nil)}, + {DecCoins{{"A", one}, {"B", zero}}, DecCoins{{"A", negone}, {"B", zero}}, DecCoins(nil)}, + {DecCoins{{"A", negone}, {"B", zero}}, DecCoins{{"A", zero}, {"B", zero}}, DecCoins{{"A", negone}}}, + } + + for tcIndex, tc := range cases { + res := tc.inputOne.Plus(tc.inputTwo) + assert.True(t, res.IsValid()) + require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex) + } +} diff --git a/x/distribution/types/delegator_info_test.go b/x/distribution/types/delegator_info_test.go new file mode 100644 index 0000000000..af89f40ca0 --- /dev/null +++ b/x/distribution/types/delegator_info_test.go @@ -0,0 +1,6 @@ +package types + +import "testing" + +func TestWithdrawRewards(t *testing.T) { +} diff --git a/x/distribution/types/fee_pool_test.go b/x/distribution/types/fee_pool_test.go new file mode 100644 index 0000000000..e20d283b8d --- /dev/null +++ b/x/distribution/types/fee_pool_test.go @@ -0,0 +1,6 @@ +package types + +import "testing" + +func TestTotalAccumUpdate(t *testing.T) { +} From 16f5d69329fef9714c98de23f74585d81082e76b Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 28 Sep 2018 19:32:42 -0400 Subject: [PATCH 62/99] types fee pool test --- x/distribution/types/fee_pool_test.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/x/distribution/types/fee_pool_test.go b/x/distribution/types/fee_pool_test.go index e20d283b8d..fc14cb153a 100644 --- a/x/distribution/types/fee_pool_test.go +++ b/x/distribution/types/fee_pool_test.go @@ -1,6 +1,19 @@ package types -import "testing" +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) func TestTotalAccumUpdate(t *testing.T) { + + ta := NewTotalAccum(0) + + ta.Update(5, sdk.NewDec(3)) + require.True(DecEq(t, sdk.NewDec(15), ta.Accum)) + + ta.Update(8, sdk.NewDec(2)) + require.True(DecEq(t, sdk.NewDec(21), ta.Accum)) } From dcf0ddaa0334c72d4a98807832d50408114c5ed5 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 28 Sep 2018 20:55:22 -0400 Subject: [PATCH 63/99] ... --- x/distribution/types/validator_info.go | 1 - 1 file changed, 1 deletion(-) diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 1ea5fc27e7..4a17e22ae4 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -19,7 +19,6 @@ func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares sdk return vi } -// XXX TODO Update dec logic // move any available accumulated fees in the FeePool to the validator's pool func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBonded, vdTokens, commissionRate sdk.Dec) (ValidatorDistInfo, FeePool) { From 1e74da1abe20c961e2c86b8f292b615fb94f1720 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 4 Oct 2018 03:00:24 -0400 Subject: [PATCH 64/99] validator_info tests --- types/decimal.go | 4 +- x/distribution/keeper/allocation.go | 10 +-- x/distribution/types/dec_coin.go | 50 +++++++++++-- x/distribution/types/dec_coin_test.go | 14 ++-- x/distribution/types/delegator_info.go | 14 +++- x/distribution/types/fee_pool.go | 6 +- x/distribution/types/fee_pool_test.go | 19 +++-- x/distribution/types/msg_test.go | 26 +++---- x/distribution/types/validator_info.go | 24 +++++-- x/distribution/types/validator_info_test.go | 80 ++++++++++++++++++++- 10 files changed, 197 insertions(+), 50 deletions(-) diff --git a/types/decimal.go b/types/decimal.go index 13a8a26c15..a4d1e40ed3 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -462,6 +462,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() } diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 4a2d820036..3c4bd3971b 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -26,22 +26,22 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { sumPowerPrecommitValidators := sdk.NewDec(1) // XXX TODO actually calculate this proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( sumPowerPrecommitValidators).Quo(bondedTokens)) - proposerReward := feesCollectedDec.Mul(proposerMultiplier) + proposerReward := feesCollectedDec.MulDec(proposerMultiplier) // apply commission - commission := proposerReward.Mul(proposerValidator.GetCommission()) - remaining := proposerReward.Mul(sdk.OneDec().Sub(proposerValidator.GetCommission())) + commission := proposerReward.MulDec(proposerValidator.GetCommission()) + remaining := proposerReward.MulDec(sdk.OneDec().Sub(proposerValidator.GetCommission())) proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission) proposerDist.Pool = proposerDist.Pool.Plus(remaining) // allocate community funding communityTax := k.GetCommunityTax(ctx) - communityFunding := feesCollectedDec.Mul(communityTax) + communityFunding := feesCollectedDec.MulDec(communityTax) feePool := k.GetFeePool(ctx) feePool.CommunityPool = feePool.CommunityPool.Plus(communityFunding) // set the global pool within the distribution module - poolReceived := feesCollectedDec.Mul(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) + poolReceived := feesCollectedDec.MulDec(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) feePool.Pool = feePool.Pool.Plus(poolReceived) k.SetValidatorDistInfo(ctx, proposerDist) diff --git a/x/distribution/types/dec_coin.go b/x/distribution/types/dec_coin.go index eef4f78a63..df94d864db 100644 --- a/x/distribution/types/dec_coin.go +++ b/x/distribution/types/dec_coin.go @@ -27,6 +27,14 @@ func (coin DecCoin) Plus(coinB DecCoin) DecCoin { return DecCoin{coin.Denom, coin.Amount.Add(coinB.Amount)} } +// Subtracts amounts of two coins with same denom +func (coin DecCoin) Minus(coinB DecCoin) DecCoin { + if !(coin.Denom == coinB.Denom) { + return coin + } + return DecCoin{coin.Denom, coin.Amount.Sub(coinB.Amount)} +} + // return the decimal coins with trunctated decimals func (coin DecCoin) TruncateDecimal() sdk.Coin { return sdk.NewCoin(coin.Denom, coin.Amount.TruncateInt()) @@ -89,15 +97,45 @@ func (coins DecCoins) Plus(coinsB DecCoins) DecCoins { } } -// multiply all the coins by a multiple -func (coins DecCoins) Mul(multiple sdk.Dec) DecCoins { - products := make([]DecCoin, len(coins)) +// Negative returns a set of coins with all amount negative +func (coins DecCoins) Negative() DecCoins { + res := make([]DecCoin, 0, len(coins)) + for _, coin := range coins { + res = append(res, DecCoin{ + Denom: coin.Denom, + Amount: coin.Amount.Neg(), + }) + } + return res +} + +// Minus subtracts a set of coins from another (adds the inverse) +func (coins DecCoins) Minus(coinsB DecCoins) DecCoins { + return coins.Plus(coinsB.Negative()) +} + +// multiply all the coins by a decimal +func (coins DecCoins) MulDec(d sdk.Dec) DecCoins { + res := make([]DecCoin, len(coins)) for i, coin := range coins { product := DecCoin{ Denom: coin.Denom, - Amount: coin.Amount.Mul(multiple), + Amount: coin.Amount.Mul(d), } - products[i] = product + res[i] = product } - return products + return res +} + +// divide all the coins by a multiple +func (coins DecCoins) QuoDec(d sdk.Dec) DecCoins { + res := make([]DecCoin, len(coins)) + for i, coin := range coins { + quotient := DecCoin{ + Denom: coin.Denom, + Amount: coin.Amount.Quo(d), + } + res[i] = quotient + } + return res } diff --git a/x/distribution/types/dec_coin_test.go b/x/distribution/types/dec_coin_test.go index ee8aa30c0d..61de361ca9 100644 --- a/x/distribution/types/dec_coin_test.go +++ b/x/distribution/types/dec_coin_test.go @@ -4,17 +4,16 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestPlusDecCoin(t *testing.T) { - decCoinA1 := DecCoin("A", sdk.NewDecWithPrec(11, 1)) - decCoinA2 := DecCoin("A", sdk.NewDecWithPrec(22, 1)) - decCoinB1 := DecCoin("B", sdk.NewDecWithPrec(11, 1)) - decCoinC1 := DecCoin("C", sdk.NewDecWithPrec(11, 1)) - decCoinCn4 := DecCoin("C", sdk.NewDecWithPrec(-44, 1)) - decCoinC5 := DecCoin("C", sdk.NewDecWithPrec(55, 1)) + decCoinA1 := DecCoin{"A", sdk.NewDecWithPrec(11, 1)} + decCoinA2 := DecCoin{"A", sdk.NewDecWithPrec(22, 1)} + decCoinB1 := DecCoin{"B", sdk.NewDecWithPrec(11, 1)} + decCoinC1 := DecCoin{"C", sdk.NewDecWithPrec(11, 1)} + decCoinCn4 := DecCoin{"C", sdk.NewDecWithPrec(-44, 1)} + decCoinC5 := DecCoin{"C", sdk.NewDecWithPrec(55, 1)} cases := []struct { inputOne DecCoin @@ -51,7 +50,6 @@ func TestPlusCoins(t *testing.T) { for tcIndex, tc := range cases { res := tc.inputOne.Plus(tc.inputTwo) - assert.True(t, res.IsValid()) require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex) } } diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index 608ef68d44..e083cf2d4c 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -9,6 +9,16 @@ type DelegatorDistInfo struct { WithdrawalHeight int64 `json:"withdrawal_height"` // last time this delegation withdrew rewards } +func NewDelegatorDistInfo(delegatorAddr sdk.AccAddress, valOperatorAddr sdk.ValAddress, + currentHeight int64) DelegatorDistInfo { + + return DelegatorDistInfo{ + DelegatorAddr: delegatorAddr, + ValOperatorAddr: valOperatorAddr, + WithdrawalHeight: currentHeight, + } +} + // withdraw rewards from delegator func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, delegatorShares, @@ -24,8 +34,8 @@ func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, blocks := height - di.WithdrawalHeight di.WithdrawalHeight = height accum := delegatorShares.Mul(sdk.NewDec(blocks)) - withdrawalTokens := vi.Pool.Mul(accum.Quo(vi.DelAccum.Accum)) - remainingTokens := vi.Pool.Mul(sdk.OneDec().Sub(accum.Quo(vi.DelAccum.Accum))) + withdrawalTokens := vi.Pool.MulDec(accum.Quo(vi.DelAccum.Accum)) + remainingTokens := vi.Pool.MulDec(sdk.OneDec().Sub(accum.Quo(vi.DelAccum.Accum))) vi.Pool = remainingTokens vi.DelAccum.Accum = vi.DelAccum.Accum.Sub(accum) diff --git a/x/distribution/types/fee_pool.go b/x/distribution/types/fee_pool.go index 03725d7c1d..d373e04858 100644 --- a/x/distribution/types/fee_pool.go +++ b/x/distribution/types/fee_pool.go @@ -1,6 +1,8 @@ package types -import sdk "github.com/cosmos/cosmos-sdk/types" +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) // total accumulation tracker type TotalAccum struct { @@ -29,7 +31,7 @@ func (ta TotalAccum) Update(height int64, accumCreatedPerBlock sdk.Dec) TotalAcc type FeePool struct { ValAccum TotalAccum `json:"val_accum"` // total valdator accum held by validators Pool DecCoins `json:"pool"` // funds for all validators which have yet to be withdrawn - CommunityPool DecCoins `json:"community_pool"` // pool for community funds yet to be spent} + CommunityPool DecCoins `json:"community_pool"` // pool for community funds yet to be spent } // update total validator accumulation factor diff --git a/x/distribution/types/fee_pool_test.go b/x/distribution/types/fee_pool_test.go index fc14cb153a..1c2a804b42 100644 --- a/x/distribution/types/fee_pool_test.go +++ b/x/distribution/types/fee_pool_test.go @@ -11,9 +11,20 @@ func TestTotalAccumUpdate(t *testing.T) { ta := NewTotalAccum(0) - ta.Update(5, sdk.NewDec(3)) - require.True(DecEq(t, sdk.NewDec(15), ta.Accum)) + ta = ta.Update(5, sdk.NewDec(3)) + require.True(sdk.DecEq(t, sdk.NewDec(15), ta.Accum)) - ta.Update(8, sdk.NewDec(2)) - require.True(DecEq(t, sdk.NewDec(21), ta.Accum)) + ta = ta.Update(8, sdk.NewDec(2)) + require.True(sdk.DecEq(t, sdk.NewDec(21), ta.Accum)) +} + +func TestUpdateTotalValAccum(t *testing.T) { + + fp := InitialFeePool() + + fp = fp.UpdateTotalValAccum(5, sdk.NewDec(3)) + require.True(sdk.DecEq(t, sdk.NewDec(15), fp.ValAccum.Accum)) + + fp = fp.UpdateTotalValAccum(8, sdk.NewDec(2)) + require.True(sdk.DecEq(t, sdk.NewDec(21), fp.ValAccum.Accum)) } diff --git a/x/distribution/types/msg_test.go b/x/distribution/types/msg_test.go index 24af43b2ec..b0c0dd9eb4 100644 --- a/x/distribution/types/msg_test.go +++ b/x/distribution/types/msg_test.go @@ -22,12 +22,12 @@ func TestMsgSetWithdrawAddress(t *testing.T) { {emptyDelAddr, emptyDelAddr, false}, } - for _, tc := range tests { + for i, tc := range tests { msg := NewMsgSetWithdrawAddress(tc.delegatorAddr, tc.withdrawAddr) if tc.expectPass { - require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) + require.Nil(t, msg.ValidateBasic(), "test index: %v", i) } else { - require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name) + require.NotNil(t, msg.ValidateBasic(), "test index: %v", i) } } } @@ -44,12 +44,12 @@ func TestMsgWithdrawDelegatorReward(t *testing.T) { {delAddr1, emptyValAddr, false}, {emptyDelAddr, emptyValAddr, false}, } - for _, tc := range tests { + for i, tc := range tests { msg := NewMsgWithdrawDelegatorReward(tc.delegatorAddr, tc.validatorAddr) if tc.expectPass { - require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) + require.Nil(t, msg.ValidateBasic(), "test index: %v", i) } else { - require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name) + require.NotNil(t, msg.ValidateBasic(), "test index: %v", i) } } } @@ -60,15 +60,15 @@ func TestMsgWithdrawDelegatorRewardsAll(t *testing.T) { delegatorAddr sdk.AccAddress expectPass bool }{ - {delAddr, true}, + {delAddr1, true}, {emptyDelAddr, false}, } - for _, tc := range tests { + for i, tc := range tests { msg := NewMsgWithdrawDelegatorRewardsAll(tc.delegatorAddr) if tc.expectPass { - require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) + require.Nil(t, msg.ValidateBasic(), "test index: %v", i) } else { - require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name) + require.NotNil(t, msg.ValidateBasic(), "test index: %v", i) } } } @@ -82,12 +82,12 @@ func TestMsgWithdrawValidatorRewardsAll(t *testing.T) { {valAddr1, true}, {emptyValAddr, false}, } - for _, tc := range tests { + for i, tc := range tests { msg := NewMsgWithdrawValidatorRewardsAll(tc.validatorAddr) if tc.expectPass { - require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) + require.Nil(t, msg.ValidateBasic(), "test index: %v", i) } else { - require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name) + require.NotNil(t, msg.ValidateBasic(), "test index: %v", i) } } } diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 4a17e22ae4..e328390469 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -1,6 +1,8 @@ package types -import sdk "github.com/cosmos/cosmos-sdk/types" +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) // distribution info for a particular validator type ValidatorDistInfo struct { @@ -13,6 +15,16 @@ type ValidatorDistInfo struct { DelAccum TotalAccum `json:"del_accum"` // total proposer pool accumulation factor held by delegators } +func NewValidatorDistInfo(operatorAddr sdk.ValAddress, currentHeight int64) ValidatorDistInfo { + return ValidatorDistInfo{ + OperatorAddr: operatorAddr, + FeePoolWithdrawalHeight: currentHeight, + Pool: DecCoins{}, + PoolCommission: DecCoins{}, + DelAccum: NewTotalAccum(currentHeight), + } +} + // update total delegator accumululation func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares sdk.Dec) ValidatorDistInfo { vi.DelAccum = vi.DelAccum.Update(height, totalDelShares) @@ -23,7 +35,7 @@ func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares sdk func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBonded, vdTokens, commissionRate sdk.Dec) (ValidatorDistInfo, FeePool) { - fp.UpdateTotalValAccum(height, totalBonded) + fp = fp.UpdateTotalValAccum(height, totalBonded) if fp.ValAccum.Accum.IsZero() { return vi, fp @@ -33,11 +45,11 @@ func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBo blocks := height - vi.FeePoolWithdrawalHeight vi.FeePoolWithdrawalHeight = height accum := sdk.NewDec(blocks).Mul(vdTokens) - withdrawalTokens := fp.Pool.Mul(accum.Quo(fp.ValAccum.Accum)) - remainingTokens := fp.Pool.Mul(sdk.OneDec().Sub(accum.Quo(fp.ValAccum.Accum))) + withdrawalTokens := fp.Pool.MulDec(accum).QuoDec(fp.ValAccum.Accum) + remainingTokens := fp.Pool.Minus(withdrawalTokens) - commission := withdrawalTokens.Mul(commissionRate) - afterCommission := withdrawalTokens.Mul(sdk.OneDec().Sub(commissionRate)) + commission := withdrawalTokens.MulDec(commissionRate) + afterCommission := withdrawalTokens.MulDec(sdk.OneDec().Sub(commissionRate)) fp.ValAccum.Accum = fp.ValAccum.Accum.Sub(accum) fp.Pool = remainingTokens diff --git a/x/distribution/types/validator_info_test.go b/x/distribution/types/validator_info_test.go index a18464be14..44c5e5daa9 100644 --- a/x/distribution/types/validator_info_test.go +++ b/x/distribution/types/validator_info_test.go @@ -1,9 +1,85 @@ package types -import "testing" +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) func TestTakeFeePoolRewards(t *testing.T) { + + // initialize + height := int64(0) + fp := InitialFeePool() + vi1 := NewValidatorDistInfo(valAddr1, height) + vi2 := NewValidatorDistInfo(valAddr2, height) + vi3 := NewValidatorDistInfo(valAddr3, height) + commissionRate1 := sdk.NewDecWithPrec(2, 2) + commissionRate2 := sdk.NewDecWithPrec(3, 2) + commissionRate3 := sdk.NewDecWithPrec(4, 2) + validatorTokens1 := sdk.NewDec(10) + validatorTokens2 := sdk.NewDec(40) + validatorTokens3 := sdk.NewDec(50) + totalBondedTokens := validatorTokens1.Add(validatorTokens2).Add(validatorTokens3) + + // simulate adding some stake for inflation + height = 10 + fp.Pool = DecCoins{DecCoin{"stake", sdk.NewDec(1000)}} + + vi1, fp = vi1.TakeFeePoolRewards(fp, height, totalBondedTokens, validatorTokens1, commissionRate1) + require.True(sdk.DecEq(t, sdk.NewDec(900), fp.ValAccum.Accum)) + assert.True(sdk.DecEq(t, sdk.NewDec(900), fp.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(100-2), vi1.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(2), vi1.PoolCommission[0].Amount)) + + vi2, fp = vi2.TakeFeePoolRewards(fp, height, totalBondedTokens, validatorTokens2, commissionRate2) + require.True(sdk.DecEq(t, sdk.NewDec(500), fp.ValAccum.Accum)) + assert.True(sdk.DecEq(t, sdk.NewDec(500), fp.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(400-12), vi2.Pool[0].Amount)) + assert.True(sdk.DecEq(t, vi2.PoolCommission[0].Amount, sdk.NewDec(12))) + + // add more blocks and inflation + height = 20 + fp.Pool[0].Amount = fp.Pool[0].Amount.Add(sdk.NewDec(1000)) + + vi3, fp = vi3.TakeFeePoolRewards(fp, height, totalBondedTokens, validatorTokens3, commissionRate3) + require.True(sdk.DecEq(t, sdk.NewDec(500), fp.ValAccum.Accum)) + assert.True(sdk.DecEq(t, sdk.NewDec(500), fp.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(1000-40), vi3.Pool[0].Amount)) + assert.True(sdk.DecEq(t, vi3.PoolCommission[0].Amount, sdk.NewDec(40))) } -func WithdrawCommission(t *testing.T) { +func TestWithdrawCommission(t *testing.T) { + + // initialize + height := int64(0) + fp := InitialFeePool() + vi1 := NewValidatorDistInfo(valAddr1, height) + commissionRate1 := sdk.NewDecWithPrec(2, 2) + validatorTokens1 := sdk.NewDec(10) + totalBondedTokens := validatorTokens1.Add(sdk.NewDec(90)) // validator-1 is 10% of total power + + // simulate adding some stake for inflation + height = 10 + fp.Pool = DecCoins{DecCoin{"stake", sdk.NewDec(1000)}} + + // for a more fun staring condition, have an non-withdraw update + vi1, fp = vi1.TakeFeePoolRewards(fp, height, totalBondedTokens, validatorTokens1, commissionRate1) + require.True(sdk.DecEq(t, sdk.NewDec(900), fp.ValAccum.Accum)) + assert.True(sdk.DecEq(t, sdk.NewDec(900), fp.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(100-2), vi1.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(2), vi1.PoolCommission[0].Amount)) + + // add more blocks and inflation + height = 20 + fp.Pool[0].Amount = fp.Pool[0].Amount.Add(sdk.NewDec(1000)) + + vi1, fp, commissionRecv := vi1.WithdrawCommission(fp, height, totalBondedTokens, validatorTokens1, commissionRate1) + require.True(sdk.DecEq(t, sdk.NewDec(1800), fp.ValAccum.Accum)) + assert.True(sdk.DecEq(t, sdk.NewDec(1800), fp.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(200-4), vi1.Pool[0].Amount)) + assert.Zero(t, len(vi1.PoolCommission)) + assert.True(sdk.DecEq(t, sdk.NewDec(4), commissionRecv[0].Amount)) } From 4d4de3aa0965a11b0bce7fdd277fb1ac0d70aff7 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 4 Oct 2018 03:26:02 -0400 Subject: [PATCH 65/99] delegator_dist_info tests --- x/distribution/keeper/delegation.go | 6 ++- x/distribution/types/delegator_info.go | 13 ++++-- x/distribution/types/delegator_info_test.go | 52 ++++++++++++++++++++- x/distribution/types/validator_info_test.go | 20 ++++---- 4 files changed, 73 insertions(+), 18 deletions(-) diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 6aa0c4ee57..ab5b7c0a25 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -74,10 +74,11 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA validator := k.stakeKeeper.Validator(ctx, validatorAddr) delegation := k.stakeKeeper.Delegation(ctx, delegatorAddr, validatorAddr) - delInfo, feePool, withdraw := delInfo.WithdrawRewards(feePool, valInfo, height, bondedTokens, + 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) withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr) _, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) if err != nil { @@ -113,10 +114,11 @@ func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, validator := k.stakeKeeper.Validator(ctx, valAddr) delegation := k.stakeKeeper.Delegation(ctx, delAddr, valAddr) - delInfo, feePool, diWithdraw := delInfo.WithdrawRewards(feePool, valInfo, height, bondedTokens, + 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.SetDelegatorDistInfo(ctx, delInfo) return false } diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index e083cf2d4c..911fad9c98 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -1,6 +1,8 @@ package types -import sdk "github.com/cosmos/cosmos-sdk/types" +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) // distribution info for a delegation type DelegatorDistInfo struct { @@ -22,13 +24,14 @@ func NewDelegatorDistInfo(delegatorAddr sdk.AccAddress, valOperatorAddr sdk.ValA // withdraw rewards from delegator func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, delegatorShares, - commissionRate sdk.Dec) (DelegatorDistInfo, FeePool, DecCoins) { + commissionRate sdk.Dec) (DelegatorDistInfo, ValidatorDistInfo, FeePool, DecCoins) { + + vi = vi.UpdateTotalDelAccum(height, totalDelShares) if vi.DelAccum.Accum.IsZero() { - return di, fp, DecCoins{} + return di, vi, fp, DecCoins{} } - vi.UpdateTotalDelAccum(height, totalDelShares) vi, fp = vi.TakeFeePoolRewards(fp, height, totalBonded, vdTokens, commissionRate) blocks := height - di.WithdrawalHeight @@ -40,7 +43,7 @@ func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, vi.Pool = remainingTokens vi.DelAccum.Accum = vi.DelAccum.Accum.Sub(accum) - return di, fp, withdrawalTokens + return di, vi, fp, withdrawalTokens } //_____________________________________________________________________ diff --git a/x/distribution/types/delegator_info_test.go b/x/distribution/types/delegator_info_test.go index af89f40ca0..f1bcbb4ec5 100644 --- a/x/distribution/types/delegator_info_test.go +++ b/x/distribution/types/delegator_info_test.go @@ -1,6 +1,56 @@ package types -import "testing" +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" +) func TestWithdrawRewards(t *testing.T) { + + // initialize + height := int64(0) + fp := InitialFeePool() + vi := NewValidatorDistInfo(valAddr1, height) + commissionRate := sdk.NewDecWithPrec(2, 2) + validatorTokens := sdk.NewDec(10) + validatorDelShares := sdk.NewDec(10) + totalBondedTokens := validatorTokens.Add(sdk.NewDec(90)) // validator-1 is 10% of total power + + di1 := NewDelegatorDistInfo(delAddr1, valAddr1, height) + di1Shares := sdk.NewDec(5) // this delegator has half the shares in the validator + + di2 := NewDelegatorDistInfo(delAddr2, valAddr1, height) + di2Shares := sdk.NewDec(5) + + // simulate adding some stake for inflation + height = 10 + fp.Pool = DecCoins{DecCoin{"stake", sdk.NewDec(1000)}} + + // withdraw rewards + di1, vi, fp, rewardRecv1 := di1.WithdrawRewards(fp, vi, height, totalBondedTokens, + validatorTokens, validatorDelShares, di1Shares, commissionRate) + + assert.Equal(t, height, di1.WithdrawalHeight) + assert.True(sdk.DecEq(t, sdk.NewDec(900), fp.ValAccum.Accum)) + assert.True(sdk.DecEq(t, sdk.NewDec(900), fp.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(49), vi.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(2), vi.PoolCommission[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(49), rewardRecv1[0].Amount)) + + // add more blocks and inflation + height = 20 + fp.Pool[0].Amount = fp.Pool[0].Amount.Add(sdk.NewDec(1000)) + + // withdraw rewards + di2, vi, fp, rewardRecv2 := di2.WithdrawRewards(fp, vi, height, totalBondedTokens, + validatorTokens, validatorDelShares, di2Shares, commissionRate) + + assert.Equal(t, height, di2.WithdrawalHeight) + assert.True(sdk.DecEq(t, sdk.NewDec(1800), fp.ValAccum.Accum)) + assert.True(sdk.DecEq(t, sdk.NewDec(1800), fp.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(49), vi.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(4), vi.PoolCommission[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(147), rewardRecv2[0].Amount)) } diff --git a/x/distribution/types/validator_info_test.go b/x/distribution/types/validator_info_test.go index 44c5e5daa9..da3b2c10d8 100644 --- a/x/distribution/types/validator_info_test.go +++ b/x/distribution/types/validator_info_test.go @@ -56,30 +56,30 @@ func TestWithdrawCommission(t *testing.T) { // initialize height := int64(0) fp := InitialFeePool() - vi1 := NewValidatorDistInfo(valAddr1, height) - commissionRate1 := sdk.NewDecWithPrec(2, 2) - validatorTokens1 := sdk.NewDec(10) - totalBondedTokens := validatorTokens1.Add(sdk.NewDec(90)) // validator-1 is 10% of total power + vi := NewValidatorDistInfo(valAddr1, height) + commissionRate := sdk.NewDecWithPrec(2, 2) + validatorTokens := sdk.NewDec(10) + totalBondedTokens := validatorTokens.Add(sdk.NewDec(90)) // validator-1 is 10% of total power // simulate adding some stake for inflation height = 10 fp.Pool = DecCoins{DecCoin{"stake", sdk.NewDec(1000)}} // for a more fun staring condition, have an non-withdraw update - vi1, fp = vi1.TakeFeePoolRewards(fp, height, totalBondedTokens, validatorTokens1, commissionRate1) + vi, fp = vi.TakeFeePoolRewards(fp, height, totalBondedTokens, validatorTokens, commissionRate) require.True(sdk.DecEq(t, sdk.NewDec(900), fp.ValAccum.Accum)) assert.True(sdk.DecEq(t, sdk.NewDec(900), fp.Pool[0].Amount)) - assert.True(sdk.DecEq(t, sdk.NewDec(100-2), vi1.Pool[0].Amount)) - assert.True(sdk.DecEq(t, sdk.NewDec(2), vi1.PoolCommission[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(100-2), vi.Pool[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(2), vi.PoolCommission[0].Amount)) // add more blocks and inflation height = 20 fp.Pool[0].Amount = fp.Pool[0].Amount.Add(sdk.NewDec(1000)) - vi1, fp, commissionRecv := vi1.WithdrawCommission(fp, height, totalBondedTokens, validatorTokens1, commissionRate1) + vi, fp, commissionRecv := vi.WithdrawCommission(fp, height, totalBondedTokens, validatorTokens, commissionRate) require.True(sdk.DecEq(t, sdk.NewDec(1800), fp.ValAccum.Accum)) assert.True(sdk.DecEq(t, sdk.NewDec(1800), fp.Pool[0].Amount)) - assert.True(sdk.DecEq(t, sdk.NewDec(200-4), vi1.Pool[0].Amount)) - assert.Zero(t, len(vi1.PoolCommission)) + assert.True(sdk.DecEq(t, sdk.NewDec(200-4), vi.Pool[0].Amount)) + assert.Zero(t, len(vi.PoolCommission)) assert.True(sdk.DecEq(t, sdk.NewDec(4), commissionRecv[0].Amount)) } From 3a9102e2afd4a5ee5d4d0a5dadc4f48e8b4321a7 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 4 Oct 2018 03:34:10 -0400 Subject: [PATCH 66/99] fix --- x/distribution/types/delegator_info.go | 4 ++-- x/distribution/types/delegator_info_test.go | 2 +- x/distribution/types/validator_info.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index 911fad9c98..1a1bd4d9b1 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -37,8 +37,8 @@ func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, blocks := height - di.WithdrawalHeight di.WithdrawalHeight = height accum := delegatorShares.Mul(sdk.NewDec(blocks)) - withdrawalTokens := vi.Pool.MulDec(accum.Quo(vi.DelAccum.Accum)) - remainingTokens := vi.Pool.MulDec(sdk.OneDec().Sub(accum.Quo(vi.DelAccum.Accum))) + withdrawalTokens := vi.Pool.MulDec(accum).QuoDec(vi.DelAccum.Accum) + remainingTokens := vi.Pool.Minus(withdrawalTokens) vi.Pool = remainingTokens vi.DelAccum.Accum = vi.DelAccum.Accum.Sub(accum) diff --git a/x/distribution/types/delegator_info_test.go b/x/distribution/types/delegator_info_test.go index f1bcbb4ec5..03803f8cd2 100644 --- a/x/distribution/types/delegator_info_test.go +++ b/x/distribution/types/delegator_info_test.go @@ -52,5 +52,5 @@ func TestWithdrawRewards(t *testing.T) { assert.True(sdk.DecEq(t, sdk.NewDec(1800), fp.Pool[0].Amount)) assert.True(sdk.DecEq(t, sdk.NewDec(49), vi.Pool[0].Amount)) assert.True(sdk.DecEq(t, sdk.NewDec(4), vi.PoolCommission[0].Amount)) - assert.True(sdk.DecEq(t, sdk.NewDec(147), rewardRecv2[0].Amount)) + assert.True(sdk.DecEq(t, sdk.NewDec(98), rewardRecv2[0].Amount)) } diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index e328390469..3092d10191 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -49,7 +49,7 @@ func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBo remainingTokens := fp.Pool.Minus(withdrawalTokens) commission := withdrawalTokens.MulDec(commissionRate) - afterCommission := withdrawalTokens.MulDec(sdk.OneDec().Sub(commissionRate)) + afterCommission := withdrawalTokens.Minus(commission) fp.ValAccum.Accum = fp.ValAccum.Accum.Sub(accum) fp.Pool = remainingTokens From eb01cb4a35bb557bc7308e11ccaf99709d7463d0 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 4 Oct 2018 18:29:03 -0400 Subject: [PATCH 67/99] checkout distr types PR updates --- x/distribution/types/codec.go | 2 +- x/distribution/types/dec_coin.go | 20 +++++++++++----- x/distribution/types/dec_coin_test.go | 26 ++++++++------------- x/distribution/types/delegator_info.go | 12 ++-------- x/distribution/types/delegator_info_test.go | 2 +- x/distribution/types/fee_pool.go | 12 ++++++---- x/distribution/types/fee_pool_test.go | 6 ++--- x/distribution/types/genesis.go | 9 +++++++ x/distribution/types/msg.go | 2 +- x/distribution/types/validator_info.go | 4 ++-- x/distribution/types/validator_info_test.go | 4 ++-- 11 files changed, 53 insertions(+), 46 deletions(-) diff --git a/x/distribution/types/codec.go b/x/distribution/types/codec.go index 55d7c6cdae..10b2dc2fb5 100644 --- a/x/distribution/types/codec.go +++ b/x/distribution/types/codec.go @@ -12,7 +12,7 @@ func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(MsgSetWithdrawAddress{}, "cosmos-sdk/MsgModifyWithdrawAddress", nil) } -// generic sealed codec to be used throught module +// generic sealed codec to be used throughout module var MsgCdc *codec.Codec func init() { diff --git a/x/distribution/types/dec_coin.go b/x/distribution/types/dec_coin.go index df94d864db..59373976de 100644 --- a/x/distribution/types/dec_coin.go +++ b/x/distribution/types/dec_coin.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,7 +13,14 @@ type DecCoin struct { Amount sdk.Dec `json:"amount"` } -func NewDecCoin(coin sdk.Coin) DecCoin { +func NewDecCoin(denom string, amount int64) DecCoin { + return DecCoin{ + Denom: denom, + Amount: sdk.NewDec(amount), + } +} + +func NewDecCoinFromCoin(coin sdk.Coin) DecCoin { return DecCoin{ Denom: coin.Denom, Amount: sdk.NewDecFromInt(coin.Amount), @@ -21,16 +29,16 @@ func NewDecCoin(coin sdk.Coin) DecCoin { // Adds amounts of two coins with same denom func (coin DecCoin) Plus(coinB DecCoin) DecCoin { - if !(coin.Denom == coinB.Denom) { - return coin + if coin.Denom != coinB.Denom { + panic(fmt.Sprintf("coin denom different: %v %v\n", coin.Denom, coinB.Denom)) } return DecCoin{coin.Denom, coin.Amount.Add(coinB.Amount)} } // Subtracts amounts of two coins with same denom func (coin DecCoin) Minus(coinB DecCoin) DecCoin { - if !(coin.Denom == coinB.Denom) { - return coin + if coin.Denom != coinB.Denom { + panic(fmt.Sprintf("coin denom different: %v %v\n", coin.Denom, coinB.Denom)) } return DecCoin{coin.Denom, coin.Amount.Sub(coinB.Amount)} } @@ -48,7 +56,7 @@ type DecCoins []DecCoin func NewDecCoins(coins sdk.Coins) DecCoins { dcs := make(DecCoins, len(coins)) for i, coin := range coins { - dcs[i] = NewDecCoin(coin) + dcs[i] = NewDecCoinFromCoin(coin) } return dcs } diff --git a/x/distribution/types/dec_coin_test.go b/x/distribution/types/dec_coin_test.go index 61de361ca9..5a326fa17b 100644 --- a/x/distribution/types/dec_coin_test.go +++ b/x/distribution/types/dec_coin_test.go @@ -4,6 +4,7 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -11,23 +12,16 @@ func TestPlusDecCoin(t *testing.T) { decCoinA1 := DecCoin{"A", sdk.NewDecWithPrec(11, 1)} decCoinA2 := DecCoin{"A", sdk.NewDecWithPrec(22, 1)} decCoinB1 := DecCoin{"B", sdk.NewDecWithPrec(11, 1)} - decCoinC1 := DecCoin{"C", sdk.NewDecWithPrec(11, 1)} - decCoinCn4 := DecCoin{"C", sdk.NewDecWithPrec(-44, 1)} - decCoinC5 := DecCoin{"C", sdk.NewDecWithPrec(55, 1)} - cases := []struct { - inputOne DecCoin - inputTwo DecCoin - expected DecCoin - }{ - {decCoinA1, decCoinA1, decCoinA2}, - {decCoinA1, decCoinB1, decCoinA1}, - {decCoinCn4, decCoinC5, decCoinC1}, - } - for tcIndex, tc := range cases { - res := tc.inputOne.Plus(tc.inputTwo) - require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex) - } + // regular add + res := decCoinA1.Plus(decCoinA1) + require.Equal(t, decCoinA2, res, "sum of coins is incorrect") + + // bad denom add + assert.Panics(t, func() { + decCoinA1.Plus(decCoinB1) + }, "expected panic on sum of different denoms") + } func TestPlusCoins(t *testing.T) { diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index 1a1bd4d9b1..4de2968904 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -4,7 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// distribution info for a delegation +// distribution info for a delegation - used to determine entitled rewards type DelegatorDistInfo struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` ValOperatorAddr sdk.ValAddress `json:"val_operator_addr"` @@ -36,7 +36,7 @@ func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, blocks := height - di.WithdrawalHeight di.WithdrawalHeight = height - accum := delegatorShares.Mul(sdk.NewDec(blocks)) + accum := delegatorShares.MulInt(sdk.NewInt(blocks)) withdrawalTokens := vi.Pool.MulDec(accum).QuoDec(vi.DelAccum.Accum) remainingTokens := vi.Pool.Minus(withdrawalTokens) @@ -45,11 +45,3 @@ func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo, return di, vi, fp, withdrawalTokens } - -//_____________________________________________________________________ - -// withdraw address for the delegation rewards -type DelegatorWithdrawInfo struct { - DelegatorAddr sdk.AccAddress `json:"delegator_addr"` - WithdrawAddr sdk.AccAddress `json:"withdraw_addr"` -} diff --git a/x/distribution/types/delegator_info_test.go b/x/distribution/types/delegator_info_test.go index 03803f8cd2..2d9e9bc0fe 100644 --- a/x/distribution/types/delegator_info_test.go +++ b/x/distribution/types/delegator_info_test.go @@ -26,7 +26,7 @@ func TestWithdrawRewards(t *testing.T) { // simulate adding some stake for inflation height = 10 - fp.Pool = DecCoins{DecCoin{"stake", sdk.NewDec(1000)}} + fp.Pool = DecCoins{NewDecCoin("stake", 1000)} // withdraw rewards di1, vi, fp, rewardRecv1 := di1.WithdrawRewards(fp, vi, height, totalBondedTokens, diff --git a/x/distribution/types/fee_pool.go b/x/distribution/types/fee_pool.go index d373e04858..66731cb197 100644 --- a/x/distribution/types/fee_pool.go +++ b/x/distribution/types/fee_pool.go @@ -17,10 +17,14 @@ func NewTotalAccum(height int64) TotalAccum { } } -// update total validator accumulation factor -func (ta TotalAccum) Update(height int64, accumCreatedPerBlock sdk.Dec) TotalAccum { +// update total validator accumulation factor for the new height +// CONTRACT: height should be greater than the old height +func (ta TotalAccum) UpdateForNewHeight(height int64, accumCreatedPerBlock sdk.Dec) TotalAccum { blocks := height - ta.UpdateHeight - ta.Accum = ta.Accum.Add(accumCreatedPerBlock.Mul(sdk.NewDec(blocks))) + if blocks < 0 { + panic("reverse updated for new height") + } + ta.Accum = ta.Accum.Add(accumCreatedPerBlock.MulInt(sdk.NewInt(blocks))) ta.UpdateHeight = height return ta } @@ -36,7 +40,7 @@ type FeePool struct { // update total validator accumulation factor func (f FeePool) UpdateTotalValAccum(height int64, totalBondedTokens sdk.Dec) FeePool { - f.ValAccum = f.ValAccum.Update(height, totalBondedTokens) + f.ValAccum = f.ValAccum.UpdateForNewHeight(height, totalBondedTokens) return f } diff --git a/x/distribution/types/fee_pool_test.go b/x/distribution/types/fee_pool_test.go index 1c2a804b42..e39fb09c94 100644 --- a/x/distribution/types/fee_pool_test.go +++ b/x/distribution/types/fee_pool_test.go @@ -7,14 +7,14 @@ import ( "github.com/stretchr/testify/require" ) -func TestTotalAccumUpdate(t *testing.T) { +func TestTotalAccumUpdateForNewHeight(t *testing.T) { ta := NewTotalAccum(0) - ta = ta.Update(5, sdk.NewDec(3)) + ta = ta.UpdateForNewHeight(5, sdk.NewDec(3)) require.True(sdk.DecEq(t, sdk.NewDec(15), ta.Accum)) - ta = ta.Update(8, sdk.NewDec(2)) + ta = ta.UpdateForNewHeight(8, sdk.NewDec(2)) require.True(sdk.DecEq(t, sdk.NewDec(21), ta.Accum)) } diff --git a/x/distribution/types/genesis.go b/x/distribution/types/genesis.go index a42f705941..f01d1b781e 100644 --- a/x/distribution/types/genesis.go +++ b/x/distribution/types/genesis.go @@ -1,5 +1,14 @@ package types +import sdk "github.com/cosmos/cosmos-sdk/types" + +// the address for where distributions rewards are withdrawn to by default +// this struct is only used at genesis to feed in default withdraw addresses +type DelegatorWithdrawInfo struct { + DelegatorAddr sdk.AccAddress `json:"delegator_addr"` + WithdrawAddr sdk.AccAddress `json:"withdraw_addr"` +} + // GenesisState - all distribution state that must be provided at genesis type GenesisState struct { FeePool FeePool `json:"fee_pool"` diff --git a/x/distribution/types/msg.go b/x/distribution/types/msg.go index a98892ee99..f00dceae1f 100644 --- a/x/distribution/types/msg.go +++ b/x/distribution/types/msg.go @@ -28,7 +28,7 @@ func NewMsgSetWithdrawAddress(delAddr, withdrawAddr sdk.AccAddress) MsgSetWithdr } func (msg MsgSetWithdrawAddress) Type() string { return MsgType } -func (msg MsgSetWithdrawAddress) Name() string { return "withdraw_delegation_rewards_all" } +func (msg MsgSetWithdrawAddress) Name() string { return "set_withdraw_address" } // Return address that must sign over msg.GetSignBytes() func (msg MsgSetWithdrawAddress) GetSigners() []sdk.AccAddress { diff --git a/x/distribution/types/validator_info.go b/x/distribution/types/validator_info.go index 3092d10191..18aef8bde6 100644 --- a/x/distribution/types/validator_info.go +++ b/x/distribution/types/validator_info.go @@ -27,7 +27,7 @@ func NewValidatorDistInfo(operatorAddr sdk.ValAddress, currentHeight int64) Vali // update total delegator accumululation func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares sdk.Dec) ValidatorDistInfo { - vi.DelAccum = vi.DelAccum.Update(height, totalDelShares) + vi.DelAccum = vi.DelAccum.UpdateForNewHeight(height, totalDelShares) return vi } @@ -44,7 +44,7 @@ func (vi ValidatorDistInfo) TakeFeePoolRewards(fp FeePool, height int64, totalBo // update the validators pool blocks := height - vi.FeePoolWithdrawalHeight vi.FeePoolWithdrawalHeight = height - accum := sdk.NewDec(blocks).Mul(vdTokens) + accum := vdTokens.MulInt(sdk.NewInt(blocks)) withdrawalTokens := fp.Pool.MulDec(accum).QuoDec(fp.ValAccum.Accum) remainingTokens := fp.Pool.Minus(withdrawalTokens) diff --git a/x/distribution/types/validator_info_test.go b/x/distribution/types/validator_info_test.go index da3b2c10d8..afa6d8c763 100644 --- a/x/distribution/types/validator_info_test.go +++ b/x/distribution/types/validator_info_test.go @@ -26,7 +26,7 @@ func TestTakeFeePoolRewards(t *testing.T) { // simulate adding some stake for inflation height = 10 - fp.Pool = DecCoins{DecCoin{"stake", sdk.NewDec(1000)}} + fp.Pool = DecCoins{NewDecCoin("stake", 1000)} vi1, fp = vi1.TakeFeePoolRewards(fp, height, totalBondedTokens, validatorTokens1, commissionRate1) require.True(sdk.DecEq(t, sdk.NewDec(900), fp.ValAccum.Accum)) @@ -63,7 +63,7 @@ func TestWithdrawCommission(t *testing.T) { // simulate adding some stake for inflation height = 10 - fp.Pool = DecCoins{DecCoin{"stake", sdk.NewDec(1000)}} + fp.Pool = DecCoins{NewDecCoin("stake", 1000)} // for a more fun staring condition, have an non-withdraw update vi, fp = vi.TakeFeePoolRewards(fp, height, totalBondedTokens, validatorTokens, commissionRate) From 20a51e587cc0d98fc0f5c7f02c9ee8536f7aff3e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 4 Oct 2018 18:37:46 -0400 Subject: [PATCH 68/99] fix compile errors --- x/distribution/abci_app.go | 2 +- x/distribution/client/cli/tx.go | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index 57c10d013b..bea9824c00 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -9,7 +9,7 @@ import ( // set the proposer for determining distribution during endblock func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) { - consAddr := sdk.ConsAddress(req.Header.Proposer.Address) + consAddr := sdk.ConsAddress(req.Header.ProposerAddress) k.SetProposerConsAddr(ctx, consAddr) } diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index d3fa22954a..b88968cda5 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -3,7 +3,6 @@ package cli import ( "fmt" - "os" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -42,7 +41,6 @@ func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command { txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). - WithLogger(os.Stdout). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) var msg sdk.Msg @@ -94,7 +92,6 @@ func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command { txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). WithCodec(cdc). - WithLogger(os.Stdout). WithAccountDecoder(authcmd.GetAccountDecoder(cdc)) delAddr, err := cliCtx.GetFromAddress() From 17dc8127493e2d5e04504dc4c894457506a2d2e4 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 4 Oct 2018 20:20:43 -0400 Subject: [PATCH 69/99] fix distribution endblocker issues --- cmd/gaia/app/app.go | 5 +++-- x/distribution/genesis.go | 12 ++++-------- x/distribution/keeper/genesis.go | 6 +++--- x/distribution/keeper/keeper.go | 3 ++- x/distribution/types/genesis.go | 16 +++++++++++----- 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 5f5b542ef8..69f957ec96 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -124,11 +124,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.keyDistr, app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams) app.MountStoresTransient(app.tkeyParams, app.tkeyStake, app.tkeyDistr) + app.SetEndBlocker(app.EndBlocker) + err := app.LoadLatestVersion(app.keyMain) if err != nil { cmn.Exit(err.Error()) @@ -168,7 +169,7 @@ func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.R validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) // distribute rewards - //distr.EndBlocker(ctx, app.distrKeeper) + distr.EndBlocker(ctx, app.distrKeeper) // Add these new validators to the addr -> pubkey map. app.slashingKeeper.AddValidators(ctx, validatorUpdates) diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index c7636c80c0..119c9b8270 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -8,6 +8,7 @@ import ( // 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) for _, vdi := range data.ValidatorDistInfos { keeper.SetValidatorDistInfo(ctx, vdi) @@ -24,14 +25,9 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { // 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) vdis := keeper.GetAllVDIs(ctx) ddis := keeper.GetAllDDIs(ctx) - dws := keeper.GetAllDWs(ctx) - - return GenesisState{ - FeePool: feePool, - ValidatorDistInfos: vdis, - DelegatorDistInfos: ddis, - DelegatorWithdrawInfos: dws, - } + dwis := keeper.GetAllDWIs(ctx) + return NewGenesisState(feePool, communityTax, vdis, ddis, dwis) } diff --git a/x/distribution/keeper/genesis.go b/x/distribution/keeper/genesis.go index ab010f277e..954c44336a 100644 --- a/x/distribution/keeper/genesis.go +++ b/x/distribution/keeper/genesis.go @@ -34,7 +34,7 @@ func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegatorDistInfo) { } // Get the set of all delegator-withdraw addresses with no limits, used during genesis dump -func (k Keeper) GetAllDWs(ctx sdk.Context) (dws []types.DelegatorWithdrawInfo) { +func (k Keeper) GetAllDWIs(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, DelegatorDistInfoKey) defer iterator.Close() @@ -44,7 +44,7 @@ func (k Keeper) GetAllDWs(ctx sdk.Context) (dws []types.DelegatorWithdrawInfo) { DelegatorAddr: sdk.AccAddress(iterator.Key()), WithdrawAddr: sdk.AccAddress(iterator.Value()), } - dws = append(dws, dw) + dwis = append(dwis, dw) } - return dws + return dwis } diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index e49793ddcd..22932065bb 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -33,6 +33,7 @@ func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ps params.Setter, ck ty storeKey: key, storeTKey: tkey, cdc: cdc, + ps: ps, bankKeeper: ck, stakeKeeper: sk, feeCollectionKeeper: fck, @@ -94,6 +95,6 @@ func (k Keeper) GetCommunityTax(ctx sdk.Context) sdk.Dec { } // nolint: errcheck -func (k Keeper) setCommunityTax(ctx sdk.Context, communityTax sdk.Dec) { +func (k Keeper) SetCommunityTax(ctx sdk.Context, communityTax sdk.Dec) { k.ps.Set(ctx, ParamStoreKeyCommunityTax, &communityTax) } diff --git a/x/distribution/types/genesis.go b/x/distribution/types/genesis.go index f01d1b781e..abce9dec48 100644 --- a/x/distribution/types/genesis.go +++ b/x/distribution/types/genesis.go @@ -12,22 +12,28 @@ 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"` ValidatorDistInfos []ValidatorDistInfo `json:"validator_dist_infos"` DelegatorDistInfos []DelegatorDistInfo `json:"delegator_dist_infos"` DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"` } -func NewGenesisState(feePool FeePool, vdis []ValidatorDistInfo, ddis []DelegatorDistInfo) GenesisState { +func NewGenesisState(feePool FeePool, communityTax sdk.Dec, + vdis []ValidatorDistInfo, ddis []DelegatorDistInfo, dwis []DelegatorWithdrawInfo) GenesisState { + return GenesisState{ - FeePool: feePool, - ValidatorDistInfos: vdis, - DelegatorDistInfos: ddis, + FeePool: feePool, + CommunityTax: communityTax, + ValidatorDistInfos: vdis, + DelegatorDistInfos: 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% } } From 81d0f5f4a7f93ef6ad6d2a9139485e6edd6943e2 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 4 Oct 2018 21:37:40 -0400 Subject: [PATCH 70/99] add wanted final test case functions --- x/distribution/keeper/allocation_test.go | 7 +++++++ x/distribution/keeper/delegation_test.go | 15 +++++++++++++++ x/distribution/keeper/validator_test.go | 7 +++++++ 3 files changed, 29 insertions(+) create mode 100644 x/distribution/keeper/allocation_test.go create mode 100644 x/distribution/keeper/delegation_test.go create mode 100644 x/distribution/keeper/validator_test.go diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go new file mode 100644 index 0000000000..77daa1cf69 --- /dev/null +++ b/x/distribution/keeper/allocation_test.go @@ -0,0 +1,7 @@ +package keeper + +import "testing" + +func TestAllocateFees(t *testing.T) { + +} diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go new file mode 100644 index 0000000000..36e44a629d --- /dev/null +++ b/x/distribution/keeper/delegation_test.go @@ -0,0 +1,15 @@ +package keeper + +import "testing" + +func TestWithdrawDelegationReward(t *testing.T) { + +} + +func TestWithdrawDelegationRewardsAll(t *testing.T) { + +} + +func TestGetDelegatorRewardsAll(t *testing.T) { + +} diff --git a/x/distribution/keeper/validator_test.go b/x/distribution/keeper/validator_test.go new file mode 100644 index 0000000000..df25ef4e00 --- /dev/null +++ b/x/distribution/keeper/validator_test.go @@ -0,0 +1,7 @@ +package keeper + +import "testing" + +func TestWithdrawValidatorRewardsAll(t *testing.T) { + +} From e304b9c60043a2e6bbc9bd751318f9354ebf8bc3 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 5 Oct 2018 20:32:06 -0400 Subject: [PATCH 71/99] debugging simulation --- cmd/gaia/app/app.go | 6 ++--- cmd/gaia/app/sim_test.go | 16 +++++++++--- docs/spec/distribution/hooks.md | 2 +- docs/spec/distribution/state.md | 4 +-- docs/spec/distribution/transactions.md | 4 +-- x/distribution/alias.go | 9 ++++--- x/distribution/genesis.go | 4 +-- x/distribution/keeper/delegation.go | 14 +++++------ x/distribution/keeper/genesis.go | 8 +++--- x/distribution/keeper/hooks.go | 6 ++--- x/distribution/keeper/key.go | 6 ++--- x/distribution/types/delegator_info.go | 12 ++++----- x/distribution/types/delegator_info_test.go | 4 +-- x/distribution/types/genesis.go | 26 ++++++++++++++++--- x/stake/keeper/delegation.go | 4 +-- x/stake/simulation/msgs.go | 28 +++++++++++++++------ 16 files changed, 97 insertions(+), 56 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 69f957ec96..6faf486d34 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -201,8 +201,7 @@ 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 @@ -212,8 +211,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci 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{ diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index db08d872f0..4f90ce8c69 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -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" @@ -52,18 +53,23 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage { Coins: coins, }) } - govGenesis := gov.DefaultGenesisState() + // Default genesis state stakeGenesis := stake.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) } @@ -73,10 +79,12 @@ 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, - GovData: govGenesis, + DistrData: distr.DefaultGenesisWithValidators(valAddrs), + GovData: gov.DefaultGenesisState(), } // Marshal genesis diff --git a/docs/spec/distribution/hooks.md b/docs/spec/distribution/hooks.md index e1a18ef593..8c2b4b91a1 100644 --- a/docs/spec/distribution/hooks.md +++ b/docs/spec/distribution/hooks.md @@ -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 diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index e5c0d47d02..0909ac7584 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -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 } ``` diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index c8c1080ad4..821c4ba352 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -172,9 +172,9 @@ 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 FeePool, vi ValidatorDistInfo, +func (di DelegationDistInfo) WithdrawRewards(g FeePool, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) ( - di DelegatorDistInfo, g FeePool, withdrawn DecCoins) + di DelegationDistInfo, g FeePool, withdrawn DecCoins) vi.UpdateTotalDelAccum(height, totalDelShares) g = vi.TakeFeePoolRewards(g, height, totalBonded, vdTokens, commissionRate) diff --git a/x/distribution/alias.go b/x/distribution/alias.go index 80667b1897..5195c95060 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -12,7 +12,7 @@ type ( Hooks = keeper.Hooks DelegatorWithdrawInfo = types.DelegatorWithdrawInfo - DelegatorDistInfo = types.DelegatorDistInfo + DelegationDistInfo = types.DelegationDistInfo ValidatorDistInfo = types.ValidatorDistInfo TotalAccum = types.TotalAccum FeePool = types.FeePool @@ -34,14 +34,15 @@ var ( GetDelegatorWithdrawAddrKey = keeper.GetDelegatorWithdrawAddrKey FeePoolKey = keeper.FeePoolKey ValidatorDistInfoKey = keeper.ValidatorDistInfoKey - DelegatorDistInfoKey = keeper.DelegatorDistInfoKey + DelegationDistInfoKey = keeper.DelegationDistInfoKey DelegatorWithdrawInfoKey = keeper.DelegatorWithdrawInfoKey ProposerKey = keeper.ProposerKey InitialFeePool = types.InitialFeePool - NewGenesisState = types.NewGenesisState - DefaultGenesisState = types.DefaultGenesisState + NewGenesisState = types.NewGenesisState + DefaultGenesisState = types.DefaultGenesisState + DefaultGenesisWithValidators = types.DefaultGenesisWithValidators RegisterCodec = types.RegisterCodec diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index 119c9b8270..735c2a713c 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -13,8 +13,8 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { for _, vdi := range data.ValidatorDistInfos { keeper.SetValidatorDistInfo(ctx, vdi) } - for _, ddi := range data.DelegatorDistInfos { - keeper.SetDelegatorDistInfo(ctx, ddi) + for _, ddi := range data.DelegationDistInfos { + keeper.SetDelegationDistInfo(ctx, ddi) } for _, dw := range data.DelegatorWithdrawInfos { keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr) diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index ab5b7c0a25..0473a6693d 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -6,8 +6,8 @@ import ( ) // get the delegator distribution info -func (k Keeper) GetDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, - valOperatorAddr sdk.ValAddress) (ddi types.DelegatorDistInfo) { +func (k Keeper) GetDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, + valOperatorAddr sdk.ValAddress) (ddi types.DelegationDistInfo) { store := ctx.KVStore(k.storeKey) @@ -21,14 +21,14 @@ func (k Keeper) GetDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, } // set the delegator distribution info -func (k Keeper) SetDelegatorDistInfo(ctx sdk.Context, ddi types.DelegatorDistInfo) { +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) RemoveDelegatorDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, +func (k Keeper) RemoveDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress, valOperatorAddr sdk.ValAddress) { store := ctx.KVStore(k.storeKey) @@ -69,7 +69,7 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA height := ctx.BlockHeight() bondedTokens := k.stakeKeeper.TotalPower(ctx) feePool := k.GetFeePool(ctx) - delInfo := k.GetDelegatorDistInfo(ctx, delegatorAddr, validatorAddr) + delInfo := k.GetDelegationDistInfo(ctx, delegatorAddr, validatorAddr) valInfo := k.GetValidatorDistInfo(ctx, validatorAddr) validator := k.stakeKeeper.Validator(ctx, validatorAddr) delegation := k.stakeKeeper.Delegation(ctx, delegatorAddr, validatorAddr) @@ -109,7 +109,7 @@ func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, // iterate over all the delegations operationAtDelegation := func(_ int64, del sdk.Delegation) (stop bool) { valAddr := del.GetValidator() - delInfo := k.GetDelegatorDistInfo(ctx, delAddr, valAddr) + delInfo := k.GetDelegationDistInfo(ctx, delAddr, valAddr) valInfo := k.GetValidatorDistInfo(ctx, valAddr) validator := k.stakeKeeper.Validator(ctx, valAddr) delegation := k.stakeKeeper.Delegation(ctx, delAddr, valAddr) @@ -119,7 +119,7 @@ func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, withdraw = withdraw.Plus(diWithdraw) k.SetFeePool(ctx, feePool) k.SetValidatorDistInfo(ctx, valInfo) - k.SetDelegatorDistInfo(ctx, delInfo) + k.SetDelegationDistInfo(ctx, delInfo) return false } k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation) diff --git a/x/distribution/keeper/genesis.go b/x/distribution/keeper/genesis.go index 954c44336a..4a34e5fdc7 100644 --- a/x/distribution/keeper/genesis.go +++ b/x/distribution/keeper/genesis.go @@ -20,13 +20,13 @@ func (k Keeper) GetAllVDIs(ctx sdk.Context) (vdis []types.ValidatorDistInfo) { } // Get the set of all delegator-distribution-info's with no limits, used during genesis dump -func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegatorDistInfo) { +func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegationDistInfo) { store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, DelegatorDistInfoKey) + iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey) defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - var ddi types.DelegatorDistInfo + var ddi types.DelegationDistInfo k.cdc.MustUnmarshalBinary(iterator.Value(), &ddi) ddis = append(ddis, ddi) } @@ -36,7 +36,7 @@ func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegatorDistInfo) { // Get the set of all delegator-withdraw addresses with no limits, used during genesis dump func (k Keeper) GetAllDWIs(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) { store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, DelegatorDistInfoKey) + iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey) defer iterator.Close() for ; iterator.Valid(); iterator.Next() { diff --git a/x/distribution/keeper/hooks.go b/x/distribution/keeper/hooks.go index d503d54fb2..a408b0d21f 100644 --- a/x/distribution/keeper/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -37,12 +37,12 @@ func (k Keeper) onValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) { func (k Keeper) onDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - ddi := types.DelegatorDistInfo{ + ddi := types.DelegationDistInfo{ DelegatorAddr: delAddr, ValOperatorAddr: valAddr, WithdrawalHeight: ctx.BlockHeight(), } - k.SetDelegatorDistInfo(ctx, ddi) + k.SetDelegationDistInfo(ctx, ddi) ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("ddi created: %v", ddi)) } @@ -57,7 +57,7 @@ func (k Keeper) onDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddre func (k Keeper) onDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { - k.RemoveDelegatorDistInfo(ctx, delAddr, valAddr) + k.RemoveDelegationDistInfo(ctx, delAddr, valAddr) } //_________________________________________________________________________________________ diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index 771343f017..f4e18cf63b 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -8,7 +8,7 @@ import ( var ( FeePoolKey = []byte{0x00} // key for global distribution state ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution - DelegatorDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution + DelegationDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info // transient @@ -22,14 +22,14 @@ func GetValidatorDistInfoKey(operatorAddr sdk.ValAddress) []byte { } // gets the key for delegator distribution for a validator -// VALUE: distribution/types.DelegatorDistInfo +// 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(DelegatorDistInfoKey, delAddr.Bytes()...) + return append(DelegationDistInfoKey, delAddr.Bytes()...) } // gets the prefix for a delegator's withdraw info diff --git a/x/distribution/types/delegator_info.go b/x/distribution/types/delegator_info.go index 4de2968904..f5b8978e5f 100644 --- a/x/distribution/types/delegator_info.go +++ b/x/distribution/types/delegator_info.go @@ -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) diff --git a/x/distribution/types/delegator_info_test.go b/x/distribution/types/delegator_info_test.go index 2d9e9bc0fe..516cbf99df 100644 --- a/x/distribution/types/delegator_info_test.go +++ b/x/distribution/types/delegator_info_test.go @@ -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 diff --git a/x/distribution/types/genesis.go b/x/distribution/types/genesis.go index abce9dec48..9921818b2d 100644 --- a/x/distribution/types/genesis.go +++ b/x/distribution/types/genesis.go @@ -14,18 +14,18 @@ type GenesisState struct { FeePool FeePool `json:"fee_pool"` CommunityTax sdk.Dec `json:"community_tax"` 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, communityTax sdk.Dec, - vdis []ValidatorDistInfo, ddis []DelegatorDistInfo, dwis []DelegatorWithdrawInfo) GenesisState { + vdis []ValidatorDistInfo, ddis []DelegationDistInfo, dwis []DelegatorWithdrawInfo) GenesisState { return GenesisState{ FeePool: feePool, CommunityTax: communityTax, ValidatorDistInfos: vdis, - DelegatorDistInfos: ddis, + DelegationDistInfos: ddis, DelegatorWithdrawInfos: dwis, } } @@ -37,3 +37,23 @@ func DefaultGenesisState() GenesisState { CommunityTax: sdk.NewDecWithPrec(2, 2), // 2% } } + +// 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% + ValidatorDistInfos: vdis, + DelegationDistInfos: ddis, + } +} diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index fe46e1679a..842ea1c272 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -278,8 +278,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 { @@ -287,6 +285,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()) diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index 0cd4e08a92..894a8cfeee 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -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. // SimulateMsgCompleteUnbonding func SimulateMsgCompleteUnbonding(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) { validatorAcc := simulation.RandomAcc(r, accs) validatorAddress := sdk.ValAddress(validatorAcc.Address) @@ -208,7 +218,9 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { // 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) @@ -248,7 +260,9 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation // SimulateMsgCompleteRedelegate func SimulateMsgCompleteRedelegate(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) { validatorSrcAcc := simulation.RandomAcc(r, accs) validatorSrcAddress := sdk.ValAddress(validatorSrcAcc.Address) From 142f42ecc79359a8eb43f6dbdaa4e0923e3c4a79 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 8 Oct 2018 20:14:03 -0400 Subject: [PATCH 72/99] ... --- x/distribution/keeper/delegation_test.go | 1 + x/distribution/keeper/test_utils.go | 27 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 x/distribution/keeper/test_utils.go diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 36e44a629d..31e22b48f0 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -4,6 +4,7 @@ import "testing" func TestWithdrawDelegationReward(t *testing.T) { + keeper.WithdrawDelegationReward(ctx, delAddr1, valAddr1) } func TestWithdrawDelegationRewardsAll(t *testing.T) { diff --git a/x/distribution/keeper/test_utils.go b/x/distribution/keeper/test_utils.go new file mode 100644 index 0000000000..3ea78cd792 --- /dev/null +++ b/x/distribution/keeper/test_utils.go @@ -0,0 +1,27 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" +) + +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()) + emptyDelAddr sdk.AccAddress + + 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()) + emptyValAddr sdk.ValAddress + + emptyPubkey crypto.PubKey +) From 46fe52bbacf40668069dd7eb5f5c39f8cd4452a5 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 9 Oct 2018 11:27:26 -0400 Subject: [PATCH 73/99] create test initialization for distr --- x/distribution/keeper/test_common.go | 103 +++++++++++++++++++++++++++ x/distribution/keeper/test_utils.go | 27 ------- 2 files changed, 103 insertions(+), 27 deletions(-) create mode 100644 x/distribution/keeper/test_common.go delete mode 100644 x/distribution/keeper/test_utils.go diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go new file mode 100644 index 0000000000..01325863af --- /dev/null +++ b/x/distribution/keeper/test_common.go @@ -0,0 +1,103 @@ +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()) + addrs = []sdk.AccAddress{delAddr1, delAddr2, delAddr3} + emptyDelAddr sdk.AccAddress + + 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()) + 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 +} + +// hogpodge of all sorts of input required for testing +func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context, auth.AccountMapper, Keeper) { + + keyDistr := sdk.NewKVStoreKey("distr") + tkeyDistr := sdk.NewTransientStoreKey("transient_distr") + keyStake := sdk.NewKVStoreKey("stake") + tkeyStake := sdk.NewTransientStoreKey("transient_stake") + keyAcc := sdk.NewKVStoreKey("acc") + keyFeeCollection := sdk.NewKVStoreKey("fee") + keyParams := sdk.NewKVStoreKey("params") + + db := dbm.NewMemDB() + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil) + ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) + err := ms.LoadLatestVersion() + require.Nil(t, err) + + ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, log.NewNopLogger()) + cdc := MakeTestCodec() + accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount) + ck := bank.NewBaseKeeper(accountMapper) + sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, 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 := auth.NewFeeCollectionKeeper(cdc, keyFeeCollection) + pk := params.NewKeeper(cdc, keyParams) + keeper := NewKeeper(cdc, keyDistr, tkeyDistr, pk.Setter(), ck, sk, fck, types.DefaultCodespace) + + return ctx, accountMapper, keeper +} diff --git a/x/distribution/keeper/test_utils.go b/x/distribution/keeper/test_utils.go deleted file mode 100644 index 3ea78cd792..0000000000 --- a/x/distribution/keeper/test_utils.go +++ /dev/null @@ -1,27 +0,0 @@ -package types - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" -) - -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()) - emptyDelAddr sdk.AccAddress - - 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()) - emptyValAddr sdk.ValAddress - - emptyPubkey crypto.PubKey -) From c9730329bfd1bb4fb6d11f7a8b3f998be4f68e01 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 9 Oct 2018 13:58:59 -0400 Subject: [PATCH 74/99] ... --- x/distribution/keeper/delegation_test.go | 22 +++++- x/distribution/keeper/test_common.go | 5 +- x/slashing/handler_test.go | 4 +- x/slashing/keeper_test.go | 10 +-- x/slashing/test_common.go | 2 +- x/slashing/tick_test.go | 2 +- x/stake/app_test.go | 18 ----- x/stake/handler_test.go | 97 +++++++++-------------- x/stake/keeper/delegation_test.go | 38 ++++----- x/stake/keeper/slash_test.go | 2 +- x/stake/keeper/test_common.go | 3 +- x/stake/keeper/validator_test.go | 98 ++++++++++++------------ x/stake/stake.go | 1 + x/stake/test_common.go | 52 +++++++++++++ 14 files changed, 192 insertions(+), 162 deletions(-) create mode 100644 x/stake/test_common.go diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 31e22b48f0..863cb6ccf3 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -1,9 +1,29 @@ package keeper -import "testing" +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/x/stake" + "github.com/stretchr/testify/require" +) func TestWithdrawDelegationReward(t *testing.T) { + ctx, accMapper, keeper, sk := CreateTestInput(t, false, 100) + stakeHandler := stake.NewHandler(sk) + denom := sk.GetParams(ctx).BondDenom + //first make a validator + msgCreateValidator := stake.NewTestMsgCreateValidator(valAddr1, valPk1, 10) + got := stakeHandler(ctx, msgCreateValidator) + require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) + + // delegate + msgDelegate := stake.NewTestMsgDelegate(delAddr1, valAddr1, 10) + got = stakeHandler(ctx, msgDelegate) + require.True(t, got.IsOK()) + + amt1 := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) + require.Equal(t, 90, amt1.Int64()) keeper.WithdrawDelegationReward(ctx, delAddr1, valAddr1) } diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index 01325863af..a984794421 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -57,7 +57,8 @@ func MakeTestCodec() *codec.Codec { } // hogpodge of all sorts of input required for testing -func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context, auth.AccountMapper, Keeper) { +func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) ( + sdk.Context, auth.AccountMapper, Keeper, stake.Keeper) { keyDistr := sdk.NewKVStoreKey("distr") tkeyDistr := sdk.NewTransientStoreKey("transient_distr") @@ -99,5 +100,5 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context pk := params.NewKeeper(cdc, keyParams) keeper := NewKeeper(cdc, keyDistr, tkeyDistr, pk.Setter(), ck, sk, fck, types.DefaultCodespace) - return ctx, accountMapper, keeper + return ctx, accountMapper, keeper, sk } diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index 059b190597..7de25268e6 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -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) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index e32e7af5b3..bd207b241b 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -30,7 +30,7 @@ func TestHandleDoubleSign(t *testing.T) { sk = sk.WithHooks(keeper.Hooks()) amtInt := int64(100) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) + got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(addr, val, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) @@ -73,7 +73,7 @@ func TestSlashingPeriodCap(t *testing.T) { amtInt := int64(100) addr, amt := addrs[0], sdk.NewInt(amtInt) valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address()) - got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, valConsPubKey, amt)) + got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(addr, valConsPubKey, amt)) require.True(t, got.IsOK()) validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) @@ -139,7 +139,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) @@ -262,7 +262,7 @@ func TestHandleNewValidator(t *testing.T) { ctx, ck, sk, _, keeper := createTestInput(t) 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) @@ -300,7 +300,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) diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index 7c97a85372..f7f2e0b2f3 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -102,7 +102,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{}, diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index a98d97c54c..8bc4080c76 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -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) diff --git a/x/stake/app_test.go b/x/stake/app_test.go index f96408c11f..6bcb9c7207 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -9,24 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/mock" "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. diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 1802f30c13..dedbc3d80a 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -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,7 +612,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") @@ -677,12 +650,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) @@ -724,7 +697,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) @@ -736,7 +709,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") @@ -783,15 +756,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") @@ -826,21 +799,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 @@ -870,16 +843,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") diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index 0964f10def..0fd6eb7aa0 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -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], @@ -521,7 +521,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{ @@ -537,14 +537,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], @@ -578,7 +578,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{ @@ -593,7 +593,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], @@ -608,7 +608,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) @@ -662,7 +662,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{ @@ -678,7 +678,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], @@ -693,7 +693,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) header := ctx.BlockHeader() diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index 7959679c6f..7dcf8ccc95 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -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) diff --git a/x/stake/keeper/test_common.go b/x/stake/keeper/test_common.go index e41b8203b1..46ec67e7c2 100644 --- a/x/stake/keeper/test_common.go +++ b/x/stake/keeper/test_common.go @@ -203,7 +203,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) diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 9b4dc3c55e..6f14ba7a5d 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -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()) diff --git a/x/stake/stake.go b/x/stake/stake.go index 7bec2d9628..61d4e0c874 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -57,6 +57,7 @@ var ( GetREDsFromValSrcIndexKey = keeper.GetREDsFromValSrcIndexKey GetREDsToValDstIndexKey = keeper.GetREDsToValDstIndexKey GetREDsByDelToValDstIndexKey = keeper.GetREDsByDelToValDstIndexKey + TestingUpdateValidator = keeper.TestingUpdateValidator DefaultParams = types.DefaultParams InitialPool = types.InitialPool diff --git a/x/stake/test_common.go b/x/stake/test_common.go new file mode 100644 index 0000000000..40678c09c4 --- /dev/null +++ b/x/stake/test_common.go @@ -0,0 +1,52 @@ +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 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)), + } +} From 6d4975e2c2d44b9be73e63389862ea970c7f86e0 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 10 Oct 2018 01:14:46 +0200 Subject: [PATCH 75/99] R4R: Fix simulation proposer (#2460) * Correctly set proposer in randomized simulation * Return nil if no validators are present --- x/mock/simulation/random_simulate_blocks.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 51705cbef0..645f1d73c3 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -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" @@ -78,7 +79,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp, validators := initChain(r, accs, setups, app, appStateFn) - 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 @@ -147,6 +148,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 { @@ -314,6 +316,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, From 151a81eddbd5da396ccf9fbf8f7fea83e3441e09 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 9 Oct 2018 20:37:22 -0400 Subject: [PATCH 76/99] staking changes test_cover fixes --- x/slashing/keeper_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 8f1eaa3f59..11d9eba26e 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -31,7 +31,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) @@ -73,7 +73,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) From 52316d9ef61e551871e271d22a91e50cdad3f9e8 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 9 Oct 2018 21:43:23 -0400 Subject: [PATCH 77/99] fix initialization of the test --- x/distribution/keeper/delegation_test.go | 7 ++-- x/distribution/keeper/test_common.go | 39 +++++++++++-------- .../types/{test_utils.go => test_common.go} | 6 +-- 3 files changed, 30 insertions(+), 22 deletions(-) rename x/distribution/types/{test_utils.go => test_common.go} (82%) diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 863cb6ccf3..59c4259f39 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -22,9 +22,10 @@ func TestWithdrawDelegationReward(t *testing.T) { got = stakeHandler(ctx, msgDelegate) require.True(t, got.IsOK()) - amt1 := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) - require.Equal(t, 90, amt1.Int64()) - keeper.WithdrawDelegationReward(ctx, delAddr1, valAddr1) + amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) + require.Equal(t, int64(90), amt.Int64()) + _ = keeper + //keeper.WithdrawDelegationReward(ctx, delAddr1, valAddr1) } func TestWithdrawDelegationRewardsAll(t *testing.T) { diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index a984794421..37c1b0d4bb 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -23,24 +23,31 @@ import ( ) 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()) - addrs = []sdk.AccAddress{delAddr1, delAddr2, delAddr3} + 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()) + + valPk1 = ed25519.GenPrivKey().PubKey() + valPk2 = ed25519.GenPrivKey().PubKey() + valPk3 = ed25519.GenPrivKey().PubKey() + valAddr1 = sdk.ValAddress(valPk1.Address()) + valAddr2 = sdk.ValAddress(valPk2.Address()) + valAddr3 = sdk.ValAddress(valPk3.Address()) + valAccAddr1 = sdk.AccAddress(valPk1.Address()) // generate acc addresses for these validator keys too + valAccAddr2 = sdk.AccAddress(valPk2.Address()) + valAccAddr3 = sdk.AccAddress(valPk3.Address()) + + addrs = []sdk.AccAddress{ + delAddr1, delAddr2, delAddr3, + valAccAddr1, valAccAddr2, valAccAddr3, + } + emptyDelAddr sdk.AccAddress - - 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()) emptyValAddr sdk.ValAddress - - emptyPubkey crypto.PubKey + emptyPubkey crypto.PubKey ) // create a codec used only for testing diff --git a/x/distribution/types/test_utils.go b/x/distribution/types/test_common.go similarity index 82% rename from x/distribution/types/test_utils.go rename to x/distribution/types/test_common.go index 3ea78cd792..b77efd46c5 100644 --- a/x/distribution/types/test_utils.go +++ b/x/distribution/types/test_common.go @@ -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 From 22de85651fe1ccdedf12d80b5a1de37595e5cdb1 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 9 Oct 2018 21:59:07 -0400 Subject: [PATCH 78/99] fix distr initialization --- x/distribution/keeper/delegation_test.go | 4 ++-- x/distribution/keeper/hooks.go | 6 ++++++ x/distribution/keeper/test_common.go | 13 +++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 59c4259f39..98749c2b80 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -24,8 +24,8 @@ func TestWithdrawDelegationReward(t *testing.T) { amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) require.Equal(t, int64(90), amt.Int64()) - _ = keeper - //keeper.WithdrawDelegationReward(ctx, delAddr1, valAddr1) + + keeper.WithdrawDelegationReward(ctx, delAddr1, valAddr1) } func TestWithdrawDelegationRewardsAll(t *testing.T) { diff --git a/x/distribution/keeper/hooks.go b/x/distribution/keeper/hooks.go index a408b0d21f..721a26db1d 100644 --- a/x/distribution/keeper/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -67,6 +67,8 @@ type Hooks struct { k Keeper } +var _ sdk.StakingHooks = Hooks{} + // New Validator Hooks func (k Keeper) Hooks() Hooks { return Hooks{k} } @@ -89,3 +91,7 @@ func (h Hooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddres 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) {} diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index 37c1b0d4bb..95921068be 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -77,9 +77,15 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) ( db := dbm.NewMemDB() ms := store.NewCommitMultiStore(db) + + ms.MountStoreWithDB(tkeyDistr, sdk.StoreTypeTransient, nil) + 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) + err := ms.LoadLatestVersion() require.Nil(t, err) @@ -107,5 +113,12 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) ( pk := params.NewKeeper(cdc, keyParams) keeper := NewKeeper(cdc, keyDistr, tkeyDistr, pk.Setter(), 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, sdk.NewDecWithPrec(2, 2)) + return ctx, accountMapper, keeper, sk } From 3b5e57be08cbc77dc13ec3ff2c6b76afd7779a58 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 10 Oct 2018 17:43:47 -0400 Subject: [PATCH 79/99] ctx with proposer, working through allocation test --- types/context.go | 6 +++ x/distribution/abci_app.go | 6 +-- x/distribution/keeper/allocation.go | 9 +++- x/distribution/keeper/allocation_test.go | 49 ++++++++++++++++++- x/distribution/keeper/delegation_test.go | 17 +++++-- x/distribution/keeper/keeper.go | 32 +++++++++--- x/distribution/keeper/key.go | 10 +++- x/distribution/keeper/test_common.go | 62 ++++++++++++++++++------ 8 files changed, 157 insertions(+), 34 deletions(-) diff --git a/types/context.go b/types/context.go index cb5958c5c9..e038337f41 100644 --- a/types/context.go +++ b/types/context.go @@ -188,6 +188,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 { return c.withValue(contextKeyBlockHeight, height) } diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index 9cced9ab83..0b634be874 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -1,8 +1,6 @@ package distribution import ( - "fmt" - abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,8 +10,10 @@ import ( // set the proposer for determining distribution during endblock func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) { consAddr := sdk.ConsAddress(req.Header.ProposerAddress) - fmt.Printf("debug consAddr: %v\n", consAddr) k.SetProposerConsAddr(ctx, consAddr) + + // XXX TODO actually calculate this + k.SetSumPrecommitPower(ctx, sdk.NewDec(1)) } // allocate fees diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 3c4bd3971b..1acd3e7304 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -11,6 +11,12 @@ import ( func (k Keeper) AllocateFees(ctx sdk.Context) { ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("allocation height: %v", ctx.BlockHeight())) + // if there is no power in the system nothing should be allocated + bondedTokens := k.stakeKeeper.TotalPower(ctx) + if bondedTokens.IsZero() { + return + } + // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) @@ -22,8 +28,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { feesCollectedDec := types.NewDecCoins(feesCollected) // allocated rewards to proposer - bondedTokens := k.stakeKeeper.TotalPower(ctx) - sumPowerPrecommitValidators := sdk.NewDec(1) // XXX TODO actually calculate this + sumPowerPrecommitValidators := k.GetSumPrecommitPower(ctx) proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( sumPowerPrecommitValidators).Quo(bondedTokens)) proposerReward := feesCollectedDec.MulDec(proposerMultiplier) diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 77daa1cf69..7e4f8a32fa 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -1,7 +1,52 @@ package keeper -import "testing" +import ( + "testing" -func TestAllocateFees(t *testing.T) { + 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 + 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) + + // 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, sdk.NewDec(10), validator.Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) + bondedTokens := sk.TotalPower(ctx) + assert.True(sdk.DecEq(t, sdk.NewDec(10), bondedTokens)) + + // initial fee pool should be empty + feePool := keeper.GetFeePool(ctx) + require.Nil(t, feePool.Pool) + + // allocate 10 denom of fees + feeInputs := sdk.NewInt(100) + fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) + require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) + ctx = ctx.WithProposer(valConsAddr1) + keeper.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, sdk.NewDec(10)) + keeper.AllocateFees(ctx) + + // verify that these fees have been received by the feePool + feePool = keeper.GetFeePool(ctx) + expRes := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(95, 2)) // 5% goes to proposer + require.Equal(t, 1, len(feePool.Pool)) + require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount)) } diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 98749c2b80..8ff99e4110 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -3,29 +3,38 @@ package keeper import ( "testing" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake" "github.com/stretchr/testify/require" ) func TestWithdrawDelegationReward(t *testing.T) { - ctx, accMapper, keeper, sk := CreateTestInput(t, false, 100) + ctx, accMapper, keeper, sk, fck := CreateTestInputDefault(t, false, 100) stakeHandler := stake.NewHandler(sk) denom := sk.GetParams(ctx).BondDenom //first make a validator - msgCreateValidator := stake.NewTestMsgCreateValidator(valAddr1, valPk1, 10) + 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, valAddr1, 10) + 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()) - keeper.WithdrawDelegationReward(ctx, delAddr1, valAddr1) + feeInputs := sdk.NewInt(20) + fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) + require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) + + keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1) + + amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) + require.Equal(t, int64(100), amt.Int64()) } func TestWithdrawDelegationRewardsAll(t *testing.T) { diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 22932065bb..9c3949b8b9 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -7,11 +7,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/params" ) -// nolint -const ( - ParamStoreKeyCommunityTax = "distr/community-tax" -) - // keeper of the stake store type Keeper struct { storeKey sdk.StoreKey @@ -70,7 +65,7 @@ func (k Keeper) GetProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress) b := tstore.Get(ProposerKey) if b == nil { - panic("Stored fee pool should not have been nil") + panic("Proposer cons address was likely not set in begin block") } k.cdc.MustUnmarshalBinary(b, &consAddr) @@ -86,7 +81,30 @@ func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { //______________________________________________________________________ -// Returns the current Deposit Procedure from the global param store +// set the proposer public key for this block +func (k Keeper) GetSumPrecommitPower(ctx sdk.Context) (sumPrecommitPower sdk.Dec) { + tstore := ctx.KVStore(k.storeTKey) + + b := tstore.Get(ProposerKey) + if b == nil { + panic("Proposer cons address was likely not set in begin block") + } + + k.cdc.MustUnmarshalBinary(b, &sumPrecommitPower) + return +} + +// get the proposer public key for this block +func (k Keeper) SetSumPrecommitPower(ctx sdk.Context, sumPrecommitPower sdk.Dec) { + tstore := ctx.KVStore(k.storeTKey) + b := k.cdc.MustMarshalBinary(sumPrecommitPower) + tstore.Set(ProposerKey, b) +} + +//______________________________________________________________________ +// PARAM STORE + +// Returns the current CommunityTax rate from the global param store // nolint: errcheck func (k Keeper) GetCommunityTax(ctx sdk.Context) sdk.Dec { var communityTax sdk.Dec diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index f4e18cf63b..bd24bff031 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -8,11 +8,17 @@ import ( 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 + DelegationDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info // transient - ProposerKey = []byte{0x00} // key for storing the proposer operator address + ProposerKey = []byte{0x00} // key for storing the proposer operator address + SumPrecommitPowerKey = []byte{0x01} // key for storing the power of the precommit validators +) + +// nolint +const ( + ParamStoreKeyCommunityTax = "distr/community-tax" ) // gets the key for the validator distribution info from address diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index 95921068be..1a64811056 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -30,15 +30,22 @@ var ( delAddr2 = sdk.AccAddress(delPk2.Address()) delAddr3 = sdk.AccAddress(delPk3.Address()) - valPk1 = ed25519.GenPrivKey().PubKey() - valPk2 = ed25519.GenPrivKey().PubKey() - valPk3 = ed25519.GenPrivKey().PubKey() - valAddr1 = sdk.ValAddress(valPk1.Address()) - valAddr2 = sdk.ValAddress(valPk2.Address()) - valAddr3 = sdk.ValAddress(valPk3.Address()) - valAccAddr1 = sdk.AccAddress(valPk1.Address()) // generate acc addresses for these validator keys too - valAccAddr2 = sdk.AccAddress(valPk2.Address()) - valAccAddr3 = sdk.AccAddress(valPk3.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, @@ -63,9 +70,18 @@ func MakeTestCodec() *codec.Codec { 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 CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) ( - sdk.Context, auth.AccountMapper, Keeper, stake.Keeper) { +func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64, + communityTax sdk.Dec) ( + sdk.Context, auth.AccountMapper, Keeper, stake.Keeper, DummyFeeCollectionKeeper) { keyDistr := sdk.NewKVStoreKey("distr") tkeyDistr := sdk.NewTransientStoreKey("transient_distr") @@ -109,7 +125,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) ( sk.SetPool(ctx, pool) } - fck := auth.NewFeeCollectionKeeper(cdc, keyFeeCollection) + fck := DummyFeeCollectionKeeper{} pk := params.NewKeeper(cdc, keyParams) keeper := NewKeeper(cdc, keyDistr, tkeyDistr, pk.Setter(), ck, sk, fck, types.DefaultCodespace) @@ -118,7 +134,25 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) ( // set genesis items required for distribution keeper.SetFeePool(ctx, types.InitialFeePool()) - keeper.SetCommunityTax(ctx, sdk.NewDecWithPrec(2, 2)) + keeper.SetCommunityTax(ctx, communityTax) - return ctx, accountMapper, keeper, sk + 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{} } From 900a5f47f66d5739cf677861422211e66ac694bc Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 10 Oct 2018 22:53:25 -0400 Subject: [PATCH 80/99] keeper_test --- x/distribution/keeper/allocation.go | 3 ++ x/distribution/keeper/allocation_test.go | 3 +- x/distribution/keeper/hooks.go | 2 ++ x/distribution/keeper/keeper_test.go | 46 ++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 x/distribution/keeper/keeper_test.go diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 1acd3e7304..2e8681c5a1 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -19,7 +19,10 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) + fmt.Printf("debug proposerConsAddr: %v\n", proposerConsAddr.String()) proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) + fmt.Printf("debug in allocate proposerValidator: %v\n", proposerValidator.GetOperator()) + proposerDist := k.GetValidatorDistInfo(ctx, proposerValidator.GetOperator()) // get the fees which have been getting collected through all the diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 7e4f8a32fa..00c06ae882 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -1,6 +1,7 @@ package keeper import ( + "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -39,7 +40,7 @@ func TestAllocateFeesBasic(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - ctx = ctx.WithProposer(valConsAddr1) + fmt.Printf("debug valConsAddr1: %v\n", valConsAddr1.String()) keeper.SetProposerConsAddr(ctx, valConsAddr1) keeper.SetSumPrecommitPower(ctx, sdk.NewDec(10)) keeper.AllocateFees(ctx) diff --git a/x/distribution/keeper/hooks.go b/x/distribution/keeper/hooks.go index 721a26db1d..a1f73d39ca 100644 --- a/x/distribution/keeper/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -10,6 +10,8 @@ import ( // Create a new validator distribution record func (k Keeper) onValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { + fmt.Printf("debug asdgojasklnaslkjv addr: %v\n", addr) + height := ctx.BlockHeight() vdi := types.ValidatorDistInfo{ OperatorAddr: addr, diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go new file mode 100644 index 0000000000..ce9ceb8077 --- /dev/null +++ b/x/distribution/keeper/keeper_test.go @@ -0,0 +1,46 @@ +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 TestSetGetProposerConsAddr(t *testing.T) { + ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0) + + keeper.SetProposerConsAddr(ctx, valConsAddr1) + res := keeper.GetProposerConsAddr(ctx) + require.True(t, res.Equals(valConsAddr1), "expected: %v got: %v", valConsAddr1.String(), res.String()) +} + +func TestSetGetSumPrecommitPower(t *testing.T) { + ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0) + + someDec := sdk.NewDec(333) + keeper.SetSumPrecommitPower(ctx, someDec) + res := keeper.GetSumPrecommitPower(ctx) + require.True(sdk.DecEq(t, someDec, res)) +} + +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) +} From f4f39ae03fc27634c75eefbd25893eb755f93e2d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 10 Oct 2018 23:16:49 -0400 Subject: [PATCH 81/99] allocation tests --- x/distribution/keeper/allocation.go | 3 - x/distribution/keeper/allocation_test.go | 72 +++++++++++++++++++++--- x/distribution/keeper/hooks.go | 2 - x/distribution/keeper/keeper.go | 4 +- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 2e8681c5a1..1acd3e7304 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -19,10 +19,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) - fmt.Printf("debug proposerConsAddr: %v\n", proposerConsAddr.String()) proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) - fmt.Printf("debug in allocate proposerValidator: %v\n", proposerValidator.GetOperator()) - proposerDist := k.GetValidatorDistInfo(ctx, proposerValidator.GetOperator()) // get the fees which have been getting collected through all the diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 00c06ae882..773e3db063 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -1,7 +1,6 @@ package keeper import ( - "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -18,7 +17,9 @@ func TestAllocateFeesBasic(t *testing.T) { denom := sk.GetParams(ctx).BondDenom //first make a validator - msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, 10) + 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) @@ -27,22 +28,21 @@ func TestAllocateFeesBasic(t *testing.T) { validator, found := sk.GetValidator(ctx, valOpAddr1) require.True(t, found) require.Equal(t, sdk.Bonded, validator.Status) - assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) - assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) + 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, sdk.NewDec(10), bondedTokens)) + assert.True(sdk.DecEq(t, totalPowerDec, bondedTokens)) // initial fee pool should be empty feePool := keeper.GetFeePool(ctx) require.Nil(t, feePool.Pool) - // allocate 10 denom of fees + // 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)) - fmt.Printf("debug valConsAddr1: %v\n", valConsAddr1.String()) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, sdk.NewDec(10)) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) keeper.AllocateFees(ctx) // verify that these fees have been received by the feePool @@ -51,3 +51,59 @@ func TestAllocateFeesBasic(t *testing.T) { require.Equal(t, 1, len(feePool.Pool)) require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount)) } + +func TestAllocateFeesWithCommunityTax(t *testing.T) { + ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.NewDecWithPrec(1, 2)) //1% + 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) + + // allocate 100 denom of fees + feeInputs := sdk.NewInt(100) + fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) + keeper.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // verify that these fees have been received by the feePool + feePool := keeper.GetFeePool(ctx) + // 5% goes to proposer, 1% community tax + expRes := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(94, 2)) + require.Equal(t, 1, len(feePool.Pool)) + require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount)) +} + +func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) { + ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.NewDecWithPrec(1, 2)) //1% + 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) + + // allocate 100 denom of fees + feeInputs := sdk.NewInt(100) + fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) + keeper.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec.Mul(sdk.NewDecWithPrec(25, 2))) // 25% precommit power + keeper.AllocateFees(ctx) + + // verify that these fees have been received by the feePool + feePool := keeper.GetFeePool(ctx) + // 1% + 4%*0.25 goes to proposer, 1% community tax + expRes := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(97, 2)) + require.Equal(t, 1, len(feePool.Pool)) + require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount)) +} diff --git a/x/distribution/keeper/hooks.go b/x/distribution/keeper/hooks.go index a1f73d39ca..721a26db1d 100644 --- a/x/distribution/keeper/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -10,8 +10,6 @@ import ( // Create a new validator distribution record func (k Keeper) onValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) { - fmt.Printf("debug asdgojasklnaslkjv addr: %v\n", addr) - height := ctx.BlockHeight() vdi := types.ValidatorDistInfo{ OperatorAddr: addr, diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 9c3949b8b9..6dd41e3262 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -85,7 +85,7 @@ func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { func (k Keeper) GetSumPrecommitPower(ctx sdk.Context) (sumPrecommitPower sdk.Dec) { tstore := ctx.KVStore(k.storeTKey) - b := tstore.Get(ProposerKey) + b := tstore.Get(SumPrecommitPowerKey) if b == nil { panic("Proposer cons address was likely not set in begin block") } @@ -98,7 +98,7 @@ func (k Keeper) GetSumPrecommitPower(ctx sdk.Context) (sumPrecommitPower sdk.Dec func (k Keeper) SetSumPrecommitPower(ctx sdk.Context, sumPrecommitPower sdk.Dec) { tstore := ctx.KVStore(k.storeTKey) b := k.cdc.MustMarshalBinary(sumPrecommitPower) - tstore.Set(ProposerKey, b) + tstore.Set(SumPrecommitPowerKey, b) } //______________________________________________________________________ From 8e378e2b2d0629be028ebd9f00db2a147e6efaf5 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 11 Oct 2018 02:14:06 -0400 Subject: [PATCH 82/99] got basic delegation tests working --- x/distribution/keeper/delegation_test.go | 25 ++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 8ff99e4110..2e085cf20e 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/require" ) -func TestWithdrawDelegationReward(t *testing.T) { - ctx, accMapper, keeper, sk, fck := CreateTestInputDefault(t, false, 100) +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 @@ -23,18 +23,31 @@ func TestWithdrawDelegationReward(t *testing.T) { 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()) - feeInputs := sdk.NewInt(20) + totalPower := int64(20) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + // withdraw delegation + ctx = ctx.WithBlockHeight(1) keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1) - amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) - require.Equal(t, int64(100), amt.Int64()) + + expRes := sdk.NewDec(90).Add(sdk.NewDec(100).Quo(sdk.NewDec(2))) // 90 + 100 tokens * 10/20 + require.True(sdk.DecEq(t, expRes, sdk.NewDecFromInt(amt))) +} + +func TestWithdrawDelegationRewardWithCommission(t *testing.T) { + } func TestWithdrawDelegationRewardsAll(t *testing.T) { From 8cb6d106d10a8b635c20eaef53aaaedc22320add Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 11 Oct 2018 02:26:54 -0400 Subject: [PATCH 83/99] TestWithdrawDelegationRewardWithCommission --- x/distribution/keeper/delegation_test.go | 35 ++++++++++++++++++++++++ x/stake/handler.go | 2 +- x/stake/test_common.go | 10 +++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 2e085cf20e..df598c0ed0 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -47,7 +47,42 @@ func TestWithdrawDelegationRewardBasic(t *testing.T) { } 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()) + + totalPower := int64(20) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // 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))) // 90 + 100*90% tokens * 10/20 + require.True(sdk.DecEq(t, expRes, sdk.NewDecFromInt(amt))) } func TestWithdrawDelegationRewardsAll(t *testing.T) { diff --git a/x/stake/handler.go b/x/stake/handler.go index 2367182891..9078ab31b2 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -104,7 +104,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) diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 40678c09c4..49bac0f316 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -32,6 +32,16 @@ func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt ) } +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, From f3c0496c99a1cb9bf89b4779d30d334424e17066 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 12 Oct 2018 04:11:09 -0400 Subject: [PATCH 84/99] TestWithdrawDelegationRewardsAll --- types/int.go | 8 +++ x/distribution/keeper/allocation.go | 3 + x/distribution/keeper/delegation.go | 4 +- x/distribution/keeper/delegation_test.go | 76 ++++++++++++++++++++++-- x/distribution/keeper/validator.go | 2 +- 5 files changed, 86 insertions(+), 7 deletions(-) diff --git a/types/int.go b/types/int.go index 1421a934df..c2bef7a64f 100644 --- a/types/int.go +++ b/types/int.go @@ -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() +} diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 1acd3e7304..92863052a5 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -32,12 +32,14 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( sumPowerPrecommitValidators).Quo(bondedTokens)) proposerReward := feesCollectedDec.MulDec(proposerMultiplier) + fmt.Printf("debug proposerReward: %v\n", proposerReward[0].Amount.String()) // apply commission commission := proposerReward.MulDec(proposerValidator.GetCommission()) remaining := proposerReward.MulDec(sdk.OneDec().Sub(proposerValidator.GetCommission())) proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission) proposerDist.Pool = proposerDist.Pool.Plus(remaining) + fmt.Printf("debug proposerDist.Pool: %v\n", proposerDist.Pool[0].Amount.String()) // allocate community funding communityTax := k.GetCommunityTax(ctx) @@ -48,6 +50,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // set the global pool within the distribution module poolReceived := feesCollectedDec.MulDec(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) feePool.Pool = feePool.Pool.Plus(poolReceived) + fmt.Printf("debug poolReceived: %v\n", poolReceived[0].Amount.String()) k.SetValidatorDistInfo(ctx, proposerDist) k.SetFeePool(ctx, feePool) diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 0473a6693d..0bcaa69e4c 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -91,7 +91,7 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA // 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) + withdraw := k.getDelegatorRewardsAll(ctx, delegatorAddr, height) withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr) _, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal()) if err != nil { @@ -100,7 +100,7 @@ func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr sdk. } // return all rewards for all delegations of a delegator -func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) types.DecCoins { +func (k Keeper) getDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) types.DecCoins { withdraw := types.DecCoins{} bondedTokens := k.stakeKeeper.TotalPower(ctx) diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index df598c0ed0..047d5bccd1 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -85,10 +85,78 @@ func TestWithdrawDelegationRewardWithCommission(t *testing.T) { require.True(sdk.DecEq(t, expRes, sdk.NewDecFromInt(amt))) } +func TestWithdrawDelegationRewardTwoDelegators(t *testing.T) { + +} + 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 -} - -func TestGetDelegatorRewardsAll(t *testing.T) { - + //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 + + totalPower := int64(160) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // 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)) } diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index baeb6ab311..ae07d8b3ff 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -40,7 +40,7 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.Va height := ctx.BlockHeight() validator := k.stakeKeeper.Validator(ctx, operatorAddr) accAddr := sdk.AccAddress(operatorAddr.Bytes()) - withdraw := k.GetDelegatorRewardsAll(ctx, accAddr, height) + withdraw := k.getDelegatorRewardsAll(ctx, accAddr, height) // withdrawal validator commission rewards bondedTokens := k.stakeKeeper.TotalPower(ctx) From a60b91b7b20ad78b99245fd099c8ddefa1f2d32d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 12 Oct 2018 05:37:30 -0400 Subject: [PATCH 85/99] bugfix form TestWithdrawDelegationRewardTwoDelegatorsUneven --- x/distribution/keeper/allocation.go | 3 - x/distribution/keeper/delegation.go | 1 + x/distribution/keeper/delegation_test.go | 124 ++++++++++++++++++++++- 3 files changed, 121 insertions(+), 7 deletions(-) diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 92863052a5..1acd3e7304 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -32,14 +32,12 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( sumPowerPrecommitValidators).Quo(bondedTokens)) proposerReward := feesCollectedDec.MulDec(proposerMultiplier) - fmt.Printf("debug proposerReward: %v\n", proposerReward[0].Amount.String()) // apply commission commission := proposerReward.MulDec(proposerValidator.GetCommission()) remaining := proposerReward.MulDec(sdk.OneDec().Sub(proposerValidator.GetCommission())) proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission) proposerDist.Pool = proposerDist.Pool.Plus(remaining) - fmt.Printf("debug proposerDist.Pool: %v\n", proposerDist.Pool[0].Amount.String()) // allocate community funding communityTax := k.GetCommunityTax(ctx) @@ -50,7 +48,6 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // set the global pool within the distribution module poolReceived := feesCollectedDec.MulDec(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) feePool.Pool = feePool.Pool.Plus(poolReceived) - fmt.Printf("debug poolReceived: %v\n", poolReceived[0].Amount.String()) k.SetValidatorDistInfo(ctx, proposerDist) k.SetFeePool(ctx, feePool) diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 0bcaa69e4c..b7443a0c11 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -79,6 +79,7 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA 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 { diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 047d5bccd1..b41245f3b3 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -42,8 +42,8 @@ func TestWithdrawDelegationRewardBasic(t *testing.T) { 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))) // 90 + 100 tokens * 10/20 - require.True(sdk.DecEq(t, expRes, sdk.NewDecFromInt(amt))) + 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) { @@ -81,12 +81,128 @@ func TestWithdrawDelegationRewardWithCommission(t *testing.T) { 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))) // 90 + 100*90% tokens * 10/20 - require.True(sdk.DecEq(t, expRes, sdk.NewDecFromInt(amt))) + 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()) + + totalPower := int64(40) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // 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()) + + totalPower := int64(30) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + 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) { From 94731a502acad617d15af30ec17f58dd8a0af3a4 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 12 Oct 2018 05:51:00 -0400 Subject: [PATCH 86/99] some validator dist tests --- x/distribution/keeper/validator.go | 3 + x/distribution/keeper/validator_test.go | 123 +++++++++++++++++++++++- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index ae07d8b3ff..9ddfbce56d 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -1,6 +1,8 @@ package keeper import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) @@ -48,6 +50,7 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.Va feePool := k.GetFeePool(ctx) valInfo, feePool, commission := valInfo.WithdrawCommission(feePool, height, bondedTokens, validator.GetTokens(), validator.GetCommission()) + fmt.Printf("debug within wvra commission: %v\n", commission[0].Amount.String()) withdraw = withdraw.Plus(commission) k.SetValidatorDistInfo(ctx, valInfo) k.SetFeePool(ctx, feePool) diff --git a/x/distribution/keeper/validator_test.go b/x/distribution/keeper/validator_test.go index df25ef4e00..5db9841f27 100644 --- a/x/distribution/keeper/validator_test.go +++ b/x/distribution/keeper/validator_test.go @@ -1,7 +1,126 @@ package keeper -import "testing" +import ( + "testing" -func TestWithdrawValidatorRewardsAll(t *testing.T) { + 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) + + totalPower := int64(10) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // 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()) + + totalPower := int64(20) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // 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 + commission := sdk.NewDecWithPrec(1, 1) + msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission( + valOpAddr1, valConsPk1, 10, commission) + 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()) + + totalPower := int64(20) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // withdraw self-delegation reward + ctx = ctx.WithBlockHeight(1) + keeper.WithdrawValidatorRewardsAll(ctx, valOpAddr1) + amt = accMapper.GetAccount(ctx, valAccAddr1).GetCoins().AmountOf(denom) + commissionTaken := sdk.NewDec(100).Mul(commission) + 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) { + +} + +func TestWithdrawValidatorRewardsAllMultipleDelegator(t *testing.T) { } From 7b1f4a87eab6a12cc78bacb558259069442c45aa Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 12 Oct 2018 06:06:01 -0400 Subject: [PATCH 87/99] finished off validator tests --- x/distribution/keeper/validator.go | 3 - x/distribution/keeper/validator_test.go | 99 ++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 9ddfbce56d..ae07d8b3ff 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -1,8 +1,6 @@ package keeper import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) @@ -50,7 +48,6 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.Va feePool := k.GetFeePool(ctx) valInfo, feePool, commission := valInfo.WithdrawCommission(feePool, height, bondedTokens, validator.GetTokens(), validator.GetCommission()) - fmt.Printf("debug within wvra commission: %v\n", commission[0].Amount.String()) withdraw = withdraw.Plus(commission) k.SetValidatorDistInfo(ctx, valInfo) k.SetFeePool(ctx, feePool) diff --git a/x/distribution/keeper/validator_test.go b/x/distribution/keeper/validator_test.go index 5db9841f27..32f5a26863 100644 --- a/x/distribution/keeper/validator_test.go +++ b/x/distribution/keeper/validator_test.go @@ -81,9 +81,9 @@ func TestWithdrawValidatorRewardsAllDelegatorWithCommission(t *testing.T) { denom := sk.GetParams(ctx).BondDenom //first make a validator - commission := sdk.NewDecWithPrec(1, 1) + commissionRate := sdk.NewDecWithPrec(1, 1) msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission( - valOpAddr1, valConsPk1, 10, commission) + valOpAddr1, valConsPk1, 10, commissionRate) got := stakeHandler(ctx, msgCreateValidator) require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) _ = sk.ApplyAndReturnValidatorSetUpdates(ctx) @@ -106,11 +106,11 @@ func TestWithdrawValidatorRewardsAllDelegatorWithCommission(t *testing.T) { keeper.SetSumPrecommitPower(ctx, totalPowerDec) keeper.AllocateFees(ctx) - // withdraw self-delegation reward + // withdraw validator reward ctx = ctx.WithBlockHeight(1) keeper.WithdrawValidatorRewardsAll(ctx, valOpAddr1) amt = accMapper.GetAccount(ctx, valAccAddr1).GetCoins().AmountOf(denom) - commissionTaken := sdk.NewDec(100).Mul(commission) + 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 @@ -118,9 +118,100 @@ func TestWithdrawValidatorRewardsAllDelegatorWithCommission(t *testing.T) { } 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) + + totalPower := int64(100) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // 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()) + + totalPower := int64(40) + totalPowerDec := sdk.NewDec(totalPower) + + // 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.SetProposerConsAddr(ctx, valConsAddr1) + keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.AllocateFees(ctx) + + // 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)) } From 06fa518e3093962a5123232155ffaf5af156f36e Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 12 Oct 2018 07:15:13 -0400 Subject: [PATCH 88/99] address @cwgoes comments, add in precommit calculation --- types/decimal.go | 10 ++++++++++ x/distribution/abci_app.go | 10 ++++++++-- x/distribution/keeper/allocation.go | 14 ++++++++++---- x/distribution/keeper/allocation_test.go | 10 ++++------ x/distribution/keeper/delegation_test.go | 17 ++++++----------- x/distribution/keeper/keeper.go | 4 ++-- x/distribution/keeper/keeper_test.go | 5 ++--- x/distribution/keeper/validator_test.go | 15 +++++---------- x/slashing/tick.go | 2 +- 9 files changed, 48 insertions(+), 39 deletions(-) diff --git a/types/decimal.go b/types/decimal.go index a4d1e40ed3..bd3f340757 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -241,6 +241,16 @@ 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) + + if mul.BitLen() > 255+DecimalPrecisionBits { + panic("Int overflow") + } + return Dec{mul} +} + func (d Dec) String() string { str := d.ToLeftPaddedWithDecimals(Precision) placement := len(str) - Precision diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index 0b634be874..e4a90fa5fc 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -12,8 +12,14 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) consAddr := sdk.ConsAddress(req.Header.ProposerAddress) k.SetProposerConsAddr(ctx, consAddr) - // XXX TODO actually calculate this - k.SetSumPrecommitPower(ctx, sdk.NewDec(1)) + // determine the total number of signed power + sumPrecommitPower := int64(0) + for _, voteInfo := range req.LastCommitInfo.GetVotes() { + if voteInfo.SignedLastBlock { + sumPrecommitPower += voteInfo.Validator.Power + } + } + k.SetSumPrecommitPower(ctx, sumPrecommitPower) } // allocate fees diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 1acd3e7304..d80a6aac38 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -12,7 +12,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("allocation height: %v", ctx.BlockHeight())) // if there is no power in the system nothing should be allocated - bondedTokens := k.stakeKeeper.TotalPower(ctx) + bondedTokens := k.stakeKeeper.TotalPower(ctx).TruncateInt() if bondedTokens.IsZero() { return } @@ -29,8 +29,14 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // allocated rewards to proposer sumPowerPrecommitValidators := k.GetSumPrecommitPower(ctx) - proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul( - sumPowerPrecommitValidators).Quo(bondedTokens)) + percentVoting := sdk.NewDec(sumPowerPrecommitValidators).QuoInt(bondedTokens) + + // rare edge case for rounding tendermint power vs bonded decimal power + if percentVoting.GT(sdk.OneDec()) { + percentVoting = sdk.OneDec() + } + + proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul(percentVoting)) proposerReward := feesCollectedDec.MulDec(proposerMultiplier) // apply commission @@ -46,7 +52,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { feePool.CommunityPool = feePool.CommunityPool.Plus(communityFunding) // set the global pool within the distribution module - poolReceived := feesCollectedDec.MulDec(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax)) + poolReceived := feesCollectedDec.Minus(proposerReward).Minus(communityFunding) feePool.Pool = feePool.Pool.Plus(poolReceived) k.SetValidatorDistInfo(ctx, proposerDist) diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 773e3db063..e1da170fd8 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -42,7 +42,7 @@ func TestAllocateFeesBasic(t *testing.T) { fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // verify that these fees have been received by the feePool @@ -59,7 +59,6 @@ func TestAllocateFeesWithCommunityTax(t *testing.T) { //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) @@ -69,7 +68,7 @@ func TestAllocateFeesWithCommunityTax(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // verify that these fees have been received by the feePool @@ -86,8 +85,7 @@ func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) { denom := sk.GetParams(ctx).BondDenom //first make a validator - totalPower := int64(10) - totalPowerDec := sdk.NewDec(totalPower) + 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) @@ -97,7 +95,7 @@ func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec.Mul(sdk.NewDecWithPrec(25, 2))) // 25% precommit power + keeper.SetSumPrecommitPower(ctx, 25) // 25% precommit power keeper.AllocateFees(ctx) // verify that these fees have been received by the feePool diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index b41245f3b3..4319bf280c 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -27,14 +27,13 @@ func TestWithdrawDelegationRewardBasic(t *testing.T) { require.Equal(t, int64(90), amt.Int64()) totalPower := int64(20) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // withdraw delegation @@ -66,14 +65,13 @@ func TestWithdrawDelegationRewardWithCommission(t *testing.T) { require.Equal(t, int64(90), amt.Int64()) totalPower := int64(20) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // withdraw delegation @@ -111,14 +109,13 @@ func TestWithdrawDelegationRewardTwoDelegators(t *testing.T) { require.Equal(t, int64(80), amt.Int64()) totalPower := int64(40) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // delegator 1 withdraw delegation @@ -158,14 +155,13 @@ func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) { require.Equal(t, int64(90), amt.Int64()) totalPower := int64(30) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) ctx = ctx.WithBlockHeight(1) @@ -181,7 +177,7 @@ func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) { fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) ctx = ctx.WithBlockHeight(2) @@ -248,14 +244,13 @@ func TestWithdrawDelegationRewardsAll(t *testing.T) { // grand total: 160 totalPower := int64(160) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // withdraw delegation diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 6dd41e3262..bedda08bfb 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -82,7 +82,7 @@ func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { //______________________________________________________________________ // set the proposer public key for this block -func (k Keeper) GetSumPrecommitPower(ctx sdk.Context) (sumPrecommitPower sdk.Dec) { +func (k Keeper) GetSumPrecommitPower(ctx sdk.Context) (sumPrecommitPower int64) { tstore := ctx.KVStore(k.storeTKey) b := tstore.Get(SumPrecommitPowerKey) @@ -95,7 +95,7 @@ func (k Keeper) GetSumPrecommitPower(ctx sdk.Context) (sumPrecommitPower sdk.Dec } // get the proposer public key for this block -func (k Keeper) SetSumPrecommitPower(ctx sdk.Context, sumPrecommitPower sdk.Dec) { +func (k Keeper) SetSumPrecommitPower(ctx sdk.Context, sumPrecommitPower int64) { tstore := ctx.KVStore(k.storeTKey) b := k.cdc.MustMarshalBinary(sumPrecommitPower) tstore.Set(SumPrecommitPowerKey, b) diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go index ce9ceb8077..2a188bae36 100644 --- a/x/distribution/keeper/keeper_test.go +++ b/x/distribution/keeper/keeper_test.go @@ -19,10 +19,9 @@ func TestSetGetProposerConsAddr(t *testing.T) { func TestSetGetSumPrecommitPower(t *testing.T) { ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0) - someDec := sdk.NewDec(333) - keeper.SetSumPrecommitPower(ctx, someDec) + keeper.SetSumPrecommitPower(ctx, 333) res := keeper.GetSumPrecommitPower(ctx) - require.True(sdk.DecEq(t, someDec, res)) + require.Equal(t, int64(333), res) } func TestSetGetCommunityTax(t *testing.T) { diff --git a/x/distribution/keeper/validator_test.go b/x/distribution/keeper/validator_test.go index 32f5a26863..7dd79805e2 100644 --- a/x/distribution/keeper/validator_test.go +++ b/x/distribution/keeper/validator_test.go @@ -20,14 +20,13 @@ func TestWithdrawValidatorRewardsAllNoDelegator(t *testing.T) { _ = sk.ApplyAndReturnValidatorSetUpdates(ctx) totalPower := int64(10) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // withdraw self-delegation reward @@ -57,14 +56,13 @@ func TestWithdrawValidatorRewardsAllDelegatorNoCommission(t *testing.T) { require.Equal(t, int64(90), amt.Int64()) totalPower := int64(20) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // withdraw self-delegation reward @@ -96,14 +94,13 @@ func TestWithdrawValidatorRewardsAllDelegatorWithCommission(t *testing.T) { require.Equal(t, int64(90), amt.Int64()) totalPower := int64(20) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // withdraw validator reward @@ -141,14 +138,13 @@ func TestWithdrawValidatorRewardsAllMultipleValidator(t *testing.T) { _ = sk.ApplyAndReturnValidatorSetUpdates(ctx) totalPower := int64(100) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // withdraw validator reward @@ -192,14 +188,13 @@ func TestWithdrawValidatorRewardsAllMultipleDelegator(t *testing.T) { require.Equal(t, int64(80), amt.Int64()) totalPower := int64(40) - totalPowerDec := sdk.NewDec(totalPower) // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPowerDec) + keeper.SetSumPrecommitPower(ctx, totalPower) keeper.AllocateFees(ctx) // withdraw validator reward diff --git a/x/slashing/tick.go b/x/slashing/tick.go index 007d937887..03bd094afc 100644 --- a/x/slashing/tick.go +++ b/x/slashing/tick.go @@ -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) From fb78f1d0af10b0559cdea831335a5ad4bb96a2f1 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Oct 2018 02:29:59 +0900 Subject: [PATCH 89/99] add docs, fix GetSubspace, address comments rm Subspace.ptr --- docs/spec/params/README.md | 20 +++++++ docs/spec/params/keeper.md | 17 ++++++ docs/spec/params/subspace.md | 76 +++++++++++++++++++++++++ store/prefixstore_test.go | 4 -- x/params/doc.go | 35 ++++++------ x/params/keeper_test.go | 103 +++++++++++++++++++++++++--------- x/params/subspace/subspace.go | 37 ++++++------ x/params/subspace/table.go | 22 ++++++-- 8 files changed, 244 insertions(+), 70 deletions(-) create mode 100644 docs/spec/params/README.md create mode 100644 docs/spec/params/keeper.md create mode 100644 docs/spec/params/subspace.md diff --git a/docs/spec/params/README.md b/docs/spec/params/README.md new file mode 100644 index 0000000000..d9c8b9221f --- /dev/null +++ b/docs/spec/params/README.md @@ -0,0 +1,20 @@ +# Params module specification + +## Abstract + +Package params provides a globally available parameter store. + +There are two main types, Keeper and Subspace. Subspace is an isolated namespace for a +paramstore, where keys are prefixed by preconfigured spacename. Keeper has a +permission to access all existing spaces. + +Subspace can be used by the individual keepers, who needs a private parameter store +that the other keeper cannot modify. Keeper can be used by the Governance keeper, +who need to modify any parameter in case of the proposal passes. + +The following contents explains how to use params module for master and user modules. + +## Contents + +1. [Keeper](keeper.md) +1. [Subspace](subspace.md) diff --git a/docs/spec/params/keeper.md b/docs/spec/params/keeper.md new file mode 100644 index 0000000000..fe376911ed --- /dev/null +++ b/docs/spec/params/keeper.md @@ -0,0 +1,17 @@ +# Keeper + +In the app initialization stage, `Keeper.Subspace(Paramspace)` is passed to the user modules, and the subspaces are stored in `Keeper.spaces`. Later it can be retrieved with `Keeper.GetSubspace`, so the keepers holding `Keeper` can access to any subspace. For example, Gov module can take `Keeper` as its argument and modify parameter of any subspace when a `ParameterChangeProposal` is accepted. + +```go +type MasterKeeper struct { + pk params.Keeper +} + +func (k MasterKeeper) SetParam(ctx sdk.Context, space string, key string, param interface{}) { + space, ok := k.ps.GetSubspace(space) + if !ok { + return + } + space.Set(ctx, key, param) +} +``` diff --git a/docs/spec/params/subspace.md b/docs/spec/params/subspace.md new file mode 100644 index 0000000000..3781778982 --- /dev/null +++ b/docs/spec/params/subspace.md @@ -0,0 +1,76 @@ +# Subspace + +## Basic Usage + +First, declare parameter space and parameter keys for the module. Then include params.Subspace in the keeper. Since we prefix the keys with the spacename, it is recommended to use the same name with the module's. + +```go +const ( + DefaultParamspace = "mymodule" +) + +const ( + KeyParameter1 = "myparameter1" + KeyParameter2 = "myparameter2" +) + +type Keeper struct { + cdc *wire.Codec + key sdk.StoreKey + + ps params.Subspace +} +``` + +Pass a params.Subspace to NewKeeper with DefaultParamSubspace (or another) + +```go +app.myKeeper = mymodule.NewKeeper(cdc, key, app.paramStore.SubStore(mymodule.DefaultParamspace)) +``` + +`NewKeeper` should register a `TypeTable`, which defines a map from parameter keys from types. + +```go +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, space params.Subspace) Keeper { + return Keeper { + cdc: cdc, + key: key, + ps: space.WithTypeTable(ParamTypeTable()), + } +} +``` + +Now we can access to the paramstore using Paramstore Keys + +```go +var param MyStruct +k.ps.Get(KeyParameter1, ¶m) +k.ps.Set(KeyParameter2, param) +``` + +# Genesis Usage + +Declare a struct for parameters and make it implement params.ParamSet. It will then be able to be passed to SetParamSet. + +```go +type MyParams struct { + Parameter1 uint64 + Parameter2 string +} + +// Implements params.ParamSet +// KeyValuePairs must return the list of (ParamKey, PointerToTheField) +func (p *MyParams) KeyValuePairs() params.KeyValuePairs { + return params.KeyFieldPairs { + {KeyParameter1, &p.Parameter1}, + {KeyParameter2, &p.Parameter2}, + } +} + +func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) { + k.ps.SetParamSet(ctx, &data.params) +} +``` + +The method is pointer receiver because there could be a case that we read from the store and set the result to the struct. + diff --git a/store/prefixstore_test.go b/store/prefixstore_test.go index 8445991b6e..4e555292c3 100644 --- a/store/prefixstore_test.go +++ b/store/prefixstore_test.go @@ -119,10 +119,6 @@ func TestPrefixStoreIterate(t *testing.T) { } func incFirstByte(bz []byte) { - if bz[0] == byte(255) { - bz[0] = byte(0) - return - } bz[0]++ } diff --git a/x/params/doc.go b/x/params/doc.go index 06d6620b20..77b05273b3 100644 --- a/x/params/doc.go +++ b/x/params/doc.go @@ -3,18 +3,18 @@ package params /* Package params provides a globally available parameter store. -There are two main types, Keeper and Space. Space is an isolated namespace for a +There are two main types, Keeper and Subspace. Subspace is an isolated namespace for a paramstore, where keys are prefixed by preconfigured spacename. Keeper has a -permission to access all existing spaces and create new space. +permission to access all existing spaces. -Space can be used by the individual keepers, who needs a private parameter store -that the other keeper are not able to modify. Keeper can be used by the Governance -keeper, who need to modify any parameter in case of the proposal passes. +Subspace can be used by the individual keepers, who needs a private parameter store +that the other keeper cannot modify. Keeper can be used by the Governance keeper, +who need to modify any parameter in case of the proposal passes. Basic Usage: First, declare parameter space and parameter keys for the module. Then include -params.Store in the keeper. Since we prefix the keys with the spacename, it is +params.Subspace in the keeper. Since we prefix the keys with the spacename, it is recommended to use the same name with the module's. const ( @@ -33,26 +33,29 @@ recommended to use the same name with the module's. ps params.Subspace } -Pass a params.Store to NewKeeper with DefaultParamSpace (or another) +Pass a params.Subspace to NewKeeper with DefaultParamSubspace (or another) app.myKeeper = mymodule.NewKeeper(app.paramStore.SubStore(mymodule.DefaultParamspace)) Now we can access to the paramstore using Paramstore Keys + var param MyStruct k.ps.Get(KeyParameter1, ¶m) k.ps.Set(KeyParameter2, param) Genesis Usage: -Declare a struct for parameters and make it implement ParamStruct. It will then -be able to be passed to SetFromParamStruct. +Declare a struct for parameters and make it implement params.ParamSet. It will then +be able to be passed to SetParamSet. type MyParams struct { Parameter1 uint64 Parameter2 string } - func (p *MyParams) KeyFieldPairs() params.KeyFieldPairs { + // Implements params.ParamSet + // KeyValuePairs must return the list of (ParamKey, PointerToTheField) + func (p *MyParams) KeyValuePairs() params.KeyValuePairs { return params.KeyFieldPairs { {KeyParameter1, &p.Parameter1}, {KeyParameter2, &p.Parameter2}, @@ -60,26 +63,26 @@ be able to be passed to SetFromParamStruct. } func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) { - k.ps.SetFromParamStruct(ctx, &data.params) + k.ps.SetParamSet(ctx, &data.params) } The method is pointer receiver because there could be a case that we read from the store and set the result to the struct. -Master Permission Usage: +Master Keeper Usage: Keepers that require master permission to the paramstore, such as gov, can take -params.Keeper itself to access all substores(using GetSubstore) +params.Keeper itself to access all subspace(using GetSubspace) type MasterKeeper struct { - ps params.Store + pk params.Keeper } func (k MasterKeeper) SetParam(ctx sdk.Context, space string, key string, param interface{}) { - store, ok := k.ps.GetSubstore(space) + space, ok := k.ps.GetSubspace(space) if !ok { return } - store.Set(ctx, key, param) + space.Set(ctx, key, param) } */ diff --git a/x/params/keeper_test.go b/x/params/keeper_test.go index 640661a245..30584421f5 100644 --- a/x/params/keeper_test.go +++ b/x/params/keeper_test.go @@ -65,45 +65,82 @@ func TestKeeper(t *testing.T) { []byte("extra2"), string(""), ) + cdc := codec.New() skey := sdk.NewKVStoreKey("test") tkey := sdk.NewTransientStoreKey("transient_test") ctx := defaultContext(skey, tkey) - store := NewKeeper(codec.New(), skey, tkey).Subspace("test").WithTypeTable(table) + keeper := NewKeeper(cdc, skey, tkey) + space := keeper.Subspace("test").WithTypeTable(table) + store := ctx.KVStore(skey).Prefix([]byte("test/")) + // Set params for i, kv := range kvs { - require.NotPanics(t, func() { store.Set(ctx, []byte(kv.key), kv.param) }, "store.Set panics, tc #%d", i) + require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i) } + // Test space.Get for i, kv := range kvs { var param int64 - require.NotPanics(t, func() { store.Get(ctx, []byte(kv.key), ¶m) }, "store.Get panics, tc #%d", i) - require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) + require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "space.Get panics, tc #%d", i) + require.Equal(t, kv.param, param, "param not equal, tc #%d", i) } - cdc := codec.New() + // Test space.GetRaw for i, kv := range kvs { var param int64 - bz := store.GetRaw(ctx, []byte(kv.key)) + bz := space.GetRaw(ctx, []byte(kv.key)) err := cdc.UnmarshalJSON(bz, ¶m) require.Nil(t, err, "err is not nil, tc #%d", i) - require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) + require.Equal(t, kv.param, param, "param not equal, tc #%d", i) } + // Test store.Get equals space.Get + for i, kv := range kvs { + var param int64 + bz := store.Get([]byte(kv.key)) + require.NotNil(t, bz, "KVStore.Get returns nil, tc #%d", i) + err := cdc.UnmarshalJSON(bz, ¶m) + require.NoError(t, err, "UnmarshalJSON returns error, tc #%d", i) + require.Equal(t, kv.param, param, "param not equal, tc #%d", i) + } + + // Test invalid space.Get for i, kv := range kvs { var param bool - require.Panics(t, func() { store.Get(ctx, []byte(kv.key), ¶m) }, "invalid store.Get not panics, tc #%d", i) + require.Panics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "invalid space.Get not panics, tc #%d", i) } + // Test invalid space.Set for i, kv := range kvs { - require.Panics(t, func() { store.Set(ctx, []byte(kv.key), true) }, "invalid store.Set not panics, tc #%d", i) + require.Panics(t, func() { space.Set(ctx, []byte(kv.key), true) }, "invalid space.Set not panics, tc #%d", i) + } + + // Test GetSubspace + for i, kv := range kvs { + var gparam, param int64 + gspace, ok := keeper.GetSubspace("test") + require.True(t, ok, "cannot retrieve subspace, tc #%d", i) + + require.NotPanics(t, func() { gspace.Get(ctx, []byte(kv.key), &gparam) }) + require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }) + require.Equal(t, gparam, param, "GetSubspace().Get not equal with space.Get, tc #%d", i) + + require.NotPanics(t, func() { gspace.Set(ctx, []byte(kv.key), int64(i)) }) + require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }) + require.Equal(t, int64(i), param, "GetSubspace().Set not equal with space.Get, tc #%d", i) } } -func TestGet(t *testing.T) { +func indirect(ptr interface{}) interface{} { + return reflect.ValueOf(ptr).Elem().Interface() +} + +func TestSubspace(t *testing.T) { + cdc := createTestCodec() key := sdk.NewKVStoreKey("test") tkey := sdk.NewTransientStoreKey("transient_test") ctx := defaultContext(key, tkey) - keeper := NewKeeper(createTestCodec(), key, tkey) + keeper := NewKeeper(cdc, key, tkey) kvs := []struct { key string @@ -140,29 +177,41 @@ func TestGet(t *testing.T) { []byte("struct"), s{}, ) - store := keeper.Subspace("test").WithTypeTable(table) + store := ctx.KVStore(key).Prefix([]byte("test/")) + space := keeper.Subspace("test").WithTypeTable(table) + // Test space.Set, space.Modified for i, kv := range kvs { - require.False(t, store.Modified(ctx, []byte(kv.key)), "store.Modified returns true before setting, tc #%d", i) - require.NotPanics(t, func() { store.Set(ctx, []byte(kv.key), kv.param) }, "store.Set panics, tc #%d", i) - require.True(t, store.Modified(ctx, []byte(kv.key)), "store.Modified returns false after setting, tc #%d", i) + require.False(t, space.Modified(ctx, []byte(kv.key)), "space.Modified returns true before setting, tc #%d", i) + require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i) + require.True(t, space.Modified(ctx, []byte(kv.key)), "space.Modified returns false after setting, tc #%d", i) } + // Test space.Get, space.GetIfExists for i, kv := range kvs { - require.NotPanics(t, func() { store.GetIfExists(ctx, []byte("invalid"), kv.ptr) }, "store.GetIfExists panics when no value exists, tc #%d", i) - require.Equal(t, kv.zero, reflect.ValueOf(kv.ptr).Elem().Interface(), "store.GetIfExists unmarshalls when no value exists, tc #%d", i) - require.Panics(t, func() { store.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid store.Get not panics when no value exists, tc #%d", i) - require.Equal(t, kv.zero, reflect.ValueOf(kv.ptr).Elem().Interface(), "invalid store.Get unmarshalls when no value exists, tc #%d", i) + require.NotPanics(t, func() { space.GetIfExists(ctx, []byte("invalid"), kv.ptr) }, "space.GetIfExists panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "space.GetIfExists unmarshalls when no value exists, tc #%d", i) + require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "invalid space.Get unmarshalls when no value exists, tc #%d", i) - require.NotPanics(t, func() { store.GetIfExists(ctx, []byte(kv.key), kv.ptr) }, "store.GetIfExists panics, tc #%d", i) - require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface(), "stored param not equal, tc #%d", i) - require.NotPanics(t, func() { store.Get(ctx, []byte(kv.key), kv.ptr) }, "store.Get panics, tc #%d", i) - require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface(), "stored param not equal, tc #%d", i) + require.NotPanics(t, func() { space.GetIfExists(ctx, []byte(kv.key), kv.ptr) }, "space.GetIfExists panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "spaced param not equal, tc #%d", i) + require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), kv.ptr) }, "space.Get panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "spaced param not equal, tc #%d", i) - require.Panics(t, func() { store.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid store.Get not panics when no value exists, tc #%d", i) - require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface(), "invalid store.Get unmarshalls when no value existt, tc #%d", i) + require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "invalid space.Get unmarshalls when no value existt, tc #%d", i) - require.Panics(t, func() { store.Get(ctx, []byte(kv.key), nil) }, "invalid store.Get not panics when the pointer is nil, tc #%d", i) - require.Panics(t, func() { store.Get(ctx, []byte(kv.key), new(invalid)) }, "invalid store.Get not panics when the pointer is different type, tc #%d", i) + require.Panics(t, func() { space.Get(ctx, []byte(kv.key), nil) }, "invalid space.Get not panics when the pointer is nil, tc #%d", i) + require.Panics(t, func() { space.Get(ctx, []byte(kv.key), new(invalid)) }, "invalid space.Get not panics when the pointer is different type, tc #%d", i) + } + + // Test store.Get equals space.Get + for i, kv := range kvs { + bz := store.Get([]byte(kv.key)) + require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i) + err := cdc.UnmarshalJSON(bz, kv.ptr) + require.NoError(t, err, "cdc.UnmarshalJSON() returns error, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "param not equal, tc #%d", i) } } diff --git a/x/params/subspace/subspace.go b/x/params/subspace/subspace.go index 7c9ca5fdaa..fe5889a908 100644 --- a/x/params/subspace/subspace.go +++ b/x/params/subspace/subspace.go @@ -7,10 +7,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// Additional capicity to be allocated for Subspace.name -// So we don't have to allocate extra space each time appending to the key -const extraKeyCap = 20 - // Individual parameter store for each keeper // Transient store persists for a block, so we use it for // recording whether the parameter has been changed or not @@ -30,32 +26,35 @@ func NewSubspace(cdc *codec.Codec, key sdk.StoreKey, tkey sdk.StoreKey, name str cdc: cdc, key: key, tkey: tkey, + name: []byte(name), + table: TypeTable{ + m: make(map[string]reflect.Type), + }, } - namebz := []byte(name) - res.name = make([]byte, len(namebz), len(namebz)+extraKeyCap) - copy(res.name, namebz) return } // WithTypeTable initializes TypeTable and returns modified Subspace -func (s Subspace) WithTypeTable(table TypeTable) (res Subspace) { - if table == nil { +func (s Subspace) WithTypeTable(table TypeTable) Subspace { + if table.m == nil { panic("SetTypeTable() called with nil TypeTable") } - if s.table != nil { - panic("SetTypeTable() called on initialized Subspace") + if len(s.table.m) != 0 { + panic("SetTypeTable() called on already initialized Subspace") } - res = Subspace{ - cdc: s.cdc, - key: s.key, - tkey: s.tkey, - name: s.name, - table: table, + for k, v := range table.m { + s.table.m[k] = v } - return + // Allocate additional capicity for Subspace.name + // So we don't have to allocate extra space each time appending to the key + name := s.name + s.name = make([]byte, len(name), len(name)+table.maxKeyLength()) + copy(s.name, name) + + return s } // Returns a KVStore identical with ctx.KVStore(s.key).Prefix() @@ -118,7 +117,7 @@ func (s Subspace) Modified(ctx sdk.Context, key []byte) bool { func (s Subspace) Set(ctx sdk.Context, key []byte, param interface{}) { store := s.kvStore(ctx) - ty, ok := s.table[string(key)] + ty, ok := s.table.m[string(key)] if !ok { panic("Parameter not registered") } diff --git a/x/params/subspace/table.go b/x/params/subspace/table.go index 363d0243d2..628ebef477 100644 --- a/x/params/subspace/table.go +++ b/x/params/subspace/table.go @@ -5,7 +5,9 @@ import ( ) // TypeTable subspaces appropriate type for each parameter key -type TypeTable map[string]reflect.Type +type TypeTable struct { + m map[string]reflect.Type +} // Constructs new table func NewTypeTable(keytypes ...interface{}) (res TypeTable) { @@ -13,7 +15,9 @@ func NewTypeTable(keytypes ...interface{}) (res TypeTable) { panic("odd number arguments in NewTypeTypeTable") } - res = make(map[string]reflect.Type) + res = TypeTable{ + m: make(map[string]reflect.Type), + } for i := 0; i < len(keytypes); i += 2 { res = res.RegisterType(keytypes[i].([]byte), keytypes[i+1]) @@ -25,7 +29,7 @@ func NewTypeTable(keytypes ...interface{}) (res TypeTable) { // Register single key-type pair func (t TypeTable) RegisterType(key []byte, ty interface{}) TypeTable { keystr := string(key) - if _, ok := t[keystr]; ok { + if _, ok := t.m[keystr]; ok { panic("duplicate parameter key") } @@ -36,7 +40,7 @@ func (t TypeTable) RegisterType(key []byte, ty interface{}) TypeTable { rty = rty.Elem() } - t[keystr] = rty + t.m[keystr] = rty return t } @@ -48,3 +52,13 @@ func (t TypeTable) RegisterParamSet(ps ParamSet) TypeTable { } return t } + +func (t TypeTable) maxKeyLength() (res int) { + for k := range t.m { + l := len(k) + if l > res { + res = l + } + } + return +} From 73d83b02cb678c51db3e282d92f32a41ebcdf1c5 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Oct 2018 02:50:32 +0900 Subject: [PATCH 90/99] typo --- x/params/doc.go | 4 ++-- x/params/keeper_test.go | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/x/params/doc.go b/x/params/doc.go index 77b05273b3..bee45e79ec 100644 --- a/x/params/doc.go +++ b/x/params/doc.go @@ -33,7 +33,7 @@ recommended to use the same name with the module's. ps params.Subspace } -Pass a params.Subspace to NewKeeper with DefaultParamSubspace (or another) +Pass a params.Subspace to NewKeeper with DefaultParamspace (or another) app.myKeeper = mymodule.NewKeeper(app.paramStore.SubStore(mymodule.DefaultParamspace)) @@ -79,7 +79,7 @@ params.Keeper itself to access all subspace(using GetSubspace) } func (k MasterKeeper) SetParam(ctx sdk.Context, space string, key string, param interface{}) { - space, ok := k.ps.GetSubspace(space) + space, ok := k.pk.GetSubspace(space) if !ok { return } diff --git a/x/params/keeper_test.go b/x/params/keeper_test.go index 30584421f5..585db3c410 100644 --- a/x/params/keeper_test.go +++ b/x/params/keeper_test.go @@ -82,7 +82,7 @@ func TestKeeper(t *testing.T) { for i, kv := range kvs { var param int64 require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "space.Get panics, tc #%d", i) - require.Equal(t, kv.param, param, "param not equal, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) } // Test space.GetRaw @@ -91,7 +91,7 @@ func TestKeeper(t *testing.T) { bz := space.GetRaw(ctx, []byte(kv.key)) err := cdc.UnmarshalJSON(bz, ¶m) require.Nil(t, err, "err is not nil, tc #%d", i) - require.Equal(t, kv.param, param, "param not equal, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) } // Test store.Get equals space.Get @@ -101,7 +101,7 @@ func TestKeeper(t *testing.T) { require.NotNil(t, bz, "KVStore.Get returns nil, tc #%d", i) err := cdc.UnmarshalJSON(bz, ¶m) require.NoError(t, err, "UnmarshalJSON returns error, tc #%d", i) - require.Equal(t, kv.param, param, "param not equal, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) } // Test invalid space.Get @@ -195,9 +195,9 @@ func TestSubspace(t *testing.T) { require.Equal(t, kv.zero, indirect(kv.ptr), "invalid space.Get unmarshalls when no value exists, tc #%d", i) require.NotPanics(t, func() { space.GetIfExists(ctx, []byte(kv.key), kv.ptr) }, "space.GetIfExists panics, tc #%d", i) - require.Equal(t, kv.param, indirect(kv.ptr), "spaced param not equal, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), kv.ptr) }, "space.Get panics, tc #%d", i) - require.Equal(t, kv.param, indirect(kv.ptr), "spaced param not equal, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i) require.Equal(t, kv.param, indirect(kv.ptr), "invalid space.Get unmarshalls when no value existt, tc #%d", i) @@ -212,6 +212,6 @@ func TestSubspace(t *testing.T) { require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i) err := cdc.UnmarshalJSON(bz, kv.ptr) require.NoError(t, err, "cdc.UnmarshalJSON() returns error, tc #%d", i) - require.Equal(t, kv.param, indirect(kv.ptr), "param not equal, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) } } From 2ece2ff37cb71b73bfab0e918dcf9f1c6b9b3482 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 02:34:01 -0400 Subject: [PATCH 91/99] address @cwgoes comments --- cmd/gaia/app/app.go | 6 ++++-- docs/spec/distribution/end_block.md | 2 +- docs/spec/distribution/state.md | 2 +- x/distribution/abci_app.go | 12 ++++++++++-- x/distribution/keeper/allocation.go | 18 +++--------------- x/distribution/keeper/allocation_test.go | 6 +++--- x/distribution/keeper/delegation_test.go | 23 ++++++----------------- x/distribution/keeper/keeper.go | 12 ++++++------ x/distribution/keeper/keeper_test.go | 9 +++++---- x/distribution/keeper/key.go | 4 ++-- x/distribution/keeper/validator_test.go | 20 +++++--------------- 11 files changed, 46 insertions(+), 68 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 6faf486d34..1f85d79637 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -165,14 +165,16 @@ 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) // distribute rewards distr.EndBlocker(ctx, app.distrKeeper) + 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, diff --git a/docs/spec/distribution/end_block.md b/docs/spec/distribution/end_block.md index 2b74cd3e90..7f54ee9723 100644 --- a/docs/spec/distribution/end_block.md +++ b/docs/spec/distribution/end_block.md @@ -1,7 +1,7 @@ # End Block At each endblock, the fees received are allocated to the proposer, community fund, -and pool. When the validator is the proposer of the round, that +and global pool. When the validator is the proposer of the round, that validator (and their delegators) receives between 1% and 5% of fee rewards, the reserve community tax is then charged, then the remainder is distributed proportionally by voting power to all bonded validators independent of whether diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index 0909ac7584..576f5390ba 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -42,7 +42,7 @@ Validator distribution information for the relevant validator is updated each ti ```golang type ValidatorDistInfo struct { - FewPoolWithdrawalHeight int64 // last height this validator withdrew from the global fee 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) diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index e4a90fa5fc..2ac2c57c63 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -13,13 +13,21 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) k.SetProposerConsAddr(ctx, consAddr) // determine the total number of signed power - sumPrecommitPower := int64(0) + totalPower, sumPrecommitPower := int64(0), int64(0) for _, voteInfo := range req.LastCommitInfo.GetVotes() { + totalPower += voteInfo.Validator.Power if voteInfo.SignedLastBlock { sumPrecommitPower += voteInfo.Validator.Power } } - k.SetSumPrecommitPower(ctx, sumPrecommitPower) + + if totalPower == 0 { + k.SetPercentPrecommitVotes(ctx, sdk.ZeroDec()) + return + } + + percentPrecommitVotes := sdk.NewDec(sumPrecommitPower).Quo(sdk.NewDec(totalPower)) + k.SetPercentPrecommitVotes(ctx, percentPrecommitVotes) } // allocate fees diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index d80a6aac38..545285ae7e 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -11,12 +11,6 @@ import ( func (k Keeper) AllocateFees(ctx sdk.Context) { ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("allocation height: %v", ctx.BlockHeight())) - // if there is no power in the system nothing should be allocated - bondedTokens := k.stakeKeeper.TotalPower(ctx).TruncateInt() - if bondedTokens.IsZero() { - return - } - // get the proposer of this block proposerConsAddr := k.GetProposerConsAddr(ctx) proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) @@ -28,20 +22,14 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { feesCollectedDec := types.NewDecCoins(feesCollected) // allocated rewards to proposer - sumPowerPrecommitValidators := k.GetSumPrecommitPower(ctx) - percentVoting := sdk.NewDec(sumPowerPrecommitValidators).QuoInt(bondedTokens) + percentVotes := k.GetPercentPrecommitVotes(ctx) - // rare edge case for rounding tendermint power vs bonded decimal power - if percentVoting.GT(sdk.OneDec()) { - percentVoting = sdk.OneDec() - } - - proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul(percentVoting)) + proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul(percentVotes)) proposerReward := feesCollectedDec.MulDec(proposerMultiplier) // apply commission commission := proposerReward.MulDec(proposerValidator.GetCommission()) - remaining := proposerReward.MulDec(sdk.OneDec().Sub(proposerValidator.GetCommission())) + remaining := proposerReward.Minus(commission) proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission) proposerDist.Pool = proposerDist.Pool.Plus(remaining) diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index e1da170fd8..62c3e2d661 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -42,7 +42,7 @@ func TestAllocateFeesBasic(t *testing.T) { fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // verify that these fees have been received by the feePool @@ -68,7 +68,7 @@ func TestAllocateFeesWithCommunityTax(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // verify that these fees have been received by the feePool @@ -95,7 +95,7 @@ func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, 25) // 25% precommit power + keeper.SetPercentPrecommitVotes(ctx, sdk.NewDecWithPrec(25, 2)) keeper.AllocateFees(ctx) // verify that these fees have been received by the feePool diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 4319bf280c..3eecfafdd2 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -26,14 +26,12 @@ func TestWithdrawDelegationRewardBasic(t *testing.T) { amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) require.Equal(t, int64(90), amt.Int64()) - totalPower := int64(20) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // withdraw delegation @@ -64,14 +62,12 @@ func TestWithdrawDelegationRewardWithCommission(t *testing.T) { amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) require.Equal(t, int64(90), amt.Int64()) - totalPower := int64(20) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // withdraw delegation @@ -108,14 +104,12 @@ func TestWithdrawDelegationRewardTwoDelegators(t *testing.T) { amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom) require.Equal(t, int64(80), amt.Int64()) - totalPower := int64(40) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // delegator 1 withdraw delegation @@ -154,14 +148,12 @@ func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) { amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom) require.Equal(t, int64(90), amt.Int64()) - totalPower := int64(30) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) ctx = ctx.WithBlockHeight(1) @@ -177,7 +169,7 @@ func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) { fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) ctx = ctx.WithBlockHeight(2) @@ -240,17 +232,14 @@ func TestWithdrawDelegationRewardsAll(t *testing.T) { // validator 1: 10 (self) + 10 (delegator) = 20 // validator 2: 50 (self) + 20 (delegator) = 70 // validator 3: 40 (self) + 30 (delegator) = 70 - // // grand total: 160 - totalPower := int64(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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // withdraw delegation diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index bedda08bfb..74d05842c9 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -82,23 +82,23 @@ func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { //______________________________________________________________________ // set the proposer public key for this block -func (k Keeper) GetSumPrecommitPower(ctx sdk.Context) (sumPrecommitPower int64) { +func (k Keeper) GetPercentPrecommitVotes(ctx sdk.Context) (percentPrecommitVotes sdk.Dec) { tstore := ctx.KVStore(k.storeTKey) - b := tstore.Get(SumPrecommitPowerKey) + b := tstore.Get(PercentPrecommitVotesKey) if b == nil { panic("Proposer cons address was likely not set in begin block") } - k.cdc.MustUnmarshalBinary(b, &sumPrecommitPower) + k.cdc.MustUnmarshalBinary(b, &percentPrecommitVotes) return } // get the proposer public key for this block -func (k Keeper) SetSumPrecommitPower(ctx sdk.Context, sumPrecommitPower int64) { +func (k Keeper) SetPercentPrecommitVotes(ctx sdk.Context, percentPrecommitVotes sdk.Dec) { tstore := ctx.KVStore(k.storeTKey) - b := k.cdc.MustMarshalBinary(sumPrecommitPower) - tstore.Set(SumPrecommitPowerKey, b) + b := k.cdc.MustMarshalBinary(percentPrecommitVotes) + tstore.Set(PercentPrecommitVotesKey, b) } //______________________________________________________________________ diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go index 2a188bae36..b2ebb6581c 100644 --- a/x/distribution/keeper/keeper_test.go +++ b/x/distribution/keeper/keeper_test.go @@ -16,12 +16,13 @@ func TestSetGetProposerConsAddr(t *testing.T) { require.True(t, res.Equals(valConsAddr1), "expected: %v got: %v", valConsAddr1.String(), res.String()) } -func TestSetGetSumPrecommitPower(t *testing.T) { +func TestSetGetPercentPrecommitVotes(t *testing.T) { ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0) - keeper.SetSumPrecommitPower(ctx, 333) - res := keeper.GetSumPrecommitPower(ctx) - require.Equal(t, int64(333), res) + someDec := sdk.NewDec(333) + keeper.SetPercentPrecommitVotes(ctx, someDec) + res := keeper.GetPercentPrecommitVotes(ctx) + require.True(sdk.DecEq(t, someDec, res)) } func TestSetGetCommunityTax(t *testing.T) { diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index bd24bff031..3c667e7083 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -12,8 +12,8 @@ var ( DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info // transient - ProposerKey = []byte{0x00} // key for storing the proposer operator address - SumPrecommitPowerKey = []byte{0x01} // key for storing the power of the precommit validators + ProposerKey = []byte{0x00} // key for storing the proposer operator address + PercentPrecommitVotesKey = []byte{0x01} // key for storing the power of the precommit validators ) // nolint diff --git a/x/distribution/keeper/validator_test.go b/x/distribution/keeper/validator_test.go index 7dd79805e2..bdac19b93f 100644 --- a/x/distribution/keeper/validator_test.go +++ b/x/distribution/keeper/validator_test.go @@ -19,14 +19,12 @@ func TestWithdrawValidatorRewardsAllNoDelegator(t *testing.T) { require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) _ = sk.ApplyAndReturnValidatorSetUpdates(ctx) - totalPower := int64(10) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // withdraw self-delegation reward @@ -55,14 +53,12 @@ func TestWithdrawValidatorRewardsAllDelegatorNoCommission(t *testing.T) { amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) require.Equal(t, int64(90), amt.Int64()) - totalPower := int64(20) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // withdraw self-delegation reward @@ -93,14 +89,12 @@ func TestWithdrawValidatorRewardsAllDelegatorWithCommission(t *testing.T) { amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom) require.Equal(t, int64(90), amt.Int64()) - totalPower := int64(20) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // withdraw validator reward @@ -137,14 +131,12 @@ func TestWithdrawValidatorRewardsAllMultipleValidator(t *testing.T) { _ = sk.ApplyAndReturnValidatorSetUpdates(ctx) - totalPower := int64(100) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // withdraw validator reward @@ -187,14 +179,12 @@ func TestWithdrawValidatorRewardsAllMultipleDelegator(t *testing.T) { amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom) require.Equal(t, int64(80), amt.Int64()) - totalPower := int64(40) - // 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.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetSumPrecommitPower(ctx, totalPower) + keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) keeper.AllocateFees(ctx) // withdraw validator reward From 8c978d24769d29a369c0c8359febd8b66e03c66b Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 16 Oct 2018 03:02:48 +0900 Subject: [PATCH 92/99] add tests and restriction for TypeTable --- x/params/subspace/table.go | 17 ++++++++++++++++ x/params/subspace/table_test.go | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 x/params/subspace/table_test.go diff --git a/x/params/subspace/table.go b/x/params/subspace/table.go index 628ebef477..19e41da090 100644 --- a/x/params/subspace/table.go +++ b/x/params/subspace/table.go @@ -26,8 +26,25 @@ func NewTypeTable(keytypes ...interface{}) (res TypeTable) { return } +func isAlphaNumeric(key []byte) bool { + for _, b := range key { + if !((48 <= b && b <= 57) || // numeric + (65 <= b && b <= 90) || // upper case + (97 <= b && b <= 122)) { // lower case + return false + } + } + return true +} + // Register single key-type pair func (t TypeTable) RegisterType(key []byte, ty interface{}) TypeTable { + if len(key) == 0 { + panic("cannot register empty key") + } + if !isAlphaNumeric(key) { + panic("non alphanumeric parameter key") + } keystr := string(key) if _, ok := t.m[keystr]; ok { panic("duplicate parameter key") diff --git a/x/params/subspace/table_test.go b/x/params/subspace/table_test.go new file mode 100644 index 0000000000..8f9142e1ec --- /dev/null +++ b/x/params/subspace/table_test.go @@ -0,0 +1,35 @@ +package subspace + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +type testparams struct { + i int64 + b bool +} + +func (tp *testparams) KeyValuePairs() KeyValuePairs { + return KeyValuePairs{ + {[]byte("i"), &tp.i}, + {[]byte("b"), &tp.b}, + } +} + +func TestTypeTable(t *testing.T) { + table := NewTypeTable() + + require.Panics(t, func() { table.RegisterType([]byte(""), nil) }) + require.Panics(t, func() { table.RegisterType([]byte("!@#$%"), nil) }) + require.Panics(t, func() { table.RegisterType([]byte("hello,"), nil) }) + require.Panics(t, func() { table.RegisterType([]byte("hello"), nil) }) + + require.NotPanics(t, func() { table.RegisterType([]byte("hello"), bool(false)) }) + require.NotPanics(t, func() { table.RegisterType([]byte("world"), int64(0)) }) + require.Panics(t, func() { table.RegisterType([]byte("hello"), bool(false)) }) + + require.NotPanics(t, func() { table.RegisterParamSet(&testparams{}) }) + require.Panics(t, func() { table.RegisterParamSet(&testparams{}) }) +} From c903f39d1f548d820b240b8177ca51dc48a75f6c Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 16 Oct 2018 04:11:31 +0900 Subject: [PATCH 93/99] update PENDING --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index 0b4e63ff37..416dc00d7d 100644 --- a/PENDING.md +++ b/PENDING.md @@ -69,6 +69,7 @@ BREAKING CHANGES * [x/staking] \#2244 staking now holds a consensus-address-index instead of a consensus-pubkey-index * [x/staking] \#2236 more distribution hooks for distribution * [x/stake] \#2394 Split up UpdateValidator into distinct state transitions applied only in EndBlock + * [x/stake] Global Paramstore refactored * Tendermint * Update tendermint version from v0.23.0 to v0.25.0, notable changes From 2f4a01bcba59dd9c7e20d0fd9dfb438b7fc59e7d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 15:51:51 -0400 Subject: [PATCH 94/99] address @ValarDragon comments, param store update --- cmd/gaia/app/app.go | 4 ++-- types/decimal.go | 4 ---- x/distribution/alias.go | 5 +++-- x/distribution/genesis.go | 6 +++--- x/distribution/keeper/allocation_test.go | 23 ++++++++++++++++------- x/distribution/keeper/genesis.go | 6 +++--- x/distribution/keeper/keeper.go | 17 ++++++++++++----- x/distribution/keeper/key.go | 7 +++++-- x/distribution/keeper/test_common.go | 11 +++++++---- x/stake/handler_test.go | 4 ++-- 10 files changed, 53 insertions(+), 34 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index ddacefd1a4..d388081d88 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -111,8 +111,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio app.distrKeeper = distr.NewKeeper( app.cdc, app.keyDistr, app.tkeyDistr, - app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, - app.feeCollectionKeeper, + app.paramsKeeper.Subspace(distr.DefaultParamspace), + app.bankKeeper, app.stakeKeeper, app.feeCollectionKeeper, app.RegisterCodespace(stake.DefaultCodespace), ) app.slashingKeeper = slashing.NewKeeper( diff --git a/types/decimal.go b/types/decimal.go index bd3f340757..e9623995f0 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -244,10 +244,6 @@ func (d Dec) Quo(d2 Dec) Dec { // quotient func (d Dec) QuoInt(i Int) Dec { mul := new(big.Int).Quo(d.Int, i.i) - - if mul.BitLen() > 255+DecimalPrecisionBits { - panic("Int overflow") - } return Dec{mul} } diff --git a/x/distribution/alias.go b/x/distribution/alias.go index 5195c95060..7f14f82a45 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -12,7 +12,7 @@ type ( Hooks = keeper.Hooks DelegatorWithdrawInfo = types.DelegatorWithdrawInfo - DelegationDistInfo = types.DelegationDistInfo + DelegationDistInfo = types.DelegationDistInfo ValidatorDistInfo = types.ValidatorDistInfo TotalAccum = types.TotalAccum FeePool = types.FeePool @@ -34,9 +34,10 @@ var ( GetDelegatorWithdrawAddrKey = keeper.GetDelegatorWithdrawAddrKey FeePoolKey = keeper.FeePoolKey ValidatorDistInfoKey = keeper.ValidatorDistInfoKey - DelegationDistInfoKey = keeper.DelegationDistInfoKey + DelegationDistInfoKey = keeper.DelegationDistInfoKey DelegatorWithdrawInfoKey = keeper.DelegatorWithdrawInfoKey ProposerKey = keeper.ProposerKey + DefaultParamspace = keeper.DefaultParamspace InitialFeePool = types.InitialFeePool diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index 735c2a713c..2c44a03399 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -26,8 +26,8 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { feePool := keeper.GetFeePool(ctx) communityTax := keeper.GetCommunityTax(ctx) - vdis := keeper.GetAllVDIs(ctx) - ddis := keeper.GetAllDDIs(ctx) - dwis := keeper.GetAllDWIs(ctx) + vdis := keeper.GetAllValidatorDistInfos(ctx) + ddis := keeper.GetAllDelegationDistInfos(ctx) + dwis := keeper.GetAllDelegatorWithdrawInfos(ctx) return NewGenesisState(feePool, communityTax, vdis, ddis, dwis) } diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 62c3e2d661..453f16bca2 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -46,14 +46,17 @@ func TestAllocateFeesBasic(t *testing.T) { keeper.AllocateFees(ctx) // 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(sdk.NewDecWithPrec(95, 2)) // 5% goes to proposer + 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) { - ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.NewDecWithPrec(1, 2)) //1% + communityTax := sdk.NewDecWithPrec(1, 2) //1% + ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, communityTax) stakeHandler := stake.NewHandler(sk) denom := sk.GetParams(ctx).BondDenom @@ -74,13 +77,16 @@ func TestAllocateFeesWithCommunityTax(t *testing.T) { // verify that these fees have been received by the feePool feePool := keeper.GetFeePool(ctx) // 5% goes to proposer, 1% community tax - expRes := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(94, 2)) + 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) { - ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.NewDecWithPrec(1, 2)) //1% + communityTax := sdk.NewDecWithPrec(1, 2) + ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, communityTax) stakeHandler := stake.NewHandler(sk) denom := sk.GetParams(ctx).BondDenom @@ -95,13 +101,16 @@ func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.NewDecWithPrec(25, 2)) + percentPrecommitVotes := sdk.NewDecWithPrec(25, 2) + keeper.SetPercentPrecommitVotes(ctx, percentPrecommitVotes) keeper.AllocateFees(ctx) // verify that these fees have been received by the feePool feePool := keeper.GetFeePool(ctx) - // 1% + 4%*0.25 goes to proposer, 1% community tax - expRes := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(97, 2)) + // 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)) } diff --git a/x/distribution/keeper/genesis.go b/x/distribution/keeper/genesis.go index 4a34e5fdc7..06b153a51d 100644 --- a/x/distribution/keeper/genesis.go +++ b/x/distribution/keeper/genesis.go @@ -6,7 +6,7 @@ import ( ) // Get the set of all validator-distribution-info's with no limits, used during genesis dump -func (k Keeper) GetAllVDIs(ctx sdk.Context) (vdis []types.ValidatorDistInfo) { +func (k Keeper) GetAllValidatorDistInfos(ctx sdk.Context) (vdis []types.ValidatorDistInfo) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, ValidatorDistInfoKey) defer iterator.Close() @@ -20,7 +20,7 @@ func (k Keeper) GetAllVDIs(ctx sdk.Context) (vdis []types.ValidatorDistInfo) { } // Get the set of all delegator-distribution-info's with no limits, used during genesis dump -func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegationDistInfo) { +func (k Keeper) GetAllDelegationDistInfos(ctx sdk.Context) (ddis []types.DelegationDistInfo) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey) defer iterator.Close() @@ -34,7 +34,7 @@ func (k Keeper) GetAllDDIs(ctx sdk.Context) (ddis []types.DelegationDistInfo) { } // Get the set of all delegator-withdraw addresses with no limits, used during genesis dump -func (k Keeper) GetAllDWIs(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) { +func (k Keeper) GetAllDelegatorWithdrawInfos(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey) defer iterator.Close() diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 74d05842c9..67d0cea622 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -12,7 +12,7 @@ type Keeper struct { storeKey sdk.StoreKey storeTKey sdk.StoreKey cdc *codec.Codec - ps params.Setter + paramSpace params.Subspace bankKeeper types.BankKeeper stakeKeeper types.StakeKeeper feeCollectionKeeper types.FeeCollectionKeeper @@ -21,14 +21,14 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ps params.Setter, ck types.BankKeeper, +func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, paramSpace params.Subspace, ck types.BankKeeper, sk types.StakeKeeper, fck types.FeeCollectionKeeper, codespace sdk.CodespaceType) Keeper { keeper := Keeper{ storeKey: key, storeTKey: tkey, cdc: cdc, - ps: ps, + paramSpace: paramSpace.WithTypeTable(ParamTypeTable()), bankKeeper: ck, stakeKeeper: sk, feeCollectionKeeper: fck, @@ -104,15 +104,22 @@ func (k Keeper) SetPercentPrecommitVotes(ctx sdk.Context, percentPrecommitVotes //______________________________________________________________________ // PARAM STORE +// Type declaration for parameters +func ParamTypeTable() params.TypeTable { + return params.NewTypeTable( + ParamStoreKeyCommunityTax, sdk.Dec{}, + ) +} + // Returns the current CommunityTax rate from the global param store // nolint: errcheck func (k Keeper) GetCommunityTax(ctx sdk.Context) sdk.Dec { var communityTax sdk.Dec - k.ps.Get(ctx, ParamStoreKeyCommunityTax, &communityTax) + k.paramSpace.Get(ctx, ParamStoreKeyCommunityTax, &communityTax) return communityTax } // nolint: errcheck func (k Keeper) SetCommunityTax(ctx sdk.Context, communityTax sdk.Dec) { - k.ps.Set(ctx, ParamStoreKeyCommunityTax, &communityTax) + k.paramSpace.Set(ctx, ParamStoreKeyCommunityTax, &communityTax) } diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index 3c667e7083..e1fc44e77b 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -14,11 +14,14 @@ var ( // transient ProposerKey = []byte{0x00} // key for storing the proposer operator address PercentPrecommitVotesKey = []byte{0x01} // key for storing the power of the precommit validators + + // params store + ParamStoreKeyCommunityTax = []byte("distr/community-tax") ) -// nolint const ( - ParamStoreKeyCommunityTax = "distr/community-tax" + // default paramspace for params keeper + DefaultParamspace = "distr" ) // gets the key for the validator distribution info from address diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index 1a64811056..ec7fc0350e 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -90,6 +90,7 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64, keyAcc := sdk.NewKVStoreKey("acc") keyFeeCollection := sdk.NewKVStoreKey("fee") keyParams := sdk.NewKVStoreKey("params") + tkeyParams := sdk.NewTransientStoreKey("transient_params") db := dbm.NewMemDB() ms := store.NewCommitMultiStore(db) @@ -101,15 +102,18 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64, 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) - ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, log.NewNopLogger()) 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, stake.DefaultCodespace) + 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) @@ -126,8 +130,7 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64, } fck := DummyFeeCollectionKeeper{} - pk := params.NewKeeper(cdc, keyParams) - keeper := NewKeeper(cdc, keyDistr, tkeyDistr, pk.Setter(), ck, sk, fck, types.DefaultCodespace) + keeper := NewKeeper(cdc, keyDistr, tkeyDistr, pk.Subspace(DefaultParamspace), ck, sk, fck, types.DefaultCodespace) // set the distribution hooks on staking sk = sk.WithHooks(keeper.Hooks()) diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 188fa51bc1..127f6a3592 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -612,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) From 076053d5b9b3d9b1a20e7842246a5d11c730d54d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 16:12:42 -0400 Subject: [PATCH 95/99] proposer reward params to global param --- x/distribution/genesis.go | 5 +++- x/distribution/keeper/allocation.go | 5 ++-- x/distribution/keeper/keeper.go | 38 ++++++++++++++++++++++++---- x/distribution/keeper/key.go | 4 ++- x/distribution/keeper/test_common.go | 2 ++ x/distribution/types/genesis.go | 14 +++++++--- 6 files changed, 56 insertions(+), 12 deletions(-) diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index 2c44a03399..2872359c78 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -26,8 +26,11 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { 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, vdis, ddis, dwis) + return NewGenesisState(feePool, communityTax, baseProposerRewards, + bonusProposerRewards, vdis, ddis, dwis) } diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 545285ae7e..bd083adebe 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -23,8 +23,9 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { // allocated rewards to proposer percentVotes := k.GetPercentPrecommitVotes(ctx) - - proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul(percentVotes)) + baseProposerReward := k.GetBaseProposerReward(ctx) + bonusProposerReward := k.GetBonusProposerReward(ctx) + proposerMultiplier := baseProposerReward.Add(bonusProposerReward.Mul(percentVotes)) proposerReward := feesCollectedDec.MulDec(proposerMultiplier) // apply commission diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 67d0cea622..356e33312b 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -108,18 +108,46 @@ func (k Keeper) SetPercentPrecommitVotes(ctx sdk.Context, percentPrecommitVotes 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 communityTax sdk.Dec - k.paramSpace.Get(ctx, ParamStoreKeyCommunityTax, &communityTax) - return communityTax + var percent sdk.Dec + k.paramSpace.Get(ctx, ParamStoreKeyCommunityTax, &percent) + return percent } // nolint: errcheck -func (k Keeper) SetCommunityTax(ctx sdk.Context, communityTax sdk.Dec) { - k.paramSpace.Set(ctx, ParamStoreKeyCommunityTax, &communityTax) +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) } diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index e1fc44e77b..0f9644f777 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -16,7 +16,9 @@ var ( PercentPrecommitVotesKey = []byte{0x01} // key for storing the power of the precommit validators // params store - ParamStoreKeyCommunityTax = []byte("distr/community-tax") + ParamStoreKeyCommunityTax = []byte("community-tax") + ParamStoreKeyBaseProposerReward = []byte("base-proposer-reward") + ParamStoreKeyBonusProposerReward = []byte("bonus-proposer-reward") ) const ( diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index ec7fc0350e..871812a119 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -138,6 +138,8 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64, // 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 } diff --git a/x/distribution/types/genesis.go b/x/distribution/types/genesis.go index 9921818b2d..528295e5c2 100644 --- a/x/distribution/types/genesis.go +++ b/x/distribution/types/genesis.go @@ -13,17 +13,21 @@ type DelegatorWithdrawInfo struct { 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"` DelegationDistInfos []DelegationDistInfo `json:"delegator_dist_infos"` DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"` } -func NewGenesisState(feePool FeePool, communityTax sdk.Dec, +func NewGenesisState(feePool FeePool, communityTax, baseProposerReward, bonusProposerReward sdk.Dec, vdis []ValidatorDistInfo, ddis []DelegationDistInfo, dwis []DelegatorWithdrawInfo) GenesisState { return GenesisState{ FeePool: feePool, CommunityTax: communityTax, + BaseProposerReward: baseProposerReward, + BonusProposerReward: bonusProposerReward, ValidatorDistInfos: vdis, DelegationDistInfos: ddis, DelegatorWithdrawInfos: dwis, @@ -33,8 +37,10 @@ func NewGenesisState(feePool FeePool, communityTax sdk.Dec, // get raw genesis raw message for testing func DefaultGenesisState() GenesisState { return GenesisState{ - FeePool: InitialFeePool(), - CommunityTax: sdk.NewDecWithPrec(2, 2), // 2% + FeePool: InitialFeePool(), + CommunityTax: sdk.NewDecWithPrec(2, 2), // 2% + BaseProposerReward: sdk.NewDecWithPrec(1, 2), // 1% + BonusProposerReward: sdk.NewDecWithPrec(4, 2), // 4% } } @@ -53,6 +59,8 @@ func DefaultGenesisWithValidators(valAddrs []sdk.ValAddress) GenesisState { 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, } From eaecde27902d7cfdaaf22c1afba67248882f8693 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 16:52:39 -0400 Subject: [PATCH 96/99] test_utils >:( --- cmd/gaia/app/app_test.go | 2 ++ cmd/gaia/app/test_utils.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index d16cba40ea..7023eb09c1 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -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(), } diff --git a/cmd/gaia/app/test_utils.go b/cmd/gaia/app/test_utils.go index 32e4c70a59..18946b3972 100644 --- a/cmd/gaia/app/test_utils.go +++ b/cmd/gaia/app/test_utils.go @@ -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 From 03b92603ed45fb1f9fbdf9431ea2e138274d3d9d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 17:03:06 -0400 Subject: [PATCH 97/99] oh --- x/distribution/genesis.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index 2872359c78..4ee5651a67 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -9,6 +9,8 @@ import ( 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) From c0ce451003dae2c7bc2b5adc8a88f6940f2ac1c8 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 16 Oct 2018 03:06:31 +0200 Subject: [PATCH 98/99] Merge #2500: Block conflicting redelegations * Block conflicting redelegations * Update PENDING.md * Add conflicting redelegation testcase --- PENDING.md | 1 + x/stake/handler_test.go | 42 ++++++++++++++++++++++++++++++++++++ x/stake/keeper/delegation.go | 7 ++++++ x/stake/types/errors.go | 5 +++++ 4 files changed, 55 insertions(+) diff --git a/PENDING.md b/PENDING.md index 654e342f8c..eb61a5468e 100644 --- a/PENDING.md +++ b/PENDING.md @@ -70,6 +70,7 @@ BREAKING CHANGES * [x/staking] \#2236 more distribution hooks for distribution * [x/stake] \#2394 Split up UpdateValidator into distinct state transitions applied only in EndBlock * [x/stake] \#2412 Added an unbonding validator queue to EndBlock to automatically update validator.Status when finished Unbonding + * [x/stake] \#2500 Block conflicting redelegations until we add an index * [x/params] Global Paramstore refactored * Tendermint diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index de7aee90f4..f3d6ae5eb6 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -863,6 +863,48 @@ func TestTransitiveRedelegation(t *testing.T) { require.True(t, got.IsOK(), "expected no error") } +func TestConflictingRedelegation(t *testing.T) { + ctx, _, keeper := keep.CreateTestInput(t, false, 1000) + validatorAddr := sdk.ValAddress(keep.Addrs[0]) + validatorAddr2 := sdk.ValAddress(keep.Addrs[1]) + + // set the unbonding time + params := keeper.GetParams(ctx) + params.UnbondingTime = 1 + keeper.SetParams(ctx, params) + + // create the validators + 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) + got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + + // end block to bond them + EndBlocker(ctx, keeper) + + // begin redelegate + msgBeginRedelegate := NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, sdk.NewDec(5)) + got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.True(t, got.IsOK(), "expected no error, %v", got) + + // cannot redelegate again while first redelegation still exists + got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate) + + // progress forward in time + ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(10 * time.Second)) + + // complete first redelegation + EndBlocker(ctx, keeper) + + // now should be able to redelegate again + got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) + require.True(t, got.IsOK(), "expected no error") +} + func TestUnbondingWhenExcessValidators(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) validatorAddr1 := sdk.ValAddress(keep.Addrs[0]) diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 6f5a44ac05..52b9d85955 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -526,6 +526,13 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress, valAd func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount sdk.Dec) (types.Redelegation, sdk.Error) { + // check if there is already a redelgation in progress from src to dst + // TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402 + _, found := k.GetRedelegation(ctx, delAddr, valSrcAddr, valDstAddr) + if found { + return types.Redelegation{}, types.ErrConflictingRedelegation(k.Codespace()) + } + // check if this is a transitive redelegation if k.HasReceivingRedelegation(ctx, delAddr, valSrcAddr) { return types.Redelegation{}, types.ErrTransitiveRedelegation(k.Codespace()) diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 84a7e5ae68..e8c85800fe 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -164,6 +164,11 @@ func ErrTransitiveRedelegation(codespace sdk.CodespaceType) sdk.Error { "redelegation to this validator already in progress, first redelegation to this validator must complete before next redelegation") } +func ErrConflictingRedelegation(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidDelegation, + "conflicting redelegation from this source validator to this dest validator already exists, you must wait for it to finish") +} + func ErrBothShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "both shares amount and shares percent provided") } From 32e0f14de2aae7eb613025e13b53b32dde0ba33f Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 22:09:13 -0400 Subject: [PATCH 99/99] rework to correctly use previous vote info --- cmd/gaia/app/app.go | 7 ++--- x/distribution/abci_app.go | 28 ++++++++--------- x/distribution/keeper/allocation.go | 6 ++-- x/distribution/keeper/allocation_test.go | 12 ++----- x/distribution/keeper/delegation_test.go | 24 ++++---------- x/distribution/keeper/keeper.go | 40 +++++------------------- x/distribution/keeper/keeper_test.go | 15 ++------- x/distribution/keeper/key.go | 5 +-- x/distribution/keeper/test_common.go | 4 +-- x/distribution/keeper/validator_test.go | 20 +++--------- 10 files changed, 46 insertions(+), 115 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index d388081d88..2c72e3aaf9 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -110,7 +110,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio ) app.distrKeeper = distr.NewKeeper( app.cdc, - app.keyDistr, app.tkeyDistr, + app.keyDistr, app.paramsKeeper.Subspace(distr.DefaultParamspace), app.bankKeeper, app.stakeKeeper, app.feeCollectionKeeper, app.RegisterCodespace(stake.DefaultCodespace), @@ -178,6 +178,8 @@ func MakeCodec() *codec.Codec { // application updates every end block 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{ @@ -189,9 +191,6 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab // nolint: unparam func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { - // distribute rewards - distr.EndBlocker(ctx, app.distrKeeper) - tags := gov.EndBlocker(ctx, app.govKeeper) validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index 2ac2c57c63..2bdcadb6a3 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -9,8 +9,19 @@ import ( // 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.SetProposerConsAddr(ctx, consAddr) + 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) @@ -22,18 +33,7 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) } if totalPower == 0 { - k.SetPercentPrecommitVotes(ctx, sdk.ZeroDec()) - return + return sdk.ZeroDec() } - - percentPrecommitVotes := sdk.NewDec(sumPrecommitPower).Quo(sdk.NewDec(totalPower)) - k.SetPercentPrecommitVotes(ctx, percentPrecommitVotes) -} - -// allocate fees -func EndBlocker(ctx sdk.Context, k keeper.Keeper) { - if ctx.BlockHeight() < 2 { - return - } - k.AllocateFees(ctx) + return sdk.NewDec(sumPrecommitPower).Quo(sdk.NewDec(totalPower)) } diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index bd083adebe..e6dd1c9696 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -8,12 +8,11 @@ import ( ) // Allocate fees handles distribution of the collected fees -func (k Keeper) AllocateFees(ctx sdk.Context) { +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 - proposerConsAddr := k.GetProposerConsAddr(ctx) - proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr) + proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposer) proposerDist := k.GetValidatorDistInfo(ctx, proposerValidator.GetOperator()) // get the fees which have been getting collected through all the @@ -22,7 +21,6 @@ func (k Keeper) AllocateFees(ctx sdk.Context) { feesCollectedDec := types.NewDecCoins(feesCollected) // allocated rewards to proposer - percentVotes := k.GetPercentPrecommitVotes(ctx) baseProposerReward := k.GetBaseProposerReward(ctx) bonusProposerReward := k.GetBonusProposerReward(ctx) proposerMultiplier := baseProposerReward.Add(bonusProposerReward.Mul(percentVotes)) diff --git a/x/distribution/keeper/allocation_test.go b/x/distribution/keeper/allocation_test.go index 453f16bca2..441739ebe4 100644 --- a/x/distribution/keeper/allocation_test.go +++ b/x/distribution/keeper/allocation_test.go @@ -41,9 +41,7 @@ func TestAllocateFeesBasic(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // verify that these fees have been received by the feePool percentProposer := sdk.NewDecWithPrec(5, 2) @@ -70,9 +68,7 @@ func TestAllocateFeesWithCommunityTax(t *testing.T) { // allocate 100 denom of fees feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // verify that these fees have been received by the feePool feePool := keeper.GetFeePool(ctx) @@ -100,10 +96,8 @@ func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) { // allocate 100 denom of fees feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) - keeper.SetProposerConsAddr(ctx, valConsAddr1) percentPrecommitVotes := sdk.NewDecWithPrec(25, 2) - keeper.SetPercentPrecommitVotes(ctx, percentPrecommitVotes) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, percentPrecommitVotes, valConsAddr1) // verify that these fees have been received by the feePool feePool := keeper.GetFeePool(ctx) diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 3eecfafdd2..8415c708a9 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -30,9 +30,7 @@ func TestWithdrawDelegationRewardBasic(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // withdraw delegation ctx = ctx.WithBlockHeight(1) @@ -66,9 +64,7 @@ func TestWithdrawDelegationRewardWithCommission(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // withdraw delegation ctx = ctx.WithBlockHeight(1) @@ -108,9 +104,7 @@ func TestWithdrawDelegationRewardTwoDelegators(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // delegator 1 withdraw delegation ctx = ctx.WithBlockHeight(1) @@ -152,9 +146,7 @@ func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) { feeInputs := sdk.NewInt(90) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) ctx = ctx.WithBlockHeight(1) // delegator 1 withdraw delegation early, delegator 2 just keeps it's accum @@ -168,9 +160,7 @@ func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) { feeInputs = sdk.NewInt(180) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) ctx = ctx.WithBlockHeight(2) // delegator 2 now withdraws everything it's entitled to @@ -238,9 +228,7 @@ func TestWithdrawDelegationRewardsAll(t *testing.T) { feeInputs := sdk.NewInt(1000) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // withdraw delegation ctx = ctx.WithBlockHeight(1) diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 356e33312b..0ccf76ca63 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -10,7 +10,6 @@ import ( // keeper of the stake store type Keeper struct { storeKey sdk.StoreKey - storeTKey sdk.StoreKey cdc *codec.Codec paramSpace params.Subspace bankKeeper types.BankKeeper @@ -21,12 +20,11 @@ type Keeper struct { codespace sdk.CodespaceType } -func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, paramSpace params.Subspace, ck types.BankKeeper, +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, - storeTKey: tkey, cdc: cdc, paramSpace: paramSpace.WithTypeTable(ParamTypeTable()), bankKeeper: ck, @@ -60,12 +58,12 @@ func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.FeePool) { //______________________________________________________________________ // set the proposer public key for this block -func (k Keeper) GetProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress) { - tstore := ctx.KVStore(k.storeTKey) +func (k Keeper) GetPreviousProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress) { + store := ctx.KVStore(k.storeKey) - b := tstore.Get(ProposerKey) + b := store.Get(ProposerKey) if b == nil { - panic("Proposer cons address was likely not set in begin block") + panic("Previous proposer not set") } k.cdc.MustUnmarshalBinary(b, &consAddr) @@ -73,32 +71,10 @@ func (k Keeper) GetProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress) } // get the proposer public key for this block -func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { - tstore := ctx.KVStore(k.storeTKey) +func (k Keeper) SetPreviousProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) { + store := ctx.KVStore(k.storeKey) b := k.cdc.MustMarshalBinary(consAddr) - tstore.Set(ProposerKey, b) -} - -//______________________________________________________________________ - -// set the proposer public key for this block -func (k Keeper) GetPercentPrecommitVotes(ctx sdk.Context) (percentPrecommitVotes sdk.Dec) { - tstore := ctx.KVStore(k.storeTKey) - - b := tstore.Get(PercentPrecommitVotesKey) - if b == nil { - panic("Proposer cons address was likely not set in begin block") - } - - k.cdc.MustUnmarshalBinary(b, &percentPrecommitVotes) - return -} - -// get the proposer public key for this block -func (k Keeper) SetPercentPrecommitVotes(ctx sdk.Context, percentPrecommitVotes sdk.Dec) { - tstore := ctx.KVStore(k.storeTKey) - b := k.cdc.MustMarshalBinary(percentPrecommitVotes) - tstore.Set(PercentPrecommitVotesKey, b) + store.Set(ProposerKey, b) } //______________________________________________________________________ diff --git a/x/distribution/keeper/keeper_test.go b/x/distribution/keeper/keeper_test.go index b2ebb6581c..8244305113 100644 --- a/x/distribution/keeper/keeper_test.go +++ b/x/distribution/keeper/keeper_test.go @@ -8,23 +8,14 @@ import ( "github.com/stretchr/testify/require" ) -func TestSetGetProposerConsAddr(t *testing.T) { +func TestSetGetPreviousProposerConsAddr(t *testing.T) { ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - res := keeper.GetProposerConsAddr(ctx) + keeper.SetPreviousProposerConsAddr(ctx, valConsAddr1) + res := keeper.GetPreviousProposerConsAddr(ctx) require.True(t, res.Equals(valConsAddr1), "expected: %v got: %v", valConsAddr1.String(), res.String()) } -func TestSetGetPercentPrecommitVotes(t *testing.T) { - ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0) - - someDec := sdk.NewDec(333) - keeper.SetPercentPrecommitVotes(ctx, someDec) - res := keeper.GetPercentPrecommitVotes(ctx) - require.True(sdk.DecEq(t, someDec, res)) -} - func TestSetGetCommunityTax(t *testing.T) { ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0) diff --git a/x/distribution/keeper/key.go b/x/distribution/keeper/key.go index 0f9644f777..2e59890810 100644 --- a/x/distribution/keeper/key.go +++ b/x/distribution/keeper/key.go @@ -10,10 +10,7 @@ var ( 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 - - // transient - ProposerKey = []byte{0x00} // key for storing the proposer operator address - PercentPrecommitVotesKey = []byte{0x01} // key for storing the power of the precommit validators + ProposerKey = []byte{0x04} // key for storing the proposer operator address // params store ParamStoreKeyCommunityTax = []byte("community-tax") diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index 871812a119..59b615ec8a 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -84,7 +84,6 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64, sdk.Context, auth.AccountMapper, Keeper, stake.Keeper, DummyFeeCollectionKeeper) { keyDistr := sdk.NewKVStoreKey("distr") - tkeyDistr := sdk.NewTransientStoreKey("transient_distr") keyStake := sdk.NewKVStoreKey("stake") tkeyStake := sdk.NewTransientStoreKey("transient_stake") keyAcc := sdk.NewKVStoreKey("acc") @@ -95,7 +94,6 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64, db := dbm.NewMemDB() ms := store.NewCommitMultiStore(db) - ms.MountStoreWithDB(tkeyDistr, sdk.StoreTypeTransient, nil) ms.MountStoreWithDB(keyDistr, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil) ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db) @@ -130,7 +128,7 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64, } fck := DummyFeeCollectionKeeper{} - keeper := NewKeeper(cdc, keyDistr, tkeyDistr, pk.Subspace(DefaultParamspace), ck, sk, fck, types.DefaultCodespace) + keeper := NewKeeper(cdc, keyDistr, pk.Subspace(DefaultParamspace), ck, sk, fck, types.DefaultCodespace) // set the distribution hooks on staking sk = sk.WithHooks(keeper.Hooks()) diff --git a/x/distribution/keeper/validator_test.go b/x/distribution/keeper/validator_test.go index bdac19b93f..57c9a8b815 100644 --- a/x/distribution/keeper/validator_test.go +++ b/x/distribution/keeper/validator_test.go @@ -23,9 +23,7 @@ func TestWithdrawValidatorRewardsAllNoDelegator(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // withdraw self-delegation reward ctx = ctx.WithBlockHeight(1) @@ -57,9 +55,7 @@ func TestWithdrawValidatorRewardsAllDelegatorNoCommission(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // withdraw self-delegation reward ctx = ctx.WithBlockHeight(1) @@ -93,9 +89,7 @@ func TestWithdrawValidatorRewardsAllDelegatorWithCommission(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // withdraw validator reward ctx = ctx.WithBlockHeight(1) @@ -135,9 +129,7 @@ func TestWithdrawValidatorRewardsAllMultipleValidator(t *testing.T) { feeInputs := sdk.NewInt(1000) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // withdraw validator reward ctx = ctx.WithBlockHeight(1) @@ -183,9 +175,7 @@ func TestWithdrawValidatorRewardsAllMultipleDelegator(t *testing.T) { feeInputs := sdk.NewInt(100) fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)}) require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom)) - keeper.SetProposerConsAddr(ctx, valConsAddr1) - keeper.SetPercentPrecommitVotes(ctx, sdk.OneDec()) - keeper.AllocateFees(ctx) + keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1) // withdraw validator reward ctx = ctx.WithBlockHeight(1)