Distr-PR-1 Staking ConsPubKey -> ConsAddr index (#2369)
* pulling in stuff from fee-distr PR * revert some gov changes * fix using cons address, also remove old commented distr code * doc update * val comments * remove GetValidatorByConsPubKey
This commit is contained in:
parent
1a5d122c93
commit
6b595842ed
|
@ -51,6 +51,7 @@ BREAKING CHANGES
|
|||
* [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.
|
||||
* [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
|
||||
|
||||
* Tendermint
|
||||
|
||||
|
|
|
@ -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 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)`
|
||||
- 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)
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 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(),
|
||||
}
|
||||
}
|
||||
|
@ -67,14 +68,14 @@ 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
|
||||
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, 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 +88,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
|
||||
|
|
|
@ -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)
|
||||
//}
|
|
@ -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)
|
||||
//}
|
|
@ -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
|
||||
//}
|
|
@ -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...)
|
||||
//}
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -444,7 +444,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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.GetConsPubKey().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()))
|
||||
|
||||
|
|
|
@ -22,25 +22,26 @@ 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.ValidatorHooks = 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) ValidatorHooks() 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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -18,8 +18,11 @@ 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
|
||||
|
@ -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())
|
||||
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())
|
||||
|
@ -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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val))
|
||||
require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64())
|
||||
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ func TestBeginBlocker(t *testing.T) {
|
|||
}
|
||||
|
||||
// validator should be jailed
|
||||
validator, found := sk.GetValidatorByPubKey(ctx, pk)
|
||||
validator, found := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk))
|
||||
require.True(t, found)
|
||||
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
||||
}
|
||||
|
|
|
@ -58,8 +58,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")
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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(),
|
||||
})
|
||||
|
|
|
@ -68,7 +68,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
|
|||
return ErrValidatorOwnerExists(k.Codespace()).Result()
|
||||
}
|
||||
|
||||
_, found = k.GetValidatorByPubKey(ctx, msg.PubKey)
|
||||
_, found = k.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(msg.PubKey))
|
||||
if found {
|
||||
return ErrValidatorPubKeyExists(k.Codespace()).Result()
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
|
|||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -84,8 +84,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
|
||||
|
@ -201,11 +202,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)
|
||||
|
||||
|
@ -267,7 +269,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)
|
||||
|
@ -914,6 +916,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)
|
||||
|
@ -947,7 +950,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)
|
||||
|
@ -971,7 +974,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)
|
||||
|
|
|
@ -66,6 +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) {
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr))
|
||||
}
|
||||
|
|
|
@ -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.ValidatorHooks
|
||||
|
||||
// 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) WithValidatorHooks(sh sdk.ValidatorHooks) Keeper {
|
||||
if k.hooks != nil {
|
||||
panic("cannot set validator hooks twice")
|
||||
}
|
||||
k.validatorHooks = v
|
||||
k.hooks = sh
|
||||
return k
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
@ -95,15 +93,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
|
||||
}
|
||||
|
|
|
@ -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, 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
|
||||
|
|
|
@ -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)
|
||||
|
@ -27,7 +28,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 +43,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 +51,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 +180,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 +210,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 +228,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 +242,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 +252,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 +262,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 +272,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 +282,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 +292,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 +304,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 +344,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 +358,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 +368,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 +382,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 +404,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 +426,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 +473,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.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(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 +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.GetValidatorByPubKey(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())
|
||||
|
|
|
@ -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"
|
||||
|
@ -58,14 +57,14 @@ 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)
|
||||
}
|
||||
|
||||
// set the main record holding validator details
|
||||
|
@ -76,9 +75,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.ConsPubKey.Address())
|
||||
store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr)
|
||||
}
|
||||
|
||||
// validator index
|
||||
|
@ -622,8 +622,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 +657,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
|
||||
|
@ -678,7 +678,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
|
||||
|
|
|
@ -262,12 +262,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)
|
||||
|
@ -306,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]))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -36,7 +36,7 @@ var (
|
|||
NewKeeper = keeper.NewKeeper
|
||||
|
||||
GetValidatorKey = keeper.GetValidatorKey
|
||||
GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey
|
||||
GetValidatorByConsAddrKey = keeper.GetValidatorByConsAddrKey
|
||||
GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey
|
||||
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
|
||||
GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey
|
||||
|
@ -45,7 +45,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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -450,12 +450,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) 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.Rate }
|
||||
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
|
||||
func (v Validator) GetBondHeight() int64 { return v.BondHeight }
|
||||
|
|
Loading…
Reference in New Issue