staking fee distribution working commit
This commit is contained in:
parent
8336eb9bc5
commit
d871605241
|
@ -81,7 +81,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
|
|||
app.SetInitChainer(app.initChainer)
|
||||
app.SetEndBlocker(stake.NewEndBlocker(app.stakeKeeper))
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, stake.FeeHandler))
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.stakeKeeper.FeeHandler))
|
||||
err := app.LoadLatestVersion(app.keyMain)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
|
|
|
@ -105,7 +105,7 @@ func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error {
|
|||
|
||||
genesisState := GenesisState{
|
||||
Accounts: genaccs,
|
||||
StakeData: stake.GetDefaultGenesisState(),
|
||||
StakeData: stake.DefaultGenesisState(),
|
||||
}
|
||||
|
||||
stateBytes, err := wire.MarshalJSONIndent(gapp.cdc, genesisState)
|
||||
|
@ -147,7 +147,7 @@ func setGenesisAccounts(gapp *GaiaApp, accs ...*auth.BaseAccount) error {
|
|||
|
||||
genesisState := GenesisState{
|
||||
Accounts: genaccs,
|
||||
StakeData: stake.GetDefaultGenesisState(),
|
||||
StakeData: stake.DefaultGenesisState(),
|
||||
}
|
||||
|
||||
stateBytes, err := json.MarshalIndent(genesisState, "", "\t")
|
||||
|
|
|
@ -135,7 +135,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState jso
|
|||
}
|
||||
|
||||
// start with the default staking genesis state
|
||||
stakeData := stake.GetDefaultGenesisState()
|
||||
stakeData := stake.DefaultGenesisState()
|
||||
|
||||
// get genesis flag account information
|
||||
genaccs := make([]GenesisAccount, len(appGenTxs))
|
||||
|
|
|
@ -4,7 +4,7 @@ package types
|
|||
type Handler func(ctx Context, msg Msg) Result
|
||||
|
||||
// core function variable which application runs to handle fees
|
||||
type FeeHandler func(ctx Context, tx Tx, fee Coins)
|
||||
type FeeHandler func(ctx Context, fee Coins)
|
||||
|
||||
// If newCtx.IsZero(), ctx is used instead.
|
||||
type AnteHandler func(ctx Context, tx Tx) (newCtx Context, result Result, abort bool)
|
||||
|
|
|
@ -77,7 +77,7 @@ func NewAnteHandler(am sdk.AccountMapper, feeHandler sdk.FeeHandler) sdk.AnteHan
|
|||
// TODO: min fee
|
||||
if !fee.Amount.IsZero() {
|
||||
signerAcc, res = deductFees(signerAcc, fee)
|
||||
feeHandler(ctx, tx, fee.Amount)
|
||||
feeHandler(ctx, fee.Amount)
|
||||
if !res.IsOK() {
|
||||
return ctx, res, true
|
||||
}
|
||||
|
@ -166,5 +166,5 @@ func deductFees(acc sdk.Account, fee sdk.StdFee) (sdk.Account, sdk.Result) {
|
|||
}
|
||||
|
||||
// BurnFeeHandler burns all fees (decreasing total supply)
|
||||
func BurnFeeHandler(ctx sdk.Context, tx sdk.Tx, fee sdk.Coins) {
|
||||
func BurnFeeHandler(ctx sdk.Context, fee sdk.Coins) {
|
||||
}
|
||||
|
|
|
@ -5,6 +5,35 @@ import (
|
|||
)
|
||||
|
||||
// Handle fee distribution to the validators and delegators
|
||||
func FeeHandler(ctx sdk.Context, tx sdk.Tx, fee sdk.Coins) {
|
||||
func (k Keeper) FeeHandler(ctx sdk.Context, collectedFees sdk.Coins) {
|
||||
pool := k.GetPool(ctx)
|
||||
params := k.GetParams(ctx)
|
||||
|
||||
// XXX calculate
|
||||
sumOfVotingPowerOfPrecommitValidators := sdk.NewRat(67, 100)
|
||||
candidate := NewCandidate(addrs[0], pks[0], Description{})
|
||||
|
||||
toProposer := coinsMulRat(collectedFees, (sdk.NewRat(1, 100).Add(sdk.NewRat(4, 100).Mul(sumOfVotingPowerOfPrecommitValidators).Quo(pool.BondedShares))))
|
||||
candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer)
|
||||
|
||||
toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee)
|
||||
pool.ReservePool = pool.ReservePool.Plus(toReservePool)
|
||||
|
||||
distributedReward := (collectedFees.Minus(toProposer)).Minus(toReservePool)
|
||||
pool.FeePool = pool.FeePool.Plus(distributedReward)
|
||||
pool.SumFeesReceived = pool.SumFeesReceived.Plus(distributedReward)
|
||||
pool.RecentFee = distributedReward
|
||||
|
||||
k.setPool(ctx, pool)
|
||||
}
|
||||
|
||||
// XXX need to introduce rat amount based coins for the pool :(
|
||||
func coinsMulRat(coins sdk.Coins, rat sdk.Rat) sdk.Coins {
|
||||
var res sdk.Coins
|
||||
for _, coin := range coins {
|
||||
coinMulAmt := rat.Mul(sdk.NewRat(coin.Amount)).Evaluate()
|
||||
coinMul := sdk.Coins{{coin.Denom, coinMulAmt}}
|
||||
res = res.Plus(coinMul)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ func (k Keeper) GetCandidate(ctx sdk.Context, addr sdk.Address) (candidate Candi
|
|||
// Get the set of all candidates, retrieve a maxRetrieve number of records
|
||||
func (k Keeper) GetCandidates(ctx sdk.Context, maxRetrieve int16) (candidates Candidates) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := store.Iterator(subspace(CandidatesKey))
|
||||
iterator := store.SubspaceIterator(CandidatesKey)
|
||||
|
||||
candidates = make([]Candidate, maxRetrieve)
|
||||
i := 0
|
||||
|
@ -220,7 +220,7 @@ func (k Keeper) GetValidators(ctx sdk.Context) (validators []Validator) {
|
|||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
// clear the recent validators store, add to the ToKickOut Temp store
|
||||
iterator := store.Iterator(subspace(RecentValidatorsKey))
|
||||
iterator := store.SubspaceIterator(RecentValidatorsKey)
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
addr := AddrFromKey(iterator.Key())
|
||||
|
||||
|
@ -232,7 +232,7 @@ func (k Keeper) GetValidators(ctx sdk.Context) (validators []Validator) {
|
|||
|
||||
// add the actual validator power sorted store
|
||||
maxValidators := k.GetParams(ctx).MaxValidators
|
||||
iterator = store.ReverseIterator(subspace(ValidatorsKey)) // largest to smallest
|
||||
iterator = store.ReverseSubspaceIterator(ValidatorsKey) // largest to smallest
|
||||
validators = make([]Validator, maxValidators)
|
||||
i := 0
|
||||
for ; ; i++ {
|
||||
|
@ -258,7 +258,7 @@ func (k Keeper) GetValidators(ctx sdk.Context) (validators []Validator) {
|
|||
}
|
||||
|
||||
// add any kicked out validators to the acc change
|
||||
iterator = store.Iterator(subspace(ToKickOutValidatorsKey))
|
||||
iterator = store.SubspaceIterator(ToKickOutValidatorsKey)
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
key := iterator.Key()
|
||||
addr := AddrFromKey(key)
|
||||
|
@ -289,7 +289,7 @@ func (k Keeper) GetValidators(ctx sdk.Context) (validators []Validator) {
|
|||
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
|
||||
iterator := store.ReverseSubspaceIterator(ValidatorsKey) // largest to smallest
|
||||
for i := 0; ; i++ {
|
||||
if !iterator.Valid() || i > int(maxVal-1) {
|
||||
iterator.Close()
|
||||
|
@ -326,7 +326,7 @@ func (k Keeper) IsRecentValidator(ctx sdk.Context, address sdk.Address) bool {
|
|||
func (k Keeper) getAccUpdateValidators(ctx sdk.Context) (updates []abci.Validator) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
iterator := store.Iterator(subspace(AccUpdateValidatorsKey)) //smallest to largest
|
||||
iterator := store.SubspaceIterator(AccUpdateValidatorsKey) //smallest to largest
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
valBytes := iterator.Value()
|
||||
var val abci.Validator
|
||||
|
@ -345,7 +345,7 @@ func (k Keeper) clearAccUpdateValidators(ctx sdk.Context) {
|
|||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
// delete subspace
|
||||
iterator := store.Iterator(subspace(AccUpdateValidatorsKey))
|
||||
iterator := store.SubspaceIterator(AccUpdateValidatorsKey)
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
store.Delete(iterator.Key())
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ func (k Keeper) GetDelegatorBond(ctx sdk.Context,
|
|||
// load all bonds
|
||||
func (k Keeper) getBonds(ctx sdk.Context, maxRetrieve int16) (bonds []DelegatorBond) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := store.Iterator(subspace(DelegatorBondKeyPrefix))
|
||||
iterator := store.SubspaceIterator(DelegatorBondKeyPrefix)
|
||||
|
||||
bonds = make([]DelegatorBond, maxRetrieve)
|
||||
i := 0
|
||||
|
@ -399,7 +399,7 @@ func (k Keeper) getBonds(ctx sdk.Context, maxRetrieve int16) (bonds []DelegatorB
|
|||
func (k Keeper) GetDelegatorBonds(ctx sdk.Context, delegator sdk.Address, maxRetrieve int16) (bonds []DelegatorBond) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
delegatorPrefixKey := GetDelegatorBondsKey(delegator, k.cdc)
|
||||
iterator := store.Iterator(subspace(delegatorPrefixKey)) //smallest to largest
|
||||
iterator := store.SubspaceIterator(delegatorPrefixKey) //smallest to largest
|
||||
|
||||
bonds = make([]DelegatorBond, maxRetrieve)
|
||||
i := 0
|
||||
|
|
|
@ -49,14 +49,14 @@ func TestCandidate(t *testing.T) {
|
|||
keeper.setCandidate(ctx, candidates[0])
|
||||
resCand, found := keeper.GetCandidate(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
assert.True(t, candidatesEqual(candidates[0], resCand), "%v \n %v", resCand, candidates[0])
|
||||
assert.True(t, candidates[0].equal(resCand), "%v \n %v", resCand, candidates[0])
|
||||
|
||||
// modify a records, save, and retrieve
|
||||
candidates[0].Liabilities = sdk.NewRat(99)
|
||||
keeper.setCandidate(ctx, candidates[0])
|
||||
resCand, found = keeper.GetCandidate(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
assert.True(t, candidatesEqual(candidates[0], resCand))
|
||||
assert.True(t, candidates[0].equal(resCand))
|
||||
|
||||
// also test that the address has been added to address list
|
||||
resCands = keeper.GetCandidates(ctx, 100)
|
||||
|
@ -68,15 +68,15 @@ func TestCandidate(t *testing.T) {
|
|||
keeper.setCandidate(ctx, candidates[2])
|
||||
resCand, found = keeper.GetCandidate(ctx, addrVals[1])
|
||||
require.True(t, found)
|
||||
assert.True(t, candidatesEqual(candidates[1], resCand), "%v \n %v", resCand, candidates[1])
|
||||
assert.True(t, candidates[1].equal(resCand), "%v \n %v", resCand, candidates[1])
|
||||
resCand, found = keeper.GetCandidate(ctx, addrVals[2])
|
||||
require.True(t, found)
|
||||
assert.True(t, candidatesEqual(candidates[2], resCand), "%v \n %v", resCand, candidates[2])
|
||||
assert.True(t, candidates[2].equal(resCand), "%v \n %v", resCand, candidates[2])
|
||||
resCands = keeper.GetCandidates(ctx, 100)
|
||||
require.Equal(t, 3, len(resCands))
|
||||
assert.True(t, candidatesEqual(candidates[0], resCands[0]), "%v \n %v", resCands[0], candidates[0])
|
||||
assert.True(t, candidatesEqual(candidates[1], resCands[1]), "%v \n %v", resCands[1], candidates[1])
|
||||
assert.True(t, candidatesEqual(candidates[2], resCands[2]), "%v \n %v", resCands[2], candidates[2])
|
||||
assert.True(t, candidates[0].equal(resCands[0]), "%v \n %v", resCands[0], candidates[0])
|
||||
assert.True(t, candidates[1].equal(resCands[1]), "%v \n %v", resCands[1], candidates[1])
|
||||
assert.True(t, candidates[2].equal(resCands[2]), "%v \n %v", resCands[2], candidates[2])
|
||||
|
||||
// remove a record
|
||||
keeper.removeCandidate(ctx, candidates[1].Address)
|
||||
|
@ -117,14 +117,14 @@ func TestBond(t *testing.T) {
|
|||
keeper.setDelegatorBond(ctx, bond1to1)
|
||||
resBond, found := keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0])
|
||||
assert.True(t, found)
|
||||
assert.True(t, bondsEqual(bond1to1, resBond))
|
||||
assert.True(t, bond1to1.equal(resBond))
|
||||
|
||||
// modify a records, save, and retrieve
|
||||
bond1to1.Shares = sdk.NewRat(99)
|
||||
keeper.setDelegatorBond(ctx, bond1to1)
|
||||
resBond, found = keeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0])
|
||||
assert.True(t, found)
|
||||
assert.True(t, bondsEqual(bond1to1, resBond))
|
||||
assert.True(t, bond1to1.equal(resBond))
|
||||
|
||||
// add some more records
|
||||
keeper.setCandidate(ctx, candidates[1])
|
||||
|
@ -143,26 +143,26 @@ func TestBond(t *testing.T) {
|
|||
// test all bond retrieve capabilities
|
||||
resBonds := keeper.GetDelegatorBonds(ctx, addrDels[0], 5)
|
||||
require.Equal(t, 3, len(resBonds))
|
||||
assert.True(t, bondsEqual(bond1to1, resBonds[0]))
|
||||
assert.True(t, bondsEqual(bond1to2, resBonds[1]))
|
||||
assert.True(t, bondsEqual(bond1to3, resBonds[2]))
|
||||
assert.True(t, bond1to1.equal(resBonds[0]))
|
||||
assert.True(t, bond1to2.equal(resBonds[1]))
|
||||
assert.True(t, bond1to3.equal(resBonds[2]))
|
||||
resBonds = keeper.GetDelegatorBonds(ctx, addrDels[0], 3)
|
||||
require.Equal(t, 3, len(resBonds))
|
||||
resBonds = keeper.GetDelegatorBonds(ctx, addrDels[0], 2)
|
||||
require.Equal(t, 2, len(resBonds))
|
||||
resBonds = keeper.GetDelegatorBonds(ctx, addrDels[1], 5)
|
||||
require.Equal(t, 3, len(resBonds))
|
||||
assert.True(t, bondsEqual(bond2to1, resBonds[0]))
|
||||
assert.True(t, bondsEqual(bond2to2, resBonds[1]))
|
||||
assert.True(t, bondsEqual(bond2to3, resBonds[2]))
|
||||
assert.True(t, bond2to1.equal(resBonds[0]))
|
||||
assert.True(t, bond2to2.equal(resBonds[1]))
|
||||
assert.True(t, bond2to3.equal(resBonds[2]))
|
||||
allBonds := keeper.getBonds(ctx, 1000)
|
||||
require.Equal(t, 6, len(allBonds))
|
||||
assert.True(t, bondsEqual(bond1to1, allBonds[0]))
|
||||
assert.True(t, bondsEqual(bond1to2, allBonds[1]))
|
||||
assert.True(t, bondsEqual(bond1to3, allBonds[2]))
|
||||
assert.True(t, bondsEqual(bond2to1, allBonds[3]))
|
||||
assert.True(t, bondsEqual(bond2to2, allBonds[4]))
|
||||
assert.True(t, bondsEqual(bond2to3, allBonds[5]))
|
||||
assert.True(t, bond1to1.equal(allBonds[0]))
|
||||
assert.True(t, bond1to2.equal(allBonds[1]))
|
||||
assert.True(t, bond1to3.equal(allBonds[2]))
|
||||
assert.True(t, bond2to1.equal(allBonds[3]))
|
||||
assert.True(t, bond2to2.equal(allBonds[4]))
|
||||
assert.True(t, bond2to3.equal(allBonds[5]))
|
||||
|
||||
// delete a record
|
||||
keeper.removeDelegatorBond(ctx, bond2to3)
|
||||
|
@ -170,8 +170,8 @@ func TestBond(t *testing.T) {
|
|||
assert.False(t, found)
|
||||
resBonds = keeper.GetDelegatorBonds(ctx, addrDels[1], 5)
|
||||
require.Equal(t, 2, len(resBonds))
|
||||
assert.True(t, bondsEqual(bond2to1, resBonds[0]))
|
||||
assert.True(t, bondsEqual(bond2to2, resBonds[1]))
|
||||
assert.True(t, bond2to1.equal(resBonds[0]))
|
||||
assert.True(t, bond2to2.equal(resBonds[1]))
|
||||
|
||||
// delete all the records from delegator 2
|
||||
keeper.removeDelegatorBond(ctx, bond2to1)
|
||||
|
@ -443,8 +443,8 @@ func TestGetAccUpdateValidators(t *testing.T) {
|
|||
require.Equal(t, 2, len(candidates))
|
||||
assert.Equal(t, candidates[0].validator().abciValidator(keeper.cdc), acc[0])
|
||||
assert.Equal(t, candidates[1].validator().abciValidator(keeper.cdc), acc[1])
|
||||
assert.True(t, validatorsEqual(candidates[0].validator(), vals[1]))
|
||||
assert.True(t, validatorsEqual(candidates[1].validator(), vals[0]))
|
||||
assert.True(t, candidates[0].validator().equal(vals[1]))
|
||||
assert.True(t, candidates[1].validator().equal(vals[0]))
|
||||
|
||||
// test identical,
|
||||
// candidate set: {c1, c3} -> {c1, c3}
|
||||
|
@ -637,10 +637,10 @@ func TestIsRecentValidator(t *testing.T) {
|
|||
keeper.setCandidate(ctx, candidatesIn[1])
|
||||
validators = keeper.GetValidators(ctx)
|
||||
require.Equal(t, 2, len(validators))
|
||||
assert.True(t, validatorsEqual(candidatesIn[0].validator(), validators[0]))
|
||||
assert.True(t, candidatesIn[0].validator().equal(validators[0]))
|
||||
c1ValWithCounter := candidatesIn[1].validator()
|
||||
c1ValWithCounter.Counter = int16(1)
|
||||
assert.True(t, validatorsEqual(c1ValWithCounter, validators[1]))
|
||||
assert.True(t, c1ValWithCounter.equal(validators[1]))
|
||||
|
||||
// test a basic retrieve of something that should be a recent validator
|
||||
assert.True(t, keeper.IsRecentValidator(ctx, candidatesIn[0].Address))
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
|
@ -52,71 +51,6 @@ var (
|
|||
emptyPubkey crypto.PubKey
|
||||
)
|
||||
|
||||
func validatorsEqual(b1, b2 Validator) bool {
|
||||
return bytes.Equal(b1.Address, b2.Address) &&
|
||||
b1.PubKey.Equals(b2.PubKey) &&
|
||||
b1.Power.Equal(b2.Power) &&
|
||||
b1.Height == b2.Height &&
|
||||
b1.Counter == b2.Counter
|
||||
}
|
||||
|
||||
func candidatesEqual(c1, c2 Candidate) bool {
|
||||
return c1.Status == c2.Status &&
|
||||
c1.PubKey.Equals(c2.PubKey) &&
|
||||
bytes.Equal(c1.Address, c2.Address) &&
|
||||
c1.Assets.Equal(c2.Assets) &&
|
||||
c1.Liabilities.Equal(c2.Liabilities) &&
|
||||
c1.Description == c2.Description
|
||||
}
|
||||
|
||||
func bondsEqual(b1, b2 DelegatorBond) bool {
|
||||
return bytes.Equal(b1.DelegatorAddr, b2.DelegatorAddr) &&
|
||||
bytes.Equal(b1.CandidateAddr, b2.CandidateAddr) &&
|
||||
b1.Height == b2.Height &&
|
||||
b1.Shares.Equal(b2.Shares)
|
||||
}
|
||||
|
||||
// default params for testing
|
||||
func defaultParams() Params {
|
||||
return Params{
|
||||
InflationRateChange: sdk.NewRat(13, 100),
|
||||
InflationMax: sdk.NewRat(20, 100),
|
||||
InflationMin: sdk.NewRat(7, 100),
|
||||
GoalBonded: sdk.NewRat(67, 100),
|
||||
MaxValidators: 100,
|
||||
BondDenom: "steak",
|
||||
}
|
||||
}
|
||||
|
||||
// initial pool for testing
|
||||
func initialPool() Pool {
|
||||
return Pool{
|
||||
TotalSupply: 0,
|
||||
BondedShares: sdk.ZeroRat(),
|
||||
UnbondedShares: sdk.ZeroRat(),
|
||||
BondedPool: 0,
|
||||
UnbondedPool: 0,
|
||||
InflationLastTime: 0,
|
||||
Inflation: sdk.NewRat(7, 100),
|
||||
}
|
||||
}
|
||||
|
||||
// get raw genesis raw message for testing
|
||||
func GetDefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
Pool: initialPool(),
|
||||
Params: defaultParams(),
|
||||
}
|
||||
}
|
||||
|
||||
// XXX reference the common declaration of this function
|
||||
func subspace(prefix []byte) (start, end []byte) {
|
||||
end = make([]byte, len(prefix))
|
||||
copy(end, prefix)
|
||||
end[len(end)-1]++
|
||||
return prefix, end
|
||||
}
|
||||
|
||||
func makeTestCodec() *wire.Codec {
|
||||
var cdc = wire.NewCodec()
|
||||
|
||||
|
|
142
x/stake/types.go
142
x/stake/types.go
|
@ -1,6 +1,8 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
|
@ -15,6 +17,14 @@ type GenesisState struct {
|
|||
Bonds []DelegatorBond `json:"bonds"`
|
||||
}
|
||||
|
||||
// get raw genesis raw message for testing
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
Pool: initialPool(),
|
||||
Params: defaultParams(),
|
||||
}
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
||||
// Params defines the high level settings for staking
|
||||
|
@ -26,6 +36,8 @@ type Params struct {
|
|||
|
||||
MaxValidators uint16 `json:"max_validators"` // maximum number of validators
|
||||
BondDenom string `json:"bond_denom"` // bondable coin denomination
|
||||
|
||||
ReservePoolFee sdk.Rat `json:"reserve_pool_fee"` // percent of fees which go to reserve pool
|
||||
}
|
||||
|
||||
func (p Params) equal(p2 Params) bool {
|
||||
|
@ -34,7 +46,20 @@ func (p Params) equal(p2 Params) bool {
|
|||
p.InflationMin.Equal(p2.InflationMin) &&
|
||||
p.GoalBonded.Equal(p2.GoalBonded) &&
|
||||
p.MaxValidators == p2.MaxValidators &&
|
||||
p.BondDenom == p2.BondDenom
|
||||
p.BondDenom == p2.BondDenom &&
|
||||
p.ReservePoolFee.Equal(p2.ReservePoolFee)
|
||||
}
|
||||
|
||||
func defaultParams() Params {
|
||||
return Params{
|
||||
InflationRateChange: sdk.NewRat(13, 100),
|
||||
InflationMax: sdk.NewRat(20, 100),
|
||||
InflationMin: sdk.NewRat(7, 100),
|
||||
GoalBonded: sdk.NewRat(67, 100),
|
||||
MaxValidators: 100,
|
||||
BondDenom: "steak",
|
||||
ReservePoolFee: sdk.NewRat(5, 100),
|
||||
}
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
@ -48,16 +73,50 @@ type Pool struct {
|
|||
UnbondedPool int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with candidates
|
||||
InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
|
||||
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate
|
||||
|
||||
DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily)
|
||||
|
||||
// XXX need to use special sdk.Rat amounts in coins here because added at small increments
|
||||
ReservePool sdk.Coins `json:"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
|
||||
SumFeesReceived sdk.Coins `json:"sum_fees_received"` // XXX sum of all fees received
|
||||
RecentFee sdk.Coins `json:"recent_fee"` // XXX most recent fee collected
|
||||
Adjustment sdk.Rat `json:"adjustment"` // XXX Adjustment factor for calculating global fee accum
|
||||
}
|
||||
|
||||
func (p Pool) equal(p2 Pool) bool {
|
||||
return p.BondedShares.Equal(p2.BondedShares) &&
|
||||
return p.TotalSupply == p2.TotalSupply &&
|
||||
p.BondedShares.Equal(p2.BondedShares) &&
|
||||
p.UnbondedShares.Equal(p2.UnbondedShares) &&
|
||||
p.Inflation.Equal(p2.Inflation) &&
|
||||
p.TotalSupply == p2.TotalSupply &&
|
||||
p.BondedPool == p2.BondedPool &&
|
||||
p.UnbondedPool == p2.UnbondedPool &&
|
||||
p.InflationLastTime == p2.InflationLastTime
|
||||
p.InflationLastTime == p2.InflationLastTime &&
|
||||
p.Inflation.Equal(p2.Inflation) &&
|
||||
p.DateLastCommissionReset == p2.DateLastCommissionReset &&
|
||||
p.ReservePool.IsEqual(p2.ReservePool) &&
|
||||
p.FeePool.IsEqual(p2.FeePool) &&
|
||||
p.SumFeesReceived.IsEqual(p2.SumFeesReceived) &&
|
||||
p.RecentFee.IsEqual(p2.RecentFee) &&
|
||||
p.Adjustment.Equal(p2.Adjustment)
|
||||
}
|
||||
|
||||
// initial pool for testing
|
||||
func initialPool() Pool {
|
||||
return Pool{
|
||||
TotalSupply: 0,
|
||||
BondedShares: sdk.ZeroRat(),
|
||||
UnbondedShares: sdk.ZeroRat(),
|
||||
BondedPool: 0,
|
||||
UnbondedPool: 0,
|
||||
InflationLastTime: 0,
|
||||
Inflation: sdk.NewRat(7, 100),
|
||||
DateLastCommissionReset: 0,
|
||||
ReservePool: sdk.Coins{},
|
||||
FeePool: sdk.Coins{},
|
||||
SumFeesReceived: sdk.Coins{},
|
||||
RecentFee: sdk.Coins{},
|
||||
Adjustment: sdk.ZeroRat(),
|
||||
}
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
@ -80,14 +139,19 @@ 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
|
||||
ValidatorBondHeight int64 `json:"validator_bond_height"` // Earliest height as a bonded validator
|
||||
ValidatorBondCounter int16 `json:"validator_bond_counter"` // Block-local tx index of validator change
|
||||
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
|
||||
ValidatorBondHeight int64 `json:"validator_bond_height"` // Earliest height as a bonded validator
|
||||
ValidatorBondCounter int16 `json:"validator_bond_counter"` // Block-local tx index of validator change
|
||||
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
|
||||
Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators
|
||||
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this candidate can ever charge
|
||||
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the candidate commission
|
||||
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
||||
}
|
||||
|
||||
// Candidates - list of Candidates
|
||||
|
@ -96,17 +160,38 @@ 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,
|
||||
ValidatorBondHeight: int64(0),
|
||||
ValidatorBondCounter: int16(0),
|
||||
Status: Unbonded,
|
||||
Address: address,
|
||||
PubKey: pubKey,
|
||||
Assets: sdk.ZeroRat(),
|
||||
Liabilities: sdk.ZeroRat(),
|
||||
Description: description,
|
||||
ValidatorBondHeight: int64(0),
|
||||
ValidatorBondCounter: int16(0),
|
||||
ProposerRewardPool: sdk.Coins{},
|
||||
Commission: sdk.ZeroRat(),
|
||||
CommissionMax: sdk.ZeroRat(),
|
||||
CommissionChangeRate: sdk.ZeroRat(),
|
||||
CommissionChangeToday: sdk.ZeroRat(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c Candidate) equal(c2 Candidate) bool {
|
||||
return c.Status == c2.Status &&
|
||||
c.PubKey.Equals(c2.PubKey) &&
|
||||
bytes.Equal(c.Address, c2.Address) &&
|
||||
c.Assets.Equal(c2.Assets) &&
|
||||
c.Liabilities.Equal(c2.Liabilities) &&
|
||||
c.Description == c2.Description &&
|
||||
c.ValidatorBondHeight == c2.ValidatorBondHeight &&
|
||||
c.ValidatorBondCounter == c2.ValidatorBondCounter &&
|
||||
c.ProposerRewardPool.IsEqual(c2.ProposerRewardPool) &&
|
||||
c.Commission.Equal(c2.Commission) &&
|
||||
c.CommissionMax.Equal(c2.CommissionMax) &&
|
||||
c.CommissionChangeRate.Equal(c2.CommissionChangeRate) &&
|
||||
c.CommissionChangeToday.Equal(c2.CommissionChangeToday)
|
||||
}
|
||||
|
||||
// Description - description fields for a candidate
|
||||
type Description struct {
|
||||
Moniker string `json:"moniker"`
|
||||
|
@ -158,6 +243,14 @@ type Validator struct {
|
|||
Counter int16 `json:"counter"` // Block-local tx index for resolving equal voting power & height
|
||||
}
|
||||
|
||||
func (v Validator) equal(v2 Validator) bool {
|
||||
return bytes.Equal(v.Address, v2.Address) &&
|
||||
v.PubKey.Equals(v2.PubKey) &&
|
||||
v.Power.Equal(v2.Power) &&
|
||||
v.Height == v2.Height &&
|
||||
v.Counter == v2.Counter
|
||||
}
|
||||
|
||||
// abci validator from stake validator type
|
||||
func (v Validator) abciValidator(cdc *wire.Codec) sdk.Validator {
|
||||
return sdk.Validator{
|
||||
|
@ -187,3 +280,10 @@ type DelegatorBond struct {
|
|||
Shares sdk.Rat `json:"shares"`
|
||||
Height int64 `json:"height"` // Last height bond updated
|
||||
}
|
||||
|
||||
func (b DelegatorBond) equal(b2 DelegatorBond) bool {
|
||||
return bytes.Equal(b.DelegatorAddr, b2.DelegatorAddr) &&
|
||||
bytes.Equal(b.CandidateAddr, b2.CandidateAddr) &&
|
||||
b.Height == b2.Height &&
|
||||
b.Shares.Equal(b2.Shares)
|
||||
}
|
||||
|
|
|
@ -44,14 +44,14 @@ func TestViewSlashBond(t *testing.T) {
|
|||
keeper.setDelegatorBond(ctx, bond1to1)
|
||||
resBond, found := viewSlashKeeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0])
|
||||
assert.True(t, found)
|
||||
assert.True(t, bondsEqual(bond1to1, resBond))
|
||||
assert.True(t, bond1to1.equal(resBond))
|
||||
|
||||
// modify a records, save, and retrieve
|
||||
bond1to1.Shares = sdk.NewRat(99)
|
||||
keeper.setDelegatorBond(ctx, bond1to1)
|
||||
resBond, found = viewSlashKeeper.GetDelegatorBond(ctx, addrDels[0], addrVals[0])
|
||||
assert.True(t, found)
|
||||
assert.True(t, bondsEqual(bond1to1, resBond))
|
||||
assert.True(t, bond1to1.equal(resBond))
|
||||
|
||||
// add some more records
|
||||
keeper.setCandidate(ctx, candidates[1])
|
||||
|
@ -70,17 +70,17 @@ func TestViewSlashBond(t *testing.T) {
|
|||
// test all bond retrieve capabilities
|
||||
resBonds := viewSlashKeeper.GetDelegatorBonds(ctx, addrDels[0], 5)
|
||||
require.Equal(t, 3, len(resBonds))
|
||||
assert.True(t, bondsEqual(bond1to1, resBonds[0]))
|
||||
assert.True(t, bondsEqual(bond1to2, resBonds[1]))
|
||||
assert.True(t, bondsEqual(bond1to3, resBonds[2]))
|
||||
assert.True(t, bond1to1.equal(resBonds[0]))
|
||||
assert.True(t, bond1to2.equal(resBonds[1]))
|
||||
assert.True(t, bond1to3.equal(resBonds[2]))
|
||||
resBonds = viewSlashKeeper.GetDelegatorBonds(ctx, addrDels[0], 3)
|
||||
require.Equal(t, 3, len(resBonds))
|
||||
resBonds = viewSlashKeeper.GetDelegatorBonds(ctx, addrDels[0], 2)
|
||||
require.Equal(t, 2, len(resBonds))
|
||||
resBonds = viewSlashKeeper.GetDelegatorBonds(ctx, addrDels[1], 5)
|
||||
require.Equal(t, 3, len(resBonds))
|
||||
assert.True(t, bondsEqual(bond2to1, resBonds[0]))
|
||||
assert.True(t, bondsEqual(bond2to2, resBonds[1]))
|
||||
assert.True(t, bondsEqual(bond2to3, resBonds[2]))
|
||||
assert.True(t, bond2to1.equal(resBonds[0]))
|
||||
assert.True(t, bond2to2.equal(resBonds[1]))
|
||||
assert.True(t, bond2to3.equal(resBonds[2]))
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue