diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 751b84017..2dcfd3caf 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -101,9 +101,9 @@ func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) { // update the list ordered by voting power if oldFound { - store.Delete(GetValidatorKey(address, oldCandidate.Assets, k.cdc)) + store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorHeight, k.cdc)) } - store.Set(GetValidatorKey(address, validator.Power, k.cdc), bz) + store.Set(GetValidatorKey(address, validator.Power, validator.Height, k.cdc), bz) // add to the validators to update list if is already a validator // or is a new validator @@ -136,7 +136,7 @@ func (k Keeper) removeCandidate(ctx sdk.Context, address sdk.Address) { // delete the old candidate record store := ctx.KVStore(k.storeKey) store.Delete(GetCandidateKey(address)) - store.Delete(GetValidatorKey(address, candidate.Assets, k.cdc)) + store.Delete(GetValidatorKey(address, candidate.Assets, candidate.ValidatorHeight, k.cdc)) // delete from recent and power weighted validator groups if the validator // exists and add validator with zero power to the validator updates diff --git a/x/stake/keeper_keys.go b/x/stake/keeper_keys.go index 45e0570bc..ae8f9d733 100644 --- a/x/stake/keeper_keys.go +++ b/x/stake/keeper_keys.go @@ -1,6 +1,8 @@ package stake import ( + "encoding/binary" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" ) @@ -30,9 +32,11 @@ func GetCandidateKey(addr sdk.Address) []byte { } // get the key for the validator used in the power-store -func GetValidatorKey(addr sdk.Address, power sdk.Rat, cdc *wire.Codec) []byte { - powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) - return append(ValidatorsKey, append(powerBytes, addr.Bytes()...)...) +func GetValidatorKey(addr sdk.Address, power sdk.Rat, height uint64, cdc *wire.Codec) []byte { + powerBytes := []byte(power.ToLeftPadded(maxDigitsForAccount)) // power big-endian (more powerful validators first) + heightBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(heightBytes, height) // height little-endian (older validators first) + return append(ValidatorsKey, append(powerBytes, append(heightBytes, addr.Bytes()...)...)...) } // get the key for the accumulated update validators diff --git a/x/stake/types.go b/x/stake/types.go index 9f7d97ae5..7757566bf 100644 --- a/x/stake/types.go +++ b/x/stake/types.go @@ -59,12 +59,13 @@ const ( // exchange rate. Voting power can be calculated as total bonds multiplied by // exchange rate. type Candidate struct { - Status CandidateStatus `json:"status"` // Bonded status - Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here - PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate - Assets sdk.Rat `json:"assets"` // total shares of a global hold pools - Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators - Description Description `json:"description"` // Description terms for the candidate + Status CandidateStatus `json:"status"` // Bonded status + Address sdk.Address `json:"owner"` // Sender of BondTx - UnbondTx returns here + PubKey crypto.PubKey `json:"pub_key"` // Pubkey of candidate + Assets sdk.Rat `json:"assets"` // total shares of a global hold pools + Liabilities sdk.Rat `json:"liabilities"` // total shares issued to a candidate's delegators + Description Description `json:"description"` // Description terms for the candidate + ValidatorHeight uint64 `json:"validator_height"` // If considered a validator, height when first considered a validator, else 0 } // Candidates - list of Candidates @@ -73,12 +74,13 @@ type Candidates []Candidate // NewCandidate - initialize a new candidate func NewCandidate(address sdk.Address, pubKey crypto.PubKey, description Description) Candidate { return Candidate{ - Status: Unbonded, - Address: address, - PubKey: pubKey, - Assets: sdk.ZeroRat, - Liabilities: sdk.ZeroRat, - Description: description, + Status: Unbonded, + Address: address, + PubKey: pubKey, + Assets: sdk.ZeroRat, + Liabilities: sdk.ZeroRat, + Description: description, + ValidatorHeight: uint64(0), } } @@ -114,6 +116,7 @@ func (c Candidate) validator() Validator { Address: c.Address, PubKey: c.PubKey, Power: c.Assets, + Height: c.ValidatorHeight, } } @@ -127,6 +130,7 @@ type Validator struct { Address sdk.Address `json:"address"` PubKey crypto.PubKey `json:"pub_key"` Power sdk.Rat `json:"voting_power"` + Height uint64 `json:"height"` // If considered a validator, height when first considered a validator, else 0 } // abci validator from stake validator type