ctx with proposer, working through allocation test

This commit is contained in:
rigelrozanski 2018-10-10 17:43:47 -04:00
parent 22de85651f
commit 3b5e57be08
8 changed files with 157 additions and 34 deletions

View File

@ -188,6 +188,12 @@ func (c Context) WithBlockTime(newTime time.Time) Context {
return c.WithBlockHeader(newHeader)
}
func (c Context) WithProposer(addr ConsAddress) Context {
newHeader := c.BlockHeader()
newHeader.ProposerAddress = addr.Bytes()
return c.WithBlockHeader(newHeader)
}
func (c Context) WithBlockHeight(height int64) Context {
return c.withValue(contextKeyBlockHeight, height)
}

View File

@ -1,8 +1,6 @@
package distribution
import (
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -12,8 +10,10 @@ import (
// set the proposer for determining distribution during endblock
func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) {
consAddr := sdk.ConsAddress(req.Header.ProposerAddress)
fmt.Printf("debug consAddr: %v\n", consAddr)
k.SetProposerConsAddr(ctx, consAddr)
// XXX TODO actually calculate this
k.SetSumPrecommitPower(ctx, sdk.NewDec(1))
}
// allocate fees

View File

@ -11,6 +11,12 @@ import (
func (k Keeper) AllocateFees(ctx sdk.Context) {
ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("allocation height: %v", ctx.BlockHeight()))
// if there is no power in the system nothing should be allocated
bondedTokens := k.stakeKeeper.TotalPower(ctx)
if bondedTokens.IsZero() {
return
}
// get the proposer of this block
proposerConsAddr := k.GetProposerConsAddr(ctx)
proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposerConsAddr)
@ -22,8 +28,7 @@ func (k Keeper) AllocateFees(ctx sdk.Context) {
feesCollectedDec := types.NewDecCoins(feesCollected)
// allocated rewards to proposer
bondedTokens := k.stakeKeeper.TotalPower(ctx)
sumPowerPrecommitValidators := sdk.NewDec(1) // XXX TODO actually calculate this
sumPowerPrecommitValidators := k.GetSumPrecommitPower(ctx)
proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul(
sumPowerPrecommitValidators).Quo(bondedTokens))
proposerReward := feesCollectedDec.MulDec(proposerMultiplier)

View File

@ -1,7 +1,52 @@
package keeper
import "testing"
import (
"testing"
func TestAllocateFees(t *testing.T) {
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAllocateFeesBasic(t *testing.T) {
// no community tax on inputs
ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
stakeHandler := stake.NewHandler(sk)
denom := sk.GetParams(ctx).BondDenom
//first make a validator
msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, 10)
got := stakeHandler(ctx, msgCreateValidator)
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
// verify everything has been set in staking correctly
validator, found := sk.GetValidator(ctx, valOpAddr1)
require.True(t, found)
require.Equal(t, sdk.Bonded, validator.Status)
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
bondedTokens := sk.TotalPower(ctx)
assert.True(sdk.DecEq(t, sdk.NewDec(10), bondedTokens))
// initial fee pool should be empty
feePool := keeper.GetFeePool(ctx)
require.Nil(t, feePool.Pool)
// allocate 10 denom of fees
feeInputs := sdk.NewInt(100)
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
ctx = ctx.WithProposer(valConsAddr1)
keeper.SetProposerConsAddr(ctx, valConsAddr1)
keeper.SetSumPrecommitPower(ctx, sdk.NewDec(10))
keeper.AllocateFees(ctx)
// verify that these fees have been received by the feePool
feePool = keeper.GetFeePool(ctx)
expRes := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(95, 2)) // 5% goes to proposer
require.Equal(t, 1, len(feePool.Pool))
require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount))
}

View File

