From 9a2aee87910c08f32ae71a3cf3ab46c205d6d275 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 3 Sep 2018 20:46:33 -0400 Subject: [PATCH 01/94] 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 000000000..da129855e --- /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 aba07eaca..000000000 --- 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 000000000..b55569d4a --- /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 000000000..b55569d4a --- /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 000000000..f4cf1e0f9 --- /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 890268060..000000000 --- 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 399a25a68..000000000 --- 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 223410471..000000000 --- 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 000000000..5a4ca9e2c --- /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/94] 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 0b89ae44e..861620620 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 da129855e..bd317b9c1 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 000000000..689ffabbf --- /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 b55569d4a..a5d6459ac 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 b55569d4a..75200d755 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 000000000..55914b59f --- /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 000000000..b3b3e2d60 --- /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 5a4ca9e2c..000000000 --- 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 000000000..8ca532d86 --- /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/94] 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/94] 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/94] 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 000000000..771572074 --- /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 bd317b9c1..39371610f 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 000000000..ce111b559 --- /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 000000000..72e96715b --- /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 a5d6459ac..c0bf48cea 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 75200d755..000000000 --- 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 000000000..9a057b85b --- /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 000000000..23e158488 --- /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 b3b3e2d60..000000000 --- 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 000000000..15a137718 --- /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 8ca532d86..4a1b1f86d 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 9a596ffbc..e4ec199ef 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/94] ... --- 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 39371610f..02fb1c3ed 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 ce111b559..43a99dfdb 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/94] ... --- 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 43a99dfdb..597be2adb 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/94] 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 952d1832a..2b74cd3e9 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 13a4ea3f1..28b1bbedd 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 3e3669789..e5c0d47d0 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 861620620..47b11165a 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 597be2adb..9f54b700e 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 c0bf48cea..741e3aa9a 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 000000000..1bc803530 --- /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 23e158488..1058db77c 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/94] 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 9f54b700e..76cee338b 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/94] 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 8e7db1340..d6c93f617 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 115eeacb0..b3e10b510 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 771572074..b794d08cb 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 02fb1c3ed..39371610f 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 72e96715b..4c0939aa3 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 9a057b85b..7643dd834 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 1bc803530..70fd4a582 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/94] ... --- 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 39371610f..c60294848 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 76cee338b..19d4e2e16 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/94] ... --- 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 5b2cdb155..46daf39dd 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 3e03a81aa..ef8754809 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 000000000..7edfc2cf0 --- /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 19d4e2e16..662d848b4 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 15a137718..7b0539216 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/94] ... --- 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 741e3aa9a..7cc2c1290 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 f4cf1e0f9..2b09573ad 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/94] 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 000000000..e70252a8d --- /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 7edfc2cf0..000000000 --- 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 689ffabbf..75f6be6d8 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 662d848b4..922d60989 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 4c0939aa3..d3f0602b9 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 7cc2c1290..13c5a0b73 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 7643dd834..5df5bb8f7 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 70fd4a582..4e6a4cfc3 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 55914b59f..1fda6dba7 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 1058db77c..072acb44d 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 c445e2552..91e6a6970 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 1f65aaa95..d651b0494 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/94] 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 da79a055a..39cb59694 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 0b9f32b4b..54fd564af 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 000000000..e3bf8d49a --- /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 000000000..1ff4a06d6 --- /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 c60294848..d2ef538fb 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 75f6be6d8..9a6f7cfbf 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 937a4674c..000000000 --- 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 d3f0602b9..5bf6793f1 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 000000000..dfc610924 --- /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 2b09573ad..f6f93464f 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 5df5bb8f7..7de71300c 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 1fda6dba7..c34fad077 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 072acb44d..14744689d 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 000000000..782f54ade --- /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 4a1b1f86d..8ca4c0387 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/94] 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 39cb59694..3213029e0 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 84f0ea7fa..d2a567fa4 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 54fd564af..68257689d 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 1ff4a06d6..f377750f8 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 9a6f7cfbf..3a4d8fbd2 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 7de71300c..ce73b2271 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 a3754f750..b9db3cbfb 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/94] 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 3213029e0..5b1dbd672 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 3a4d8fbd2..97be985f2 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 f5f3cc48c..8d519c794 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 bef723c4d..2e5191b2d 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 366012bbf..541ad3d7b 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/94] 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 47b11165a..c8c1080ad 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 e3bf8d49a..000000000 --- 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 d2ef538fb..1ae74ac78 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 ce73b2271..b8dece32c 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 000000000..dd55ba236 --- /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 000000000..84fee76a3 --- /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 000000000..3808752f1 --- /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 e7641393d..e1fb3edc0 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 ad2ab86f0..78e16de82 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 b9db3cbfb..cb76a9562 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 2e5191b2d..27f2547fd 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 aa4f64f8a..4921cdf8e 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/94] 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 b794d08cb..ca10471c6 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 d0e83ab3c..4c36be0b5 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/94] 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 c216bb2eb..166359201 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 ca10471c6..f9cd858bb 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 84fee76a3..ece45a004 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 3808752f1..ce77285c1 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/94] 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 d2a567fa4..3166a6cc2 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 000000000..a89375034 --- /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 f377750f8..045c840ed 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 922d60989..d6e586b60 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 13c5a0b73..ff5ab62cc 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 000000000..57a3dd73e --- /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/94] 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 05019f84a..0ad107b49 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 a89375034..898a07714 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 c34fad077..fc3dca729 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 8ca4c0387..9c962b7c0 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 27f2547fd..d2c314222 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/94] 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 0ad107b49..05019f84a 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 f9cd858bb..37330634e 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 ff5ab62cc..01f0ee078 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 ece45a004..edb121d20 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 4e6a4cfc3..f014e3615 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 14744689d..7c215fce2 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 782f54ade..a42f70594 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 7b0539216..3cf34da2a 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 ce77285c1..6b4997fef 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 9c962b7c0..5f8fa686b 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 cb76a9562..82170a4ae 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 e4c7a1c19..629791939 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 d2c314222..d0dbcc9e4 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/94] 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 68257689d..6012e4643 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 f014e3615..eef4f78a6 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 fc3dca729..eeb5af11d 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 7c215fce2..03725d7c1 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 5f8fa686b..b2f2592ea 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 7a004bccd..a7f849308 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 e1fb3edc0..2f563fdc0 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 78e16de82..6ac51ac19 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 629791939..d702e845d 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 52dbd21c7..e45c458f7 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 d0dbcc9e4..766f3fc8f 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 18b99fd4a..6b4036d28 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/94] 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 5a008ccec..468f94163 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 2f563fdc0..c9955f1bf 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 000000000..81bf5594b --- /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/94] ... --- 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 6012e4643..3d5969f9d 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 d6e586b60..a20055bbb 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 5bf6793f1..1323f2dbc 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 01f0ee078..bbf4c1541 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 eeb5af11d..4bb02e20c 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 3cf34da2a..b33e916b8 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 b2f2592ea..7c41b7e50 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 6c5066a78..d7463eb79 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/94] 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 3d5969f9d..4577e6047 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 e70252a8d..2ed9af0c0 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 a20055bbb..1c990dc4b 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 1323f2dbc..9913bfce5 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 dfc610924..ab010f277 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 97be985f2..e846acd26 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 bbf4c1541..31ce345b2 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 f6f93464f..771343f01 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 b8dece32c..f8e04f0cb 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 b33e916b8..14ea30dc0 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 a756eaf92..55fd81da2 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 38a94c369..57ac70a57 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/94] ... --- 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 5b1dbd672..d3692dce0 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 2ed9af0c0..648d70a5d 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 898a07714..920be5d3e 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 045c840ed..c7636c80c 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 1ae74ac78..661d7d32a 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 6b4997fef..a98892ee9 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/94] 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 d3692dce0..5b544af3e 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 166359201..61eeeeac8 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 920be5d3e..e7af73fba 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 37330634e..2cf293d89 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 1c990dc4b..8cc61dcad 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 9913bfce5..34caa5c1a 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 e846acd26..f13daf03a 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 f8e04f0cb..0b58ca68c 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 14ea30dc0..31a68a5da 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/94] 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 4577e6047..d97001cfb 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 c99674926..84964b20f 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 c43ed6be6..4f342f62a 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 468f94163..3506d2741 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 c9955f1bf..005b3af7d 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 d702e845d..9872630a4 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 e45c458f7..ea378678a 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 65bac2d80..caed72ff5 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 766f3fc8f..af7d77e20 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 d7463eb79..c15d43396 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/94] ... --- 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 5b544af3e..41f91c602 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 61eeeeac8..d178f0484 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 9f84786ad..fd5ec85b1 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 d97001cfb..ded771548 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 e7af73fba..80667b189 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 6c6d64aa6..9c5348b2c 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 8d519c794..701a6b2cd 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 3506d2741..e639182e1 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 ff50a594e..1d69f714f 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 81003a968..fe273be5e 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 70a21c171..4bc92c0b7 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 caed72ff5..0086b529c 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 e23d3b0aa..a541600d9 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/94] ... --- 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 0086b529c..c4a1edd41 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/94] 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 c43ed6be6..4f342f62a 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 f5f3cc48c..701a6b2cd 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 5a008ccec..e639182e1 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 ff50a594e..1d69f714f 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 81003a968..fe273be5e 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 d0e83ab3c..4c36be0b5 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 7a004bccd..a7f849308 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 e7641393d..005b3af7d 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 70a21c171..4bc92c0b7 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 ef09a307e..6ac51ac19 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 000000000..81bf5594b --- /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 a3754f750..82170a4ae 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 c445e2552..91e6a6970 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 e4c7a1c19..9872630a4 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 52dbd21c7..ea378678a 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 65bac2d80..c4a1edd41 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 996bf06bf..af7d77e20 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 e23d3b0aa..a541600d9 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 18b99fd4a..6b4036d28 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 aa4f64f8a..4921cdf8e 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 38a94c369..57ac70a57 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 366012bbf..541ad3d7b 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 6c5066a78..c15d43396 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/94] PENDING --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index e07319d49..d9b94175f 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/94] 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 0b9f32b4b..b8740a3cb 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 4cbd1d758..710ecb1db 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 58273c8e8..15f952c00 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 e8cdf49aa..84964b20f 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 8af2d1fd3..bebcf51e7 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 91c41d7d7..a61292b93 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 e453add79..f74091c74 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 e68069957..b4c678367 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 f46fe995e..168081b18 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 a756eaf92..55fd81da2 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 6c6d64aa6..9c5348b2c 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 6e2809bfc..43ae6b0d0 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 4f342f62a..740166d2a 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 701a6b2cd..92c4cf85f 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 a7f849308..58b7ed1b4 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 005b3af7d..f4864a14a 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 6ac51ac19..6efa4c8ed 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 81bf5594b..000000000 --- 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 82170a4ae..0f700f9ab 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 af7d77e20..d4fe76b70 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 c15d43396..38cc127b0 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/94] 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 b8740a3cb..ade96843d 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 710ecb1db..4cbd1d758 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 15f952c00..58273c8e8 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 84964b20f..00eaf3744 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 bebcf51e7..8af2d1fd3 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 a61292b93..91c41d7d7 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 f74091c74..e453add79 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 b4c678367..e68069957 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 168081b18..f46fe995e 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 9c5348b2c..6c6d64aa6 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/94] 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 9f84786ad..a54cdfedf 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 6c6d64aa6..9c5348b2c 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 544da50e3..985a22dca 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 1d69f714f..9a3ff537c 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 2ab071704..cdd80a8c4 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/94] 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 937a4674c..000000000 --- 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 890268060..000000000 --- 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 399a25a68..000000000 --- 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 223410471..000000000 --- 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 ea378678a..29adec06a 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 c4a1edd41..7d2f2f785 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 d4fe76b70..ef2256e08 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 a541600d9..356170189 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/94] 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 f2d6f9854..9d5e12923 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/94] 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 985a22dca..544da50e3 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 541ad3d7b..366012bbf 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/94] 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 9d5e12923..9454aca7d 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 ef2256e08..f7c43757f 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/94] 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 8e7db1340..d6c93f617 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 779460c25..161215467 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/94] pending --- PENDING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PENDING.md b/PENDING.md index 4d494f377..700abff64 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/94] ... --- PENDING.md | 1 - 1 file changed, 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index 700abff64..5cf80cd6f 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/94] 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 353825121..31b912a9d 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 ade96843d..03bf5e3bf 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 92c4cf85f..701a6b2cd 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 9a3ff537c..1d69f714f 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 f4864a14a..b3bf4c018 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 6efa4c8ed..a2392ac58 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 000000000..81bf5594b --- /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 0f700f9ab..82170a4ae 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 f7c43757f..69bab0f8e 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/94] pending --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index 5cf80cd6f..04b7b23f2 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/94] 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 000000000..bcc496e3d --- /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/94] 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 b3bf4c018..21800ffe2 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 a2392ac58..cc46646a7 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 69bab0f8e..6e9427d47 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/94] 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 58b694f5d..ae13b2ad0 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 ade96843d..e794ea734 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 9a3ff537c..d4b1af3d5 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 fe273be5e..8225c9634 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 f4864a14a..4d74c8a7b 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 9872630a4..d702e845d 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 7d2f2f785..0a6cccac2 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 f7c43757f..00d465cff 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 356170189..c21336f9f 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/94] 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 30cf1f17c..051ffa9e5 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/94] 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 406093cbd..b812e6a20 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/94] comment update --- types/decimal.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/decimal.go b/types/decimal.go index 79ada9559..13a494ba0 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/94] 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 fd5ec85b1..a54cdfedf 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 58b694f5d..ae13b2ad0 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 e2ec36876..6c6c78d6e 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 d6c93f617..13a494ba0 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 1d4900d3c..46bf748f4 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 ded771548..e794ea734 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 77364665a..1bd01b58a 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 059c0bb1c..3f62691c7 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 710ecb1db..27eff15f6 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 15f952c00..58273c8e8 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 84964b20f..3f8cd312b 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 bebcf51e7..80e5a205c 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 a61292b93..91c41d7d7 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 f74091c74..e453add79 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 b4c678367..37e29df70 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 000000000..1d5f2cf38 --- /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 f20bb46f7..606f73a9c 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 168081b18..d5ff1881e 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 35a11fb07..b0317d116 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 55fd81da2..c5751258a 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 9c5348b2c..28fe0cb59 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 497440a08..a3370b1d8 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 45b1b6471..94537c2eb 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 6e2809bfc..43ae6b0d0 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 4f342f62a..740166d2a 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 701a6b2cd..92c4cf85f 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 e639182e1..6a5fa3014 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 1d69f714f..d4b1af3d5 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 da9340baf..2b09226f2 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 db2293a2f..7c97a8537 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 fe273be5e..8225c9634 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 922ce8ac3..f96408c11 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 4c36be0b5..bec76298f 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 f91717328..74f4c6d6e 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 000000000..9aca2d899 --- /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 8d55bed8c..a8fbfecf4 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 b71684360..324e0c914 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 8ab565500..e7b8891ea 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 a7f849308..58b7ed1b4 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 005b3af7d..0524b2c11 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 4bc92c0b7..5780bf543 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 6ac51ac19..6efa4c8ed 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 82170a4ae..0f700f9ab 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 9872630a4..d702e845d 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 ea378678a..486dc3286 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 c4a1edd41..0a6cccac2 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 af7d77e20..9d8fb4362 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 a541600d9..73a391acc 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 2ab071704..cdd80a8c4 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 5b2bc1ee8..0cd4e08a9 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 53b9d826c..b81555f03 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 6b4036d28..7e60b3113 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 000000000..b76971faa --- /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 541ad3d7b..84a7e5ae6 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 fd181af3c..159ecb4c4 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 558c913fc..a313dd64f 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 eb66c0422..b5adbd0ad 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 c15d43396..051ffa9e5 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 eceffbad3..de9e18480 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/94] ... --- types/stake.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/stake.go b/types/stake.go index e794ea734..5a8a4fd43 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/94] 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 9acdb6764..84a82dba5 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/94] 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 8cc61dcad..4174f8b17 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/94] 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 ad9330ba9..749588c43 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 2cf293d89..d3fa22954 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 4174f8b17..03742fdac 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 f13daf03a..d503d54fb 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 31ce345b2..0803d2493 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 771343f01..6162baf6d 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 0b58ca68c..45ff70fd9 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 4bb02e20c..608ef68d4 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 7c41b7e50..1ea5fc27e 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 58b7ed1b4..cddb3fb57 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 cc46646a7..888fe1570 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/94] 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 3f6013822..24a5b9449 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 749588c43..9c07f895e 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 648d70a5d..57c10d013 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 03742fdac..4a2d82003 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 34caa5c1a..6aa0c4ee5 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 0803d2493..e49793ddc 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 6162baf6d..771343f01 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 45ff70fd9..baeb6ab31 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/94] 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 24a5b9449..f82880fd7 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 9c07f895e..5f5b542ef 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/94] 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 000000000..24af43b2e --- /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 000000000..3ea78cd79 --- /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 000000000..a18464be1 --- /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/94] 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 edb121d20..55d7c6cda 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 000000000..ee8aa30c0 --- /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 000000000..af89f40ca --- /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 000000000..e20d283b8 --- /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/94] 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 e20d283b8..fc14cb153 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/94] ... --- 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 1ea5fc27e..4a17e22ae 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/94] 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 13a8a26c1..a4d1e40ed 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 4a2d82003..3c4bd3971 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 eef4f78a6..df94d864d 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 ee8aa30c0..61de361ca 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 608ef68d4..e083cf2d4 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 03725d7c1..d373e0485 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 fc14cb153..1c2a804b4 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 24af43b2e..b0c0dd9eb 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 4a17e22ae..e32839046 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 a18464be1..44c5e5daa 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/94] 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 6aa0c4ee5..ab5b7c0a2 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 e083cf2d4..911fad9c9 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 af89f40ca..f1bcbb4ec 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 44c5e5daa..da3b2c10d 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/94] 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 911fad9c9..1a1bd4d9b 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 f1bcbb4ec..03803f8cd 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 e32839046..3092d1019 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/94] 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 55d7c6cda..10b2dc2fb 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 df94d864d..59373976d 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 61de361ca..5a326fa17 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 1a1bd4d9b..4de296890 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 03803f8cd..2d9e9bc0f 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 d373e0485..66731cb19 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 1c2a804b4..e39fb09c9 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 a42f70594..f01d1b781 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 a98892ee9..f00dceae1 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 3092d1019..18aef8bde 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 da3b2c10d..afa6d8c76 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/94] 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 57c10d013..bea9824c0 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 d3fa22954..b88968cda 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/94] 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 5f5b542ef..69f957ec9 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 c7636c80c..119c9b827 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 ab010f277..954c44336 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 e49793ddc..22932065b 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 f01d1b781..abce9dec4 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/94] 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 000000000..77daa1cf6 --- /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 000000000..36e44a629 --- /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 000000000..df25ef4e0 --- /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/94] 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 69f957ec9..6faf486d3 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 db08d872f..4f90ce8c6 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 e1a18ef59..8c2b4b91a 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 e5c0d47d0..0909ac758 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 c8c1080ad..821c4ba35 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 80667b189..5195c9506 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 119c9b827..735c2a713 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 ab5b7c0a2..0473a6693 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 954c44336..4a34e5fdc 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 d503d54fb..a408b0d21 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 771343f01..f4e18cf63 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 4de296890..f5b8978e5 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 2d9e9bc0f..516cbf99d 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 abce9dec4..9921818b2 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 fe46e1679..842ea1c27 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 0cd4e08a9..894a8cfee 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/94] ... --- 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 36e44a629..31e22b48f 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 000000000..3ea78cd79 --- /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/94] 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 000000000..01325863a --- /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 3ea78cd79..000000000 --- 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/94] ... --- 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 31e22b48f..863cb6ccf 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 01325863a..a98479442 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 059b19059..7de25268e 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 e32e7af5b..bd207b241 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 7c97a8537..f7f2e0b2f 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 a98d97c54..8bc4080c7 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 f96408c11..6bcb9c720 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 1802f30c1..dedbc3d80 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 0964f10de..0fd6eb7aa 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 7959679c6..7dcf8ccc9 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 e41b8203b..46ec67e7c 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 9b4dc3c55..6f14ba7a5 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 7bec2d962..61d4e0c87 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 000000000..40678c09c --- /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/94] 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 51705cbef..645f1d73c 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/94] 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 8f1eaa3f5..11d9eba26 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/94] 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 863cb6ccf..59c4259f3 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 a98479442..37c1b0d4b 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 3ea78cd79..b77efd46c 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/94] 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 59c4259f3..98749c2b8 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 a408b0d21..721a26db1 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 37c1b0d4b..95921068b 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/94] 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 cb5958c5c..e038337f4 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 9cced9ab8..0b634be87 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 3c4bd3971..1acd3e730 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 77daa1cf6..7e4f8a32f 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 98749c2b8..8ff99e411 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 22932065b..9c3949b8b 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 f4e18cf63..bd24bff03 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 95921068b..1a6481105 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/94] 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 1acd3e730..2e8681c5a 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 7e4f8a32f..00c06ae88 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 721a26db1..a1f73d39c 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 000000000..ce9ceb807 --- /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/94] 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 2e8681c5a..1acd3e730 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 00c06ae88..773e3db06 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 a1f73d39c..721a26db1 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 9c3949b8b..6dd41e326 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/94] 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 8ff99e411..2e085cf20 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/94] 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 2e085cf20..df598c0ed 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 236718289..9078ab31b 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 40678c09c..49bac0f31 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/94] 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 1421a934d..c2bef7a64 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 1acd3e730..92863052a 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 0473a6693..0bcaa69e4 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 df598c0ed..047d5bccd 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 baeb6ab31..ae07d8b3f 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/94] 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 92863052a..1acd3e730 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 0bcaa69e4..b7443a0c1 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 047d5bccd..b41245f3b 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/94] 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 ae07d8b3f..9ddfbce56 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 df25ef4e0..5db9841f2 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/94] 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 9ddfbce56..ae07d8b3f 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 5db9841f2..32f5a2686 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/94] 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 a4d1e40ed..bd3f34075 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 0b634be87..e4a90fa5f 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 1acd3e730..d80a6aac3 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 773e3db06..e1da170fd 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 b41245f3b..4319bf280 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 6dd41e326..bedda08bf 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 ce9ceb807..2a188bae3 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 32f5a2686..7dd79805e 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 007d93788..03bd094af 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 2ece2ff37cb71b73bfab0e918dcf9f1c6b9b3482 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 02:34:01 -0400 Subject: [PATCH 89/94] 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 6faf486d3..1f85d7963 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 2b74cd3e9..7f54ee972 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 0909ac758..576f5390b 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 e4a90fa5f..2ac2c57c6 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 d80a6aac3..545285ae7 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 e1da170fd..62c3e2d66 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 4319bf280..3eecfafdd 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 bedda08bf..74d05842c 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 2a188bae3..b2ebb6581 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 bd24bff03..3c667e708 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 7dd79805e..bdac19b93 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 2f4a01bcba59dd9c7e20d0fd9dfb438b7fc59e7d Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 15:51:51 -0400 Subject: [PATCH 90/94] 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 ddacefd1a..d388081d8 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 bd3f34075..e9623995f 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 5195c9506..7f14f82a4 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 735c2a713..2c44a0339 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 62c3e2d66..453f16bca 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 4a34e5fdc..06b153a51 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 74d05842c..67d0cea62 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 3c667e708..e1fc44e77 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 1a6481105..ec7fc0350 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 188fa51bc..127f6a359 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 91/94] 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 2c44a0339..2872359c7 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 545285ae7..bd083adeb 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 67d0cea62..356e33312 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 e1fc44e77..0f9644f77 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 ec7fc0350..871812a11 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 9921818b2..528295e5c 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 92/94] 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 d16cba40e..7023eb09c 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 32e4c70a5..18946b397 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 93/94] oh --- x/distribution/genesis.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index 2872359c7..4ee5651a6 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 32e0f14de2aae7eb613025e13b53b32dde0ba33f Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 15 Oct 2018 22:09:13 -0400 Subject: [PATCH 94/94] 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 d388081d8..2c72e3aaf 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 2ac2c57c6..2bdcadb6a 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 bd083adeb..e6dd1c969 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 453f16bca..441739ebe 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 3eecfafdd..8415c708a 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 356e33312..0ccf76ca6 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 b2ebb6581..824430511 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 0f9644f77..2e5989081 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 871812a11..59b615ec8 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 bdac19b93..57c9a8b81 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)