2018-03-20 06:56:07 -07:00
|
|
|
package stake
|
|
|
|
|
|
|
|
import (
|
2018-03-28 11:12:21 -07:00
|
|
|
"bytes"
|
|
|
|
|
2018-03-20 06:56:07 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/wire"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
2018-04-04 20:22:13 -07:00
|
|
|
abci "github.com/tendermint/abci/types"
|
2018-03-20 06:56:07 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// keeper of the staking store
|
|
|
|
type Keeper struct {
|
|
|
|
storeKey sdk.StoreKey
|
|
|
|
cdc *wire.Codec
|
2018-04-18 21:49:24 -07:00
|
|
|
coinKeeper bank.Keeper
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// caches
|
2018-04-30 14:21:14 -07:00
|
|
|
pool Pool
|
2018-03-20 06:56:07 -07:00
|
|
|
params Params
|
2018-04-17 19:16:21 -07:00
|
|
|
|
|
|
|
// codespace
|
|
|
|
codespace sdk.CodespaceType
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-04-18 21:49:24 -07:00
|
|
|
func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
|
2018-03-20 06:56:07 -07:00
|
|
|
keeper := Keeper{
|
|
|
|
storeKey: key,
|
|
|
|
cdc: cdc,
|
|
|
|
coinKeeper: ck,
|
2018-04-17 19:16:21 -07:00
|
|
|
codespace: codespace,
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
return keeper
|
|
|
|
}
|
|
|
|
|
2018-04-19 05:09:12 -07:00
|
|
|
// get the current in-block validator operation counter
|
|
|
|
func (k Keeper) getCounter(ctx sdk.Context) int16 {
|
2018-04-16 04:22:05 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
b := store.Get(CounterKey)
|
|
|
|
if b == nil {
|
|
|
|
return 0
|
|
|
|
}
|
2018-04-19 05:09:12 -07:00
|
|
|
var counter int16
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(b, &counter)
|
2018-04-16 04:22:05 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return counter
|
|
|
|
}
|
|
|
|
|
2018-04-19 05:09:12 -07:00
|
|
|
// set the current in-block validator operation counter
|
|
|
|
func (k Keeper) setCounter(ctx sdk.Context, counter int16) {
|
2018-04-16 04:22:05 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-05-01 13:41:04 -07:00
|
|
|
bz, err := k.cdc.MarshalBinary(counter)
|
2018-04-16 04:22:05 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
store.Set(CounterKey, bz)
|
|
|
|
}
|
|
|
|
|
2018-03-22 09:00:45 -07:00
|
|
|
//_________________________________________________________________________
|
|
|
|
|
2018-03-22 10:10:25 -07:00
|
|
|
// get a single candidate
|
|
|
|
func (k Keeper) GetCandidate(ctx sdk.Context, addr sdk.Address) (candidate Candidate, found bool) {
|
2018-03-20 14:21:18 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-03-20 06:56:07 -07:00
|
|
|
b := store.Get(GetCandidateKey(addr))
|
|
|
|
if b == nil {
|
2018-03-20 14:21:18 -07:00
|
|
|
return candidate, false
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(b, &candidate)
|
2018-03-20 06:56:07 -07:00
|
|
|
if err != nil {
|
2018-03-20 14:21:18 -07:00
|
|
|
panic(err)
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
2018-03-20 14:21:18 -07:00
|
|
|
return candidate, true
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-04-24 06:46:39 -07:00
|
|
|
// Get the set of all candidates, retrieve a maxRetrieve number of records
|
2018-03-22 10:10:25 -07:00
|
|
|
func (k Keeper) GetCandidates(ctx sdk.Context, maxRetrieve int16) (candidates Candidates) {
|
2018-03-22 09:00:45 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-03-22 14:47:57 -07:00
|
|
|
iterator := store.Iterator(subspace(CandidatesKey))
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-03-22 09:00:45 -07:00
|
|
|
candidates = make([]Candidate, maxRetrieve)
|
|
|
|
i := 0
|
|
|
|
for ; ; i++ {
|
2018-04-24 06:46:39 -07:00
|
|
|
if !iterator.Valid() || i > int(maxRetrieve-1) {
|
2018-03-22 09:00:45 -07:00
|
|
|
iterator.Close()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
bz := iterator.Value()
|
|
|
|
var candidate Candidate
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(bz, &candidate)
|
2018-03-22 09:00:45 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
candidates[i] = candidate
|
|
|
|
iterator.Next()
|
|
|
|
}
|
|
|
|
return candidates[:i] // trim
|
|
|
|
}
|
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
func (k Keeper) setCandidate(ctx sdk.Context, candidate Candidate) {
|
2018-03-20 14:21:18 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-03-22 14:47:57 -07:00
|
|
|
address := candidate.Address
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// retreive the old candidate record
|
|
|
|
oldCandidate, oldFound := k.GetCandidate(ctx, address)
|
|
|
|
|
2018-04-16 04:22:05 -07:00
|
|
|
// if found, copy the old block height and counter
|
|
|
|
if oldFound {
|
2018-04-19 05:09:12 -07:00
|
|
|
candidate.ValidatorBondHeight = oldCandidate.ValidatorBondHeight
|
|
|
|
candidate.ValidatorBondCounter = oldCandidate.ValidatorBondCounter
|
2018-04-16 04:22:05 -07:00
|
|
|
}
|
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// marshal the candidate record and add to the state
|
2018-05-01 13:41:04 -07:00
|
|
|
bz, err := k.cdc.MarshalBinary(candidate)
|
2018-03-20 06:56:07 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-03-22 14:47:57 -07:00
|
|
|
store.Set(GetCandidateKey(candidate.Address), bz)
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-04-02 11:37:35 -07:00
|
|
|
// if the voting power is the same no need to update any of the other indexes
|
|
|
|
if oldFound && oldCandidate.Assets.Equal(candidate.Assets) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-04-16 04:22:05 -07:00
|
|
|
updateHeight := false
|
|
|
|
|
2018-03-20 06:56:07 -07:00
|
|
|
// update the list ordered by voting power
|
2018-03-22 14:47:57 -07:00
|
|
|
if oldFound {
|
2018-04-16 04:22:05 -07:00
|
|
|
if !k.isNewValidator(ctx, store, candidate.Address) {
|
|
|
|
updateHeight = true
|
2018-04-12 03:37:38 -07:00
|
|
|
}
|
2018-04-16 04:22:05 -07:00
|
|
|
// else already in the validator set - retain the old validator height and counter
|
2018-04-19 05:09:12 -07:00
|
|
|
store.Delete(GetValidatorKey(address, oldCandidate.Assets, oldCandidate.ValidatorBondHeight, oldCandidate.ValidatorBondCounter, k.cdc))
|
2018-04-12 02:52:54 -07:00
|
|
|
} else {
|
2018-04-16 04:22:05 -07:00
|
|
|
updateHeight = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if updateHeight {
|
|
|
|
// wasn't a candidate or wasn't in the validator set, update the validator block height and counter
|
2018-04-19 05:09:12 -07:00
|
|
|
candidate.ValidatorBondHeight = ctx.BlockHeight()
|
2018-04-16 04:22:05 -07:00
|
|
|
counter := k.getCounter(ctx)
|
2018-04-19 05:09:12 -07:00
|
|
|
candidate.ValidatorBondCounter = counter
|
2018-04-16 04:22:05 -07:00
|
|
|
k.setCounter(ctx, counter+1)
|
2018-03-22 14:47:57 -07:00
|
|
|
}
|
2018-04-09 04:12:08 -07:00
|
|
|
|
|
|
|
// update the candidate record
|
2018-05-01 13:41:04 -07:00
|
|
|
bz, err = k.cdc.MarshalBinary(candidate)
|
2018-04-09 04:12:08 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
store.Set(GetCandidateKey(candidate.Address), bz)
|
|
|
|
|
|
|
|
// marshal the new validator record
|
|
|
|
validator := candidate.validator()
|
2018-05-01 13:41:04 -07:00
|
|
|
bz, err = k.cdc.MarshalBinary(validator)
|
2018-04-09 04:12:08 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2018-04-16 04:22:05 -07:00
|
|
|
store.Set(GetValidatorKey(address, validator.Power, validator.Height, validator.Counter, k.cdc), bz)
|
2018-03-22 14:47:57 -07:00
|
|
|
|
|
|
|
// add to the validators to update list if is already a validator
|
2018-04-02 11:37:35 -07:00
|
|
|
// or is a new validator
|
|
|
|
setAcc := false
|
|
|
|
if store.Get(GetRecentValidatorKey(address)) != nil {
|
|
|
|
setAcc = true
|
|
|
|
|
|
|
|
// want to check in the else statement because inefficient
|
|
|
|
} else if k.isNewValidator(ctx, store, address) {
|
|
|
|
setAcc = true
|
|
|
|
}
|
|
|
|
if setAcc {
|
2018-04-25 07:38:04 -07:00
|
|
|
bz, err = k.cdc.MarshalBinary(validator.abciValidator(k.cdc))
|
2018-04-05 09:31:36 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-03-28 11:12:21 -07:00
|
|
|
store.Set(GetAccUpdateValidatorKey(validator.Address), bz)
|
2018-04-09 03:17:45 -07:00
|
|
|
|
2018-03-28 11:12:21 -07:00
|
|
|
}
|
2018-04-09 03:17:45 -07:00
|
|
|
|
2018-03-28 11:12:21 -07:00
|
|
|
return
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
func (k Keeper) removeCandidate(ctx sdk.Context, address sdk.Address) {
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// first retreive the old candidate record
|
2018-04-05 09:31:36 -07:00
|
|
|
candidate, found := k.GetCandidate(ctx, address)
|
2018-03-22 14:47:57 -07:00
|
|
|
if !found {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// delete the old candidate record
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
store.Delete(GetCandidateKey(address))
|
2018-04-19 05:09:12 -07:00
|
|
|
store.Delete(GetValidatorKey(address, candidate.Assets, candidate.ValidatorBondHeight, candidate.ValidatorBondCounter, k.cdc))
|
2018-03-22 09:00:45 -07:00
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// delete from recent and power weighted validator groups if the validator
|
|
|
|
// exists and add validator with zero power to the validator updates
|
2018-04-02 13:18:54 -07:00
|
|
|
if store.Get(GetRecentValidatorKey(address)) == nil {
|
2018-03-22 14:47:57 -07:00
|
|
|
return
|
|
|
|
}
|
2018-04-25 07:38:04 -07:00
|
|
|
bz, err := k.cdc.MarshalBinary(candidate.validator().abciValidatorZero(k.cdc))
|
2018-03-20 06:56:07 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-03-22 14:47:57 -07:00
|
|
|
store.Set(GetAccUpdateValidatorKey(address), bz)
|
|
|
|
store.Delete(GetRecentValidatorKey(address))
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
//___________________________________________________________________________
|
|
|
|
|
2018-04-05 15:34:25 -07:00
|
|
|
// Get the validator set from the candidates. The correct subset is retrieved
|
|
|
|
// by iterating through an index of the candidates sorted by power, stored
|
|
|
|
// using the ValidatorsKey. Simultaniously the most recent the validator
|
|
|
|
// records are updated in store with the RecentValidatorsKey. This store is
|
|
|
|
// used to determine if a candidate is a validator without needing to iterate
|
|
|
|
// over the subspace as we do in GetValidators
|
2018-04-25 07:38:04 -07:00
|
|
|
func (k Keeper) GetValidators(ctx sdk.Context) (validators []Validator) {
|
2018-03-20 14:21:18 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-04-02 11:37:35 -07:00
|
|
|
// clear the recent validators store, add to the ToKickOut Temp store
|
|
|
|
iterator := store.Iterator(subspace(RecentValidatorsKey))
|
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
|
|
|
addr := AddrFromKey(iterator.Key())
|
2018-04-05 09:31:36 -07:00
|
|
|
|
|
|
|
// iterator.Value is the validator object
|
|
|
|
store.Set(GetToKickOutValidatorKey(addr), iterator.Value())
|
2018-04-02 11:37:35 -07:00
|
|
|
store.Delete(iterator.Key())
|
|
|
|
}
|
|
|
|
iterator.Close()
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// add the actual validator power sorted store
|
2018-04-05 09:31:36 -07:00
|
|
|
maxValidators := k.GetParams(ctx).MaxValidators
|
2018-04-02 11:37:35 -07:00
|
|
|
iterator = store.ReverseIterator(subspace(ValidatorsKey)) // largest to smallest
|
2018-04-25 07:38:04 -07:00
|
|
|
validators = make([]Validator, maxValidators)
|
2018-03-22 10:10:25 -07:00
|
|
|
i := 0
|
|
|
|
for ; ; i++ {
|
2018-04-05 09:31:36 -07:00
|
|
|
if !iterator.Valid() || i > int(maxValidators-1) {
|
2018-03-20 06:56:07 -07:00
|
|
|
iterator.Close()
|
|
|
|
break
|
|
|
|
}
|
2018-03-22 14:47:57 -07:00
|
|
|
bz := iterator.Value()
|
2018-04-25 07:38:04 -07:00
|
|
|
var validator Validator
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(bz, &validator)
|
2018-03-20 06:56:07 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-04-05 09:31:36 -07:00
|
|
|
validators[i] = validator
|
2018-03-22 14:47:57 -07:00
|
|
|
|
2018-04-02 11:37:35 -07:00
|
|
|
// remove from ToKickOut group
|
2018-04-05 09:31:36 -07:00
|
|
|
store.Delete(GetToKickOutValidatorKey(validator.Address))
|
2018-04-02 11:37:35 -07:00
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// also add to the recent validators group
|
2018-04-05 09:31:36 -07:00
|
|
|
store.Set(GetRecentValidatorKey(validator.Address), bz)
|
2018-03-22 14:47:57 -07:00
|
|
|
|
2018-03-20 06:56:07 -07:00
|
|
|
iterator.Next()
|
|
|
|
}
|
2018-03-22 14:47:57 -07:00
|
|
|
|
2018-04-02 11:37:35 -07:00
|
|
|
// add any kicked out validators to the acc change
|
|
|
|
iterator = store.Iterator(subspace(ToKickOutValidatorsKey))
|
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
2018-04-05 09:31:36 -07:00
|
|
|
key := iterator.Key()
|
|
|
|
addr := AddrFromKey(key)
|
|
|
|
|
|
|
|
// get the zero abci validator from the ToKickOut iterator value
|
|
|
|
bz := iterator.Value()
|
2018-04-25 07:38:04 -07:00
|
|
|
var validator Validator
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(bz, &validator)
|
2018-04-05 09:31:36 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-04-25 07:38:04 -07:00
|
|
|
bz, err = k.cdc.MarshalBinary(validator.abciValidatorZero(k.cdc))
|
2018-04-02 11:37:35 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-04-05 09:31:36 -07:00
|
|
|
|
2018-04-02 11:37:35 -07:00
|
|
|
store.Set(GetAccUpdateValidatorKey(addr), bz)
|
2018-04-05 09:31:36 -07:00
|
|
|
store.Delete(key)
|
2018-04-02 11:37:35 -07:00
|
|
|
}
|
|
|
|
iterator.Close()
|
|
|
|
|
2018-03-22 10:10:25 -07:00
|
|
|
return validators[:i] // trim
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-03-28 11:12:21 -07:00
|
|
|
// TODO this is madly inefficient because need to call every time we set a candidate
|
|
|
|
// Should use something better than an iterator maybe?
|
|
|
|
// Used to determine if something has just been added to the actual validator set
|
|
|
|
func (k Keeper) isNewValidator(ctx sdk.Context, store sdk.KVStore, address sdk.Address) bool {
|
|
|
|
// add the actual validator power sorted store
|
|
|
|
maxVal := k.GetParams(ctx).MaxValidators
|
|
|
|
iterator := store.ReverseIterator(subspace(ValidatorsKey)) // largest to smallest
|
|
|
|
for i := 0; ; i++ {
|
|
|
|
if !iterator.Valid() || i > int(maxVal-1) {
|
|
|
|
iterator.Close()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
bz := iterator.Value()
|
2018-04-25 07:38:04 -07:00
|
|
|
var val Validator
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(bz, &val)
|
2018-03-28 11:12:21 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if bytes.Equal(val.Address, address) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
iterator.Next()
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// Is the address provided a part of the most recently saved validator group?
|
|
|
|
func (k Keeper) IsRecentValidator(ctx sdk.Context, address sdk.Address) bool {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
if store.Get(GetRecentValidatorKey(address)) == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-03-20 06:56:07 -07:00
|
|
|
//_________________________________________________________________________
|
2018-03-22 14:47:57 -07:00
|
|
|
// Accumulated updates to the validator set
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
// get the most recently updated validators
|
2018-04-04 20:22:13 -07:00
|
|
|
func (k Keeper) getAccUpdateValidators(ctx sdk.Context) (updates []abci.Validator) {
|
2018-03-20 14:21:18 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
iterator := store.Iterator(subspace(AccUpdateValidatorsKey)) //smallest to largest
|
2018-03-20 06:56:07 -07:00
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
|
|
|
valBytes := iterator.Value()
|
2018-04-05 09:31:36 -07:00
|
|
|
var val abci.Validator
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(valBytes, &val)
|
2018-03-20 06:56:07 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
updates = append(updates, val)
|
|
|
|
}
|
|
|
|
iterator.Close()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove all validator update entries
|
2018-03-22 14:47:57 -07:00
|
|
|
func (k Keeper) clearAccUpdateValidators(ctx sdk.Context) {
|
2018-03-20 14:21:18 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-03-22 14:47:57 -07:00
|
|
|
|
2018-04-04 20:22:13 -07:00
|
|
|
// delete subspace
|
|
|
|
iterator := store.Iterator(subspace(AccUpdateValidatorsKey))
|
2018-03-20 06:56:07 -07:00
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
2018-03-22 14:47:57 -07:00
|
|
|
store.Delete(iterator.Key())
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
iterator.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
//_____________________________________________________________________
|
|
|
|
|
2018-04-23 09:17:21 -07:00
|
|
|
// load a delegator bond
|
2018-04-10 20:51:09 -07:00
|
|
|
func (k Keeper) GetDelegatorBond(ctx sdk.Context,
|
2018-03-20 14:21:18 -07:00
|
|
|
delegatorAddr, candidateAddr sdk.Address) (bond DelegatorBond, found bool) {
|
2018-03-20 06:56:07 -07:00
|
|
|
|
2018-03-20 14:21:18 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
delegatorBytes := store.Get(GetDelegatorBondKey(delegatorAddr, candidateAddr, k.cdc))
|
2018-03-20 06:56:07 -07:00
|
|
|
if delegatorBytes == nil {
|
2018-03-20 14:21:18 -07:00
|
|
|
return bond, false
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(delegatorBytes, &bond)
|
2018-03-20 06:56:07 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-03-20 14:21:18 -07:00
|
|
|
return bond, true
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-04-24 06:46:39 -07:00
|
|
|
// load all bonds
|
2018-04-26 11:13:16 -07:00
|
|
|
func (k Keeper) getBonds(ctx sdk.Context, maxRetrieve int16) (bonds []DelegatorBond) {
|
2018-04-24 06:05:19 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
iterator := store.Iterator(subspace(DelegatorBondKeyPrefix))
|
|
|
|
|
|
|
|
bonds = make([]DelegatorBond, maxRetrieve)
|
|
|
|
i := 0
|
|
|
|
for ; ; i++ {
|
2018-04-24 06:46:39 -07:00
|
|
|
if !iterator.Valid() || i > int(maxRetrieve-1) {
|
2018-04-24 06:05:19 -07:00
|
|
|
iterator.Close()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
bondBytes := iterator.Value()
|
|
|
|
var bond DelegatorBond
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(bondBytes, &bond)
|
2018-04-24 06:05:19 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
bonds[i] = bond
|
|
|
|
iterator.Next()
|
|
|
|
}
|
|
|
|
return bonds[:i] // trim
|
|
|
|
}
|
|
|
|
|
2018-03-22 09:00:45 -07:00
|
|
|
// load all bonds of a delegator
|
2018-04-10 20:51:09 -07:00
|
|
|
func (k Keeper) GetDelegatorBonds(ctx sdk.Context, delegator sdk.Address, maxRetrieve int16) (bonds []DelegatorBond) {
|
2018-03-22 09:00:45 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
delegatorPrefixKey := GetDelegatorBondsKey(delegator, k.cdc)
|
|
|
|
iterator := store.Iterator(subspace(delegatorPrefixKey)) //smallest to largest
|
|
|
|
|
|
|
|
bonds = make([]DelegatorBond, maxRetrieve)
|
|
|
|
i := 0
|
|
|
|
for ; ; i++ {
|
|
|
|
if !iterator.Valid() || i > int(maxRetrieve-1) {
|
|
|
|
iterator.Close()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
bondBytes := iterator.Value()
|
|
|
|
var bond DelegatorBond
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(bondBytes, &bond)
|
2018-03-22 09:00:45 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
bonds[i] = bond
|
|
|
|
iterator.Next()
|
|
|
|
}
|
|
|
|
return bonds[:i] // trim
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-03-22 14:47:57 -07:00
|
|
|
func (k Keeper) setDelegatorBond(ctx sdk.Context, bond DelegatorBond) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-05-01 13:41:04 -07:00
|
|
|
b, err := k.cdc.MarshalBinary(bond)
|
2018-03-22 14:47:57 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
store.Set(GetDelegatorBondKey(bond.DelegatorAddr, bond.CandidateAddr, k.cdc), b)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k Keeper) removeDelegatorBond(ctx sdk.Context, bond DelegatorBond) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
store.Delete(GetDelegatorBondKey(bond.DelegatorAddr, bond.CandidateAddr, k.cdc))
|
|
|
|
}
|
|
|
|
|
2018-03-20 06:56:07 -07:00
|
|
|
//_______________________________________________________________________
|
|
|
|
|
|
|
|
// load/save the global staking params
|
2018-03-22 10:10:25 -07:00
|
|
|
func (k Keeper) GetParams(ctx sdk.Context) (params Params) {
|
2018-03-20 06:56:07 -07:00
|
|
|
// check if cached before anything
|
2018-04-30 14:21:14 -07:00
|
|
|
if !k.params.equal(Params{}) {
|
2018-03-20 14:21:18 -07:00
|
|
|
return k.params
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
2018-03-20 14:21:18 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-03-20 06:56:07 -07:00
|
|
|
b := store.Get(ParamKey)
|
|
|
|
if b == nil {
|
2018-04-03 11:50:31 -07:00
|
|
|
panic("Stored params should not have been nil")
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(b, ¶ms)
|
2018-03-20 06:56:07 -07:00
|
|
|
if err != nil {
|
2018-03-22 09:00:45 -07:00
|
|
|
panic(err)
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2018-03-20 14:21:18 -07:00
|
|
|
func (k Keeper) setParams(ctx sdk.Context, params Params) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-05-01 13:41:04 -07:00
|
|
|
b, err := k.cdc.MarshalBinary(params)
|
2018-03-20 06:56:07 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
store.Set(ParamKey, b)
|
2018-03-20 14:21:18 -07:00
|
|
|
k.params = Params{} // clear the cache
|
2018-03-20 06:56:07 -07:00
|
|
|
}
|
2018-03-28 13:37:42 -07:00
|
|
|
|
|
|
|
//_______________________________________________________________________
|
|
|
|
|
|
|
|
// load/save the pool
|
2018-04-30 14:21:14 -07:00
|
|
|
func (k Keeper) GetPool(ctx sdk.Context) (pool Pool) {
|
2018-03-28 13:37:42 -07:00
|
|
|
// check if cached before anything
|
2018-04-30 14:21:14 -07:00
|
|
|
if !k.pool.equal(Pool{}) {
|
|
|
|
return k.pool
|
2018-03-28 13:37:42 -07:00
|
|
|
}
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
b := store.Get(PoolKey)
|
|
|
|
if b == nil {
|
2018-04-03 11:50:31 -07:00
|
|
|
panic("Stored pool should not have been nil")
|
2018-03-28 13:37:42 -07:00
|
|
|
}
|
2018-05-01 13:41:04 -07:00
|
|
|
err := k.cdc.UnmarshalBinary(b, &pool)
|
2018-03-28 13:37:42 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err) // This error should never occur big problem if does
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k Keeper) setPool(ctx sdk.Context, p Pool) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
2018-05-01 13:41:04 -07:00
|
|
|
b, err := k.cdc.MarshalBinary(p)
|
2018-03-28 13:37:42 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
store.Set(PoolKey, b)
|
2018-04-30 14:21:14 -07:00
|
|
|
k.pool = Pool{} //clear the cache
|
2018-03-28 13:37:42 -07:00
|
|
|
}
|
2018-04-25 07:12:59 -07:00
|
|
|
|
|
|
|
//__________________________________________________________________________
|
|
|
|
|
2018-04-25 07:38:04 -07:00
|
|
|
// Implements ValidatorSetKeeper
|
|
|
|
|
|
|
|
var _ sdk.ValidatorSetKeeper = Keeper{}
|
|
|
|
|
|
|
|
func (k Keeper) Validators(ctx sdk.Context) []*sdk.Validator {
|
|
|
|
vals := k.GetValidators(ctx)
|
|
|
|
res := make([]*sdk.Validator, len(vals))
|
|
|
|
|
|
|
|
for i, val := range vals {
|
|
|
|
abcival := val.abciValidator(k.cdc)
|
|
|
|
res[i] = &abcival
|
|
|
|
}
|
|
|
|
|
|
|
|
return res
|
|
|
|
}
|
2018-04-25 07:12:59 -07:00
|
|
|
|
|
|
|
func (k Keeper) Size(ctx sdk.Context) int {
|
|
|
|
return len(k.GetValidators(ctx))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k Keeper) IsValidator(ctx sdk.Context, addr sdk.Address) bool {
|
|
|
|
for _, v := range k.GetValidators(ctx) {
|
|
|
|
if bytes.Equal(v.Address, addr) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k Keeper) GetByAddress(ctx sdk.Context, addr sdk.Address) (int, *sdk.Validator) {
|
|
|
|
for i, v := range k.GetValidators(ctx) {
|
|
|
|
if bytes.Equal(v.Address, addr) {
|
|
|
|
val := v.abciValidator(k.cdc)
|
|
|
|
return i, &val
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k Keeper) GetByIndex(ctx sdk.Context, index int) *sdk.Validator {
|
|
|
|
valset := k.GetValidators(ctx)
|
|
|
|
|
|
|
|
if index < 0 || index >= len(valset) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
val := valset[index].abciValidator(k.cdc)
|
|
|
|
return &val
|
|
|
|
}
|
|
|
|
|
2018-04-17 14:38:12 -07:00
|
|
|
func (k Keeper) TotalPower(ctx sdk.Context) sdk.Rat {
|
|
|
|
valset := k.GetValidators(ctx)
|
|
|
|
|
|
|
|
res := sdk.ZeroRat
|
|
|
|
|
|
|
|
for _, v := range valset {
|
|
|
|
res = res.Add(v.Power)
|
|
|
|
}
|
|
|
|
|
|
|
|
return res
|
2018-04-25 07:12:59 -07:00
|
|
|
}
|