@ -3,29 +3,38 @@ package keeper
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/stretchr/testify/require"
)
func TestWithdrawDelegationReward(t *testing.T) {
ctx, accMapper, keeper, sk := CreateTestInput(t, false, 100)
ctx, accMapper, keeper, sk, fck := CreateTestInputDefault(t, false, 100)
stakeHandler := stake.NewHandler(sk)
denom := sk.GetParams(ctx).BondDenom
//first make a validator
msgCreateValidator := stake.NewTestMsgCreateValidator(valAddr1, valPk1, 10)
msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, 10)
got := stakeHandler(ctx, msgCreateValidator)
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
// delegate
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valAddr1, 10)
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
got = stakeHandler(ctx, msgDelegate)
require.True(t, got.IsOK())
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
require.Equal(t, int64(90), amt.Int64())
keeper.WithdrawDelegationReward(ctx, delAddr1, valAddr1)
feeInputs := sdk.NewInt(20)
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
require.Equal(t, int64(100), amt.Int64())
}
func TestWithdrawDelegationRewardsAll(t *testing.T) {

View File

@ -7,11 +7,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/params"
)
// nolint
const (
ParamStoreKeyCommunityTax = "distr/community-tax"
)
// keeper of the stake store
type Keeper struct {
storeKey sdk.StoreKey
@ -70,7 +65,7 @@ func (k Keeper) GetProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress)
b := tstore.Get(ProposerKey)
if b == nil {
panic("Stored fee pool should not have been nil")
panic("Proposer cons address was likely not set in begin block")
}
k.cdc.MustUnmarshalBinary(b, &consAddr)
@ -86,7 +81,30 @@ func (k Keeper) SetProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) {
//______________________________________________________________________
// Returns the current Deposit Procedure from the global param store
// set the proposer public key for this block
func (k Keeper) GetSumPrecommitPower(ctx sdk.Context) (sumPrecommitPower sdk.Dec) {
tstore := ctx.KVStore(k.storeTKey)
b := tstore.Get(ProposerKey)
if b == nil {
panic("Proposer cons address was likely not set in begin block")
}
k.cdc.MustUnmarshalBinary(b, &sumPrecommitPower)
return
}
// get the proposer public key for this block
func (k Keeper) SetSumPrecommitPower(ctx sdk.Context, sumPrecommitPower sdk.Dec) {
tstore := ctx.KVStore(k.storeTKey)
b := k.cdc.MustMarshalBinary(sumPrecommitPower)
tstore.Set(ProposerKey, b)
}
//______________________________________________________________________
// PARAM STORE
// Returns the current CommunityTax rate from the global param store
// nolint: errcheck
func (k Keeper) GetCommunityTax(ctx sdk.Context) sdk.Dec {
var communityTax sdk.Dec

View File

@ -8,11 +8,17 @@ import (
var (
FeePoolKey = []byte{0x00} // key for global distribution state
ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution
DelegationDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution
DelegationDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution
DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info
// transient
ProposerKey = []byte{0x00} // key for storing the proposer operator address
ProposerKey = []byte{0x00} // key for storing the proposer operator address
SumPrecommitPowerKey = []byte{0x01} // key for storing the power of the precommit validators
)
// nolint
const (
ParamStoreKeyCommunityTax = "distr/community-tax"
)
// gets the key for the validator distribution info from address

View File

@ -30,15 +30,22 @@ var (
delAddr2 = sdk.AccAddress(delPk2.Address())
delAddr3 = sdk.AccAddress(delPk3.Address())
valPk1 = ed25519.GenPrivKey().PubKey()
valPk2 = ed25519.GenPrivKey().PubKey()
valPk3 = ed25519.GenPrivKey().PubKey()
valAddr1 = sdk.ValAddress(valPk1.Address())
valAddr2 = sdk.ValAddress(valPk2.Address())
valAddr3 = sdk.ValAddress(valPk3.Address())
valAccAddr1 = sdk.AccAddress(valPk1.Address()) // generate acc addresses for these validator keys too
valAccAddr2 = sdk.AccAddress(valPk2.Address())
valAccAddr3 = sdk.AccAddress(valPk3.Address())
valOpPk1 = ed25519.GenPrivKey().PubKey()
valOpPk2 = ed25519.GenPrivKey().PubKey()
valOpPk3 = ed25519.GenPrivKey().PubKey()
valOpAddr1 = sdk.ValAddress(valOpPk1.Address())
valOpAddr2 = sdk.ValAddress(valOpPk2.Address())
valOpAddr3 = sdk.ValAddress(valOpPk3.Address())
valAccAddr1 = sdk.AccAddress(valOpPk1.Address()) // generate acc addresses for these validator keys too
valAccAddr2 = sdk.AccAddress(valOpPk2.Address())
valAccAddr3 = sdk.AccAddress(valOpPk3.Address())
valConsPk1 = ed25519.GenPrivKey().PubKey()
valConsPk2 = ed25519.GenPrivKey().PubKey()
valConsPk3 = ed25519.GenPrivKey().PubKey()
valConsAddr1 = sdk.ConsAddress(valConsPk1.Address())
valConsAddr2 = sdk.ConsAddress(valConsPk2.Address())
valConsAddr3 = sdk.ConsAddress(valConsPk3.Address())
addrs = []sdk.AccAddress{
delAddr1, delAddr2, delAddr3,
@ -63,9 +70,18 @@ func MakeTestCodec() *codec.Codec {
return cdc
}
// test input with default values
func CreateTestInputDefault(t *testing.T, isCheckTx bool, initCoins int64) (
sdk.Context, auth.AccountMapper, Keeper, stake.Keeper, DummyFeeCollectionKeeper) {
communityTax := sdk.NewDecWithPrec(2, 2)
return CreateTestInputAdvanced(t, isCheckTx, initCoins, communityTax)
}
// hogpodge of all sorts of input required for testing
func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (
sdk.Context, auth.AccountMapper, Keeper, stake.Keeper) {
func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64,
communityTax sdk.Dec) (
sdk.Context, auth.AccountMapper, Keeper, stake.Keeper, DummyFeeCollectionKeeper) {
keyDistr := sdk.NewKVStoreKey("distr")
tkeyDistr := sdk.NewTransientStoreKey("transient_distr")
@ -109,7 +125,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (
sk.SetPool(ctx, pool)
}
fck := auth.NewFeeCollectionKeeper(cdc, keyFeeCollection)
fck := DummyFeeCollectionKeeper{}
pk := params.NewKeeper(cdc, keyParams)
keeper := NewKeeper(cdc, keyDistr, tkeyDistr, pk.Setter(), ck, sk, fck, types.DefaultCodespace)
@ -118,7 +134,25 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (
// set genesis items required for distribution
keeper.SetFeePool(ctx, types.InitialFeePool())
keeper.SetCommunityTax(ctx, sdk.NewDecWithPrec(2, 2))
keeper.SetCommunityTax(ctx, communityTax)
return ctx, accountMapper, keeper, sk
return ctx, accountMapper, keeper, sk, fck
}
//__________________________________________________________________________________
// fee collection keeper used only for testing
type DummyFeeCollectionKeeper struct{}
var heldFees sdk.Coins
var _ types.FeeCollectionKeeper = DummyFeeCollectionKeeper{}
// nolint
func (fck DummyFeeCollectionKeeper) GetCollectedFees(_ sdk.Context) sdk.Coins {
return heldFees
}
func (fck DummyFeeCollectionKeeper) SetCollectedFees(in sdk.Coins) {
heldFees = in
}
func (fck DummyFeeCollectionKeeper) ClearCollectedFees(_ sdk.Context) {
heldFees = sdk.Coins{}
}