|
|
|
@@ -7,29 +7,43 @@ import (
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"cosmossdk.io/core/comet"
|
|
|
|
|
"cosmossdk.io/depinject"
|
|
|
|
|
"cosmossdk.io/log"
|
|
|
|
|
storetypes "cosmossdk.io/store/types"
|
|
|
|
|
"cosmossdk.io/x/evidence"
|
|
|
|
|
"cosmossdk.io/x/evidence/exported"
|
|
|
|
|
"cosmossdk.io/x/evidence/keeper"
|
|
|
|
|
"cosmossdk.io/x/evidence/testutil"
|
|
|
|
|
"cosmossdk.io/x/evidence/types"
|
|
|
|
|
evidencetypes "cosmossdk.io/x/evidence/types"
|
|
|
|
|
abci "github.com/cometbft/cometbft/abci/types"
|
|
|
|
|
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
|
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
|
|
|
|
|
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec/address"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
|
|
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/runtime"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/testutil/integration"
|
|
|
|
|
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
|
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
|
|
|
|
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
|
|
|
|
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
|
|
|
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
|
|
|
|
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
|
|
|
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
|
|
|
|
consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types"
|
|
|
|
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
|
|
|
|
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/slashing"
|
|
|
|
|
slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/slashing/testutil"
|
|
|
|
|
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/staking"
|
|
|
|
|
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
|
|
|
|
stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil"
|
|
|
|
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
@@ -51,51 +65,101 @@ var (
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type fixture struct {
|
|
|
|
|
ctx sdk.Context
|
|
|
|
|
app *runtime.App
|
|
|
|
|
app *integration.App
|
|
|
|
|
|
|
|
|
|
evidenceKeeper keeper.Keeper
|
|
|
|
|
bankKeeper bankkeeper.Keeper
|
|
|
|
|
accountKeeper authkeeper.AccountKeeper
|
|
|
|
|
slashingKeeper slashingkeeper.Keeper
|
|
|
|
|
stakingKeeper *stakingkeeper.Keeper
|
|
|
|
|
interfaceRegistry codectypes.InterfaceRegistry
|
|
|
|
|
sdkCtx sdk.Context
|
|
|
|
|
cdc codec.Codec
|
|
|
|
|
|
|
|
|
|
bankKeeper bankkeeper.Keeper
|
|
|
|
|
evidenceKeeper *keeper.Keeper
|
|
|
|
|
slashingKeeper slashingkeeper.Keeper
|
|
|
|
|
stakingKeeper *stakingkeeper.Keeper
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func initFixture(t assert.TestingT) *fixture {
|
|
|
|
|
f := &fixture{}
|
|
|
|
|
var evidenceKeeper keeper.Keeper
|
|
|
|
|
|
|
|
|
|
app, err := simtestutil.Setup(
|
|
|
|
|
depinject.Configs(
|
|
|
|
|
testutil.AppConfig,
|
|
|
|
|
depinject.Supply(log.NewNopLogger()),
|
|
|
|
|
),
|
|
|
|
|
&evidenceKeeper,
|
|
|
|
|
&f.interfaceRegistry,
|
|
|
|
|
&f.accountKeeper,
|
|
|
|
|
&f.bankKeeper,
|
|
|
|
|
&f.slashingKeeper,
|
|
|
|
|
&f.stakingKeeper,
|
|
|
|
|
func initFixture(t testing.TB) *fixture {
|
|
|
|
|
keys := storetypes.NewKVStoreKeys(
|
|
|
|
|
authtypes.StoreKey, banktypes.StoreKey, paramtypes.StoreKey, consensusparamtypes.StoreKey, evidencetypes.StoreKey, stakingtypes.StoreKey, slashingtypes.StoreKey,
|
|
|
|
|
)
|
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, evidence.AppModuleBasic{}).Codec
|
|
|
|
|
|
|
|
|
|
router := types.NewRouter()
|
|
|
|
|
router = router.AddRoute(types.RouteEquivocation, testEquivocationHandler(evidenceKeeper))
|
|
|
|
|
logger := log.NewTestLogger(t)
|
|
|
|
|
cms := integration.CreateMultiStore(keys, logger)
|
|
|
|
|
|
|
|
|
|
newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)
|
|
|
|
|
|
|
|
|
|
authority := authtypes.NewModuleAddress("gov")
|
|
|
|
|
|
|
|
|
|
maccPerms := map[string][]string{
|
|
|
|
|
minttypes.ModuleName: {authtypes.Minter},
|
|
|
|
|
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
|
|
|
|
|
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
accountKeeper := authkeeper.NewAccountKeeper(
|
|
|
|
|
cdc,
|
|
|
|
|
runtime.NewKVStoreService(keys[authtypes.StoreKey]),
|
|
|
|
|
authtypes.ProtoBaseAccount,
|
|
|
|
|
maccPerms,
|
|
|
|
|
sdk.Bech32MainPrefix,
|
|
|
|
|
authority.String(),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
blockedAddresses := map[string]bool{
|
|
|
|
|
accountKeeper.GetAuthority(): false,
|
|
|
|
|
}
|
|
|
|
|
bankKeeper := bankkeeper.NewBaseKeeper(
|
|
|
|
|
cdc,
|
|
|
|
|
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
|
|
|
|
|
accountKeeper,
|
|
|
|
|
blockedAddresses,
|
|
|
|
|
authority.String(),
|
|
|
|
|
log.NewNopLogger(),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
stakingKeeper := stakingkeeper.NewKeeper(cdc, keys[stakingtypes.StoreKey], accountKeeper, bankKeeper, authority.String())
|
|
|
|
|
|
|
|
|
|
slashingKeeper := slashingkeeper.NewKeeper(cdc, codec.NewLegacyAmino(), keys[slashingtypes.StoreKey], stakingKeeper, authority.String())
|
|
|
|
|
|
|
|
|
|
evidenceKeeper := keeper.NewKeeper(cdc, keys[evidencetypes.StoreKey], stakingKeeper, slashingKeeper, address.NewBech32Codec("cosmos"), runtime.ProvideCometInfoService())
|
|
|
|
|
router := evidencetypes.NewRouter()
|
|
|
|
|
router = router.AddRoute(evidencetypes.RouteEquivocation, testEquivocationHandler(evidenceKeeper))
|
|
|
|
|
evidenceKeeper.SetRouter(router)
|
|
|
|
|
|
|
|
|
|
f.ctx = app.BaseApp.NewContext(false, cmtproto.Header{Height: 1})
|
|
|
|
|
f.app = app
|
|
|
|
|
f.evidenceKeeper = evidenceKeeper
|
|
|
|
|
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
|
|
|
|
|
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
|
|
|
|
|
stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil)
|
|
|
|
|
slashingModule := slashing.NewAppModule(cdc, slashingKeeper, accountKeeper, bankKeeper, stakingKeeper, nil, cdc.InterfaceRegistry())
|
|
|
|
|
evidenceModule := evidence.NewAppModule(*evidenceKeeper)
|
|
|
|
|
|
|
|
|
|
return f
|
|
|
|
|
integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, authModule, bankModule, stakingModule, slashingModule, evidenceModule)
|
|
|
|
|
|
|
|
|
|
sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context())
|
|
|
|
|
|
|
|
|
|
// Register MsgServer and QueryServer
|
|
|
|
|
evidencetypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), keeper.NewMsgServerImpl(*evidenceKeeper))
|
|
|
|
|
evidencetypes.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewQuerier(evidenceKeeper))
|
|
|
|
|
|
|
|
|
|
slashingKeeper.SetParams(sdkCtx, testutil.TestParams())
|
|
|
|
|
|
|
|
|
|
// set default staking params
|
|
|
|
|
stakingKeeper.SetParams(sdkCtx, stakingtypes.DefaultParams())
|
|
|
|
|
|
|
|
|
|
return &fixture{
|
|
|
|
|
app: integrationApp,
|
|
|
|
|
sdkCtx: sdkCtx,
|
|
|
|
|
cdc: cdc,
|
|
|
|
|
bankKeeper: bankKeeper,
|
|
|
|
|
evidenceKeeper: evidenceKeeper,
|
|
|
|
|
slashingKeeper: slashingKeeper,
|
|
|
|
|
stakingKeeper: stakingKeeper,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestHandleDoubleSign(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
f := initFixture(t)
|
|
|
|
|
|
|
|
|
|
ctx := f.ctx.WithIsCheckTx(false).WithBlockHeight(1)
|
|
|
|
|
ctx := f.sdkCtx.WithIsCheckTx(false).WithBlockHeight(1)
|
|
|
|
|
populateValidators(t, f)
|
|
|
|
|
|
|
|
|
|
power := int64(100)
|
|
|
|
@@ -106,13 +170,18 @@ func TestHandleDoubleSign(t *testing.T) {
|
|
|
|
|
selfDelegation := tstaking.CreateValidatorWithValPower(operatorAddr, val, power, true)
|
|
|
|
|
|
|
|
|
|
// execute end-blocker and verify validator attributes
|
|
|
|
|
f.stakingKeeper.EndBlocker(f.ctx)
|
|
|
|
|
f.stakingKeeper.EndBlocker(f.sdkCtx)
|
|
|
|
|
assert.DeepEqual(t,
|
|
|
|
|
f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(operatorAddr)).String(),
|
|
|
|
|
sdk.NewCoins(sdk.NewCoin(stakingParams.BondDenom, initAmt.Sub(selfDelegation))).String(),
|
|
|
|
|
)
|
|
|
|
|
assert.DeepEqual(t, selfDelegation, f.stakingKeeper.Validator(ctx, operatorAddr).GetBondedTokens())
|
|
|
|
|
|
|
|
|
|
f.slashingKeeper.AddPubkey(f.sdkCtx, val)
|
|
|
|
|
|
|
|
|
|
info := slashingtypes.NewValidatorSigningInfo(sdk.ConsAddress(val.Address()), f.sdkCtx.BlockHeight(), int64(0), time.Unix(0, 0), false, int64(0))
|
|
|
|
|
f.slashingKeeper.SetValidatorSigningInfo(f.sdkCtx, sdk.ConsAddress(val.Address()), info)
|
|
|
|
|
|
|
|
|
|
// handle a signature to set signing info
|
|
|
|
|
f.slashingKeeper.HandleValidatorSignature(ctx, val.Address(), selfDelegation.Int64(), true)
|
|
|
|
|
|
|
|
|
@@ -123,14 +192,13 @@ func TestHandleDoubleSign(t *testing.T) {
|
|
|
|
|
ByzantineValidators: []abci.Misbehavior{{
|
|
|
|
|
Validator: abci.Validator{Address: val.Address(), Power: power},
|
|
|
|
|
Type: abci.MisbehaviorType_DUPLICATE_VOTE,
|
|
|
|
|
Time: time.Unix(0, 0),
|
|
|
|
|
Height: 0,
|
|
|
|
|
Time: time.Now().UTC(),
|
|
|
|
|
Height: 1,
|
|
|
|
|
}},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
ctx = ctx.WithCometInfo(nci)
|
|
|
|
|
|
|
|
|
|
f.evidenceKeeper.BeginBlocker(ctx)
|
|
|
|
|
f.evidenceKeeper.BeginBlocker(ctx.WithCometInfo(nci))
|
|
|
|
|
|
|
|
|
|
// should be jailed and tombstoned
|
|
|
|
|
assert.Assert(t, f.stakingKeeper.Validator(ctx, operatorAddr).IsJailed())
|
|
|
|
@@ -170,18 +238,19 @@ func TestHandleDoubleSign_TooOld(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
f := initFixture(t)
|
|
|
|
|
|
|
|
|
|
ctx := f.ctx.WithIsCheckTx(false).WithBlockHeight(1).WithBlockTime(time.Now())
|
|
|
|
|
ctx := f.sdkCtx.WithIsCheckTx(false).WithBlockHeight(1).WithBlockTime(time.Now())
|
|
|
|
|
populateValidators(t, f)
|
|
|
|
|
|
|
|
|
|
power := int64(100)
|
|
|
|
|
stakingParams := f.stakingKeeper.GetParams(ctx)
|
|
|
|
|
operatorAddr, val := valAddresses[0], pubkeys[0]
|
|
|
|
|
|
|
|
|
|
tstaking := stakingtestutil.NewHelper(t, ctx, f.stakingKeeper)
|
|
|
|
|
|
|
|
|
|
amt := tstaking.CreateValidatorWithValPower(operatorAddr, val, power, true)
|
|
|
|
|
|
|
|
|
|
// execute end-blocker and verify validator attributes
|
|
|
|
|
f.stakingKeeper.EndBlocker(f.ctx)
|
|
|
|
|
f.stakingKeeper.EndBlocker(f.sdkCtx)
|
|
|
|
|
assert.DeepEqual(t,
|
|
|
|
|
f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(operatorAddr)),
|
|
|
|
|
sdk.NewCoins(sdk.NewCoin(stakingParams.BondDenom, initAmt.Sub(amt))),
|
|
|
|
@@ -197,6 +266,7 @@ func TestHandleDoubleSign_TooOld(t *testing.T) {
|
|
|
|
|
}},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
f.app.BaseApp.StoreConsensusParams(ctx, *simtestutil.DefaultConsensusParams)
|
|
|
|
|
cp := f.app.BaseApp.GetConsensusParams(ctx)
|
|
|
|
|
|
|
|
|
|
ctx = ctx.WithCometInfo(nci)
|
|
|
|
@@ -214,10 +284,10 @@ func populateValidators(t assert.TestingT, f *fixture) {
|
|
|
|
|
// add accounts and set total supply
|
|
|
|
|
totalSupplyAmt := initAmt.MulRaw(int64(len(valAddresses)))
|
|
|
|
|
totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, totalSupplyAmt))
|
|
|
|
|
assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, totalSupply))
|
|
|
|
|
assert.NilError(t, f.bankKeeper.MintCoins(f.sdkCtx, minttypes.ModuleName, totalSupply))
|
|
|
|
|
|
|
|
|
|
for _, addr := range valAddresses {
|
|
|
|
|
assert.NilError(t, f.bankKeeper.SendCoinsFromModuleToAccount(f.ctx, minttypes.ModuleName, (sdk.AccAddress)(addr), initCoins))
|
|
|
|
|
assert.NilError(t, f.bankKeeper.SendCoinsFromModuleToAccount(f.sdkCtx, minttypes.ModuleName, (sdk.AccAddress)(addr), initCoins))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -232,13 +302,13 @@ func newPubKey(pk string) (res cryptotypes.PubKey) {
|
|
|
|
|
return pubkey
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func testEquivocationHandler(_ interface{}) types.Handler {
|
|
|
|
|
func testEquivocationHandler(_ interface{}) evidencetypes.Handler {
|
|
|
|
|
return func(ctx sdk.Context, e exported.Evidence) error {
|
|
|
|
|
if err := e.ValidateBasic(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ee, ok := e.(*types.Equivocation)
|
|
|
|
|
ee, ok := e.(*evidencetypes.Equivocation)
|
|
|
|
|
if !ok {
|
|
|
|
|
return fmt.Errorf("unexpected evidence type: %T", e)
|
|
|
|
|
}
|
|
|
|
|