Skip to content

Commit

Permalink
refactor: use mocks for x/distribution (cosmos#12889)
Browse files Browse the repository at this point in the history
* initial commit

* add mocks

* TestAllocateTokensToManyValidators

* one file more in, like a hundred left

* progress

* progress

* move tests to integration

* finally got TestCalculateRewardsMultiDelegator right lol

* small fixes

* progress

* progress

* progress

* progress

* revert test panic

* progress

* progress

* more progress

* fix go.mod

* merge

* merge

* cache issue?

* fix go.sum

* fix tests

* make mocks

* move back simulations

Co-authored-by: Marko <marbar3778@yahoo.com>
  • Loading branch information
facundomedica and tac0turtle committed Aug 29, 2022
1 parent 8436dc1 commit 0024a0b
Show file tree
Hide file tree
Showing 19 changed files with 2,730 additions and 596 deletions.
1 change: 1 addition & 0 deletions scripts/mockgen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ $mockgen_cmd -source=x/authz/expected_keepers.go -package testutil -destination
$mockgen_cmd -source=x/bank/types/expected_keepers.go -package testutil -destination x/bank/testutil/expected_keepers_mocks.go
$mockgen_cmd -source=x/group/testutil/expected_keepers.go -package testutil -destination x/group/testutil/expected_keepers_mocks.go
$mockgen_cmd -source=x/evidence/types/expected_keepers.go -package testutil -destination x/evidence/testutil/expected_keepers_mocks.go
$mockgen_cmd -source=x/distribution/types/expected_keepers.go -package testutil -destination x/distribution/testutil/expected_keepers_mocks.go
$mockgen_cmd -source=x/slashing/types/expected_keepers.go -package testutil -destination x/slashing/testutil/expected_keepers_mocks.go
$mockgen_cmd -source=x/genutil/types/expected_keepers.go -package testutil -destination x/genutil/testutil/expected_keepers_mocks.go
$mockgen_cmd -source=x/gov/testutil/expected_keepers.go -package testutil -destination x/gov/testutil/expected_keepers_mocks.go
Expand Down
248 changes: 248 additions & 0 deletions tests/integration/distribution/keeper/allocation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
package keeper_test

import (
"testing"

"cosmossdk.io/math"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/cosmos/cosmos-sdk/x/distribution/testutil"
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
var (
bankKeeper bankkeeper.Keeper
distrKeeper keeper.Keeper
stakingKeeper *stakingkeeper.Keeper
)

app, err := simtestutil.Setup(testutil.AppConfig,
&bankKeeper,
&distrKeeper,
&stakingKeeper,
)
require.NoError(t, err)

ctx := app.BaseApp.NewContext(false, tmproto.Header{})

addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 3, sdk.NewInt(1234))
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)

// create validator with 50% commission
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
tstaking.CreateValidator(sdk.ValAddress(addrs[0]), valConsPk0, sdk.NewInt(100), true)
val := stakingKeeper.Validator(ctx, valAddrs[0])

// allocate tokens
tokens := sdk.DecCoins{
{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(10)},
}
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)

// check commission
expected := sdk.DecCoins{
{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(5)},
}
require.Equal(t, expected, distrKeeper.GetValidatorAccumulatedCommission(ctx, val.GetOperator()).Commission)

// check current rewards
require.Equal(t, expected, distrKeeper.GetValidatorCurrentRewards(ctx, val.GetOperator()).Rewards)
}

func TestAllocateTokensToManyValidators(t *testing.T) {
var (
accountKeeper authkeeper.AccountKeeper
bankKeeper bankkeeper.Keeper
distrKeeper keeper.Keeper
stakingKeeper *stakingkeeper.Keeper
)

app, err := simtestutil.Setup(testutil.AppConfig,
&accountKeeper,
&bankKeeper,
&distrKeeper,
&stakingKeeper,
)
require.NoError(t, err)

ctx := app.BaseApp.NewContext(false, tmproto.Header{})

// reset fee pool
distrKeeper.SetFeePool(ctx, disttypes.InitialFeePool())

addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1234))
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)

// create validator with 50% commission
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(100), true)

// create second validator with 0% commission
tstaking.Commission = stakingtypes.NewCommissionRates(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0))
tstaking.CreateValidator(valAddrs[1], valConsPk1, sdk.NewInt(100), true)

abciValA := abci.Validator{
Address: valConsPk0.Address(),
Power: 100,
}
abciValB := abci.Validator{
Address: valConsPk1.Address(),
Power: 100,
}

// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsZero())
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
require.True(t, distrKeeper.GetFeePool(ctx).CommunityPool.IsZero())
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards.IsZero())
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards.IsZero())

// allocate tokens as if both had voted and second was proposer
fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))
feeCollector := accountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
require.NotNil(t, feeCollector)

// fund fee collector
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, feeCollector.GetName(), fees))

accountKeeper.SetAccount(ctx, feeCollector)

votes := []abci.VoteInfo{
{
Validator: abciValA,
SignedLastBlock: true,
},
{
Validator: abciValB,
SignedLastBlock: true,
},
}
distrKeeper.AllocateTokens(ctx, 200, votes)

// 98 outstanding rewards (100 less 2 to community pool)
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards)
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards)

// 2 community pool coins
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(2)}}, distrKeeper.GetFeePool(ctx).CommunityPool)

// 50% commission for first proposer, (0.5 * 98%) * 100 / 2 = 23.25
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2450, 2)}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)

// zero commission for second proposer
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())

// just staking.proportional for first proposer less commission = (0.5 * 98%) * 100 / 2 = 24.50
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2450, 2)}}, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards)

// proposer reward + staking.proportional for second proposer = (0.5 * (98%)) * 100 = 49
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards)
}

func TestAllocateTokensTruncation(t *testing.T) {
var (
accountKeeper authkeeper.AccountKeeper
bankKeeper bankkeeper.Keeper
distrKeeper keeper.Keeper
stakingKeeper *stakingkeeper.Keeper
)

app, err := simtestutil.Setup(testutil.AppConfig,
&accountKeeper,
&bankKeeper,
&distrKeeper,
&stakingKeeper,
)
require.NoError(t, err)

ctx := app.BaseApp.NewContext(false, tmproto.Header{})

// reset fee pool
distrKeeper.SetFeePool(ctx, disttypes.InitialFeePool())

addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 3, sdk.NewInt(1234))
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)

// create validator with 10% commission
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(110), true)

// create second validator with 10% commission
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
tstaking.CreateValidator(valAddrs[1], valConsPk1, sdk.NewInt(100), true)

// create third validator with 10% commission
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
tstaking.CreateValidator(valAddrs[2], valConsPk2, sdk.NewInt(100), true)

abciValA := abci.Validator{
Address: valConsPk0.Address(),
Power: 11,
}
abciValB := abci.Validator{
Address: valConsPk1.Address(),
Power: 10,
}
abciValС := abci.Validator{
Address: valConsPk2.Address(),
Power: 10,
}

// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsZero())
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
require.True(t, distrKeeper.GetFeePool(ctx).CommunityPool.IsZero())
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards.IsZero())
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards.IsZero())

// allocate tokens as if both had voted and second was proposer
fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(634195840)))

feeCollector := accountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
require.NotNil(t, feeCollector)

require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, feeCollector.GetName(), fees))

accountKeeper.SetAccount(ctx, feeCollector)

votes := []abci.VoteInfo{
{
Validator: abciValA,
SignedLastBlock: true,
},
{
Validator: abciValB,
SignedLastBlock: true,
},
{
Validator: abciValС,
SignedLastBlock: true,
},
}
distrKeeper.AllocateTokens(ctx, 31, votes)

require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsValid())
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsValid())
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[2]).Rewards.IsValid())
}
21 changes: 21 additions & 0 deletions tests/integration/distribution/keeper/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package keeper_test

import (
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)

var (
PKS = simtestutil.CreateTestPubKeys(5)

valConsPk0 = PKS[0]
valConsPk1 = PKS[1]
valConsPk2 = PKS[2]

valConsAddr0 = sdk.ConsAddress(valConsPk0.Address())
valConsAddr1 = sdk.ConsAddress(valConsPk1.Address())

distrAcc = authtypes.NewEmptyModuleAccount(types.ModuleName)
)
Loading

0 comments on commit 0024a0b

Please sign in to comment.