feature: add ante handler to block non validators from sending restri… (#273)

* feature: add ante handler to block non validators from sending restricted txs

* fix: add missing msg types and linter errors

* fix: staticcheck error

* refactor: use fallthrough on ante handle switch

* fix: set val address on machine attest test
---------

Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
Lorenz Herzberger 2024-01-11 14:33:20 +01:00 committed by GitHub
parent 001a472ef9
commit 2534828fc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 194 additions and 4 deletions

View File

@ -57,6 +57,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
NewCheckValidatorDecorator(options.StakingKeeper),
NewCheckMachineDecorator(options.MachineKeeper),
NewCheckMintAddressDecorator(options.DaoKeeper),
NewCheckReissuanceDecorator(options.DaoKeeper),

View File

@ -0,0 +1,57 @@
package ante
import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/planetmint/planetmint-go/x/dao/types"
)
type CheckValidatorDecorator struct {
sk StakingKeeper
}
func NewCheckValidatorDecorator(sk StakingKeeper) CheckValidatorDecorator {
return CheckValidatorDecorator{sk: sk}
}
func (cv CheckValidatorDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (_ sdk.Context, err error) {
if simulate || ctx.BlockHeight() == 0 {
return next(ctx, tx, simulate)
}
for _, msg := range tx.GetMsgs() {
switch sdk.MsgTypeURL(msg) {
case "/planetmintgo.dao.MsgInitPop":
fallthrough
case "/planetmintgo.dao.MsgDistributionRequest":
fallthrough
case "/planetmintgo.dao.MsgDistributionResult":
fallthrough
case "/planetmintgo.dao.MsgReissueRDDLProposal":
fallthrough
case "/planetmintgo.dao.MsgReissueRDDLResult":
fallthrough
case "/planetmintgo.machine.MsgNotarizeLiquidAsset":
fallthrough
case "/planetmintgo.machine.MsgRegisterTrustAnchor":
ctx, err = cv.handleMsg(ctx, msg)
default:
continue
}
}
if err != nil {
return ctx, err
}
return next(ctx, tx, simulate)
}
func (cv CheckValidatorDecorator) handleMsg(ctx sdk.Context, msg sdk.Msg) (_ sdk.Context, err error) {
signer := msg.GetSigners()[0]
_, found := cv.sk.GetValidator(ctx, sdk.ValAddress(signer))
if !found {
return ctx, errorsmod.Wrapf(types.ErrRestrictedMsg, "error during CheckTx or ReCheckTx")
}
return ctx, nil
}

View File

@ -22,3 +22,8 @@ func TestGasConsumptionE2ETestSuite(t *testing.T) {
cfg := network.DefaultConfig()
suite.Run(t, NewGasConsumptionE2ETestSuite(cfg))
}
func TestRestrictedMsgsE2ETestSuite(t *testing.T) {
cfg := network.DefaultConfig()
suite.Run(t, NewRestrictedMsgsE2ESuite(cfg))
}

View File

@ -27,7 +27,7 @@ func NewGasConsumptionE2ETestSuite(cfg network.Config) *GasConsumptionE2ETestSui
func (s *GasConsumptionE2ETestSuite) SetupSuite() {
s.T().Log("setting up e2e test suite")
conf := config.GetConfig()
conf.FeeDenom = "stake"
conf.FeeDenom = sample.FeeDenom
s.network = network.New(s.T(), s.cfg)
account, err := e2etestutil.CreateAccount(s.network, sample.Name, sample.Mnemonic)
s.Require().NoError(err)

View File

@ -7,6 +7,7 @@ import (
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/testutil/sample"
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
@ -43,7 +44,7 @@ func NewPopSelectionE2ETestSuite(cfg network.Config) *PopSelectionE2ETestSuite {
func (s *PopSelectionE2ETestSuite) SetupSuite() {
s.T().Log("setting up e2e test suite")
conf := config.GetConfig()
conf.FeeDenom = "stake"
conf.FeeDenom = sample.FeeDenom
s.network = network.New(s.T(), s.cfg)

View File

@ -0,0 +1,122 @@
package dao
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/planetmint/planetmint-go/config"
"github.com/planetmint/planetmint-go/lib"
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
"github.com/planetmint/planetmint-go/testutil/network"
"github.com/planetmint/planetmint-go/testutil/sample"
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
"github.com/stretchr/testify/suite"
)
var msgs = []sdk.Msg{
&daotypes.MsgInitPop{},
&daotypes.MsgDistributionRequest{},
&daotypes.MsgDistributionResult{},
&daotypes.MsgReissueRDDLProposal{},
&daotypes.MsgReissueRDDLResult{},
&machinetypes.MsgRegisterTrustAnchor{},
&machinetypes.MsgNotarizeLiquidAsset{},
}
type RestrictedMsgsE2ESuite struct {
suite.Suite
cfg network.Config
network *network.Network
}
func NewRestrictedMsgsE2ESuite(cfg network.Config) *RestrictedMsgsE2ESuite {
return &RestrictedMsgsE2ESuite{cfg: cfg}
}
func (s *RestrictedMsgsE2ESuite) SetupSuite() {
s.T().Log("setting up e2e test suite")
conf := config.GetConfig()
conf.FeeDenom = sample.FeeDenom
s.network = network.New(s.T(), s.cfg)
account, err := e2etestutil.CreateAccount(s.network, sample.Name, sample.Mnemonic)
s.Require().NoError(err)
err = e2etestutil.FundAccount(s.network, account)
s.Require().NoError(err)
}
func (s *RestrictedMsgsE2ESuite) TearDownSuite() {
s.T().Log("tearing down e2e test suite")
}
func (s *RestrictedMsgsE2ESuite) TestRestrictedMsgsValidator() {
val := s.network.Validators[0]
msg := daotypes.NewMsgInitPop(val.Address.String(), val.Address.String(), val.Address.String(), val.Address.String(), 0)
out, err := lib.BroadcastTxWithFileLock(val.Address, msg)
s.Require().NoError(err)
txResponse, err := lib.GetTxResponseFromOut(out)
s.Require().NoError(err)
s.Require().Equal(int(0), int(txResponse.Code))
}
func (s *RestrictedMsgsE2ESuite) TestRestrictedMsgsNonValidator() {
val := s.network.Validators[0]
k, err := val.ClientCtx.Keyring.Key(sample.Name)
s.Require().NoError(err)
addr, _ := k.GetAddress()
for _, msg := range msgs {
msg = setCreator(msg, addr.String())
out, err := lib.BroadcastTxWithFileLock(addr, msg)
s.Require().NoError(err)
txResponse, err := lib.GetTxResponseFromOut(out)
s.Require().NoError(err)
s.Require().Equal(int(18), int(txResponse.Code))
s.Require().NoError(s.network.WaitForNextBlock())
}
}
func setCreator(msg sdk.Msg, creator string) sdk.Msg {
switch sdk.MsgTypeURL(msg) {
case "/planetmintgo.dao.MsgInitPop":
msg, ok := msg.(*daotypes.MsgInitPop)
if ok {
msg.Creator = creator
}
case "/planetmintgo.dao.MsgDistributionRequest":
msg, ok := msg.(*daotypes.MsgDistributionRequest)
if ok {
msg.Creator = creator
}
case "/planetmintgo.dao.MsgDistributionResult":
msg, ok := msg.(*daotypes.MsgDistributionResult)
if ok {
msg.Creator = creator
}
case "/planetmintgo.dao.MsgReissueRDDLProposal":
msg, ok := msg.(*daotypes.MsgReissueRDDLProposal)
if ok {
msg.Creator = creator
}
case "/planetmintgo.dao.MsgReissueRDDLResult":
msg, ok := msg.(*daotypes.MsgReissueRDDLResult)
if ok {
msg.Creator = creator
}
case "/planetmintgo.machine.MsgNotarizeLiquidAsset":
msg, ok := msg.(*machinetypes.MsgNotarizeLiquidAsset)
if ok {
msg.Creator = creator
}
case "/planetmintgo.machine.MsgRegisterTrustAnchor":
msg, ok := msg.(*machinetypes.MsgRegisterTrustAnchor)
if ok {
msg.Creator = creator
}
}
return msg
}

View File

@ -64,10 +64,10 @@ func (s *RestE2ETestSuite) TestAttestMachineREST() {
// Register TA
ta := sample.TrustAnchor(pubKey)
taMsg := machinetypes.MsgRegisterTrustAnchor{
Creator: addr.String(),
Creator: val.Address.String(),
TrustAnchor: &ta,
}
out, err := e2etestutil.BuildSignBroadcastTx(s.T(), addr, &taMsg)
out, err := e2etestutil.BuildSignBroadcastTx(s.T(), val.Address, &taMsg)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())

View File

@ -32,6 +32,9 @@ const Amount = "1000stake"
// Fees is the amount of fees to use in tests
const Fees = "1stake"
// FeeDenom is the fee denomination for e2e test cases
const FeeDenom = "stake"
// DefaultDerivationPath is the BIP44Prefix for PLMNT (see https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
const DefaultDerivationPath = "m/44'/8680'/0'/0/0"

View File

@ -24,4 +24,5 @@ var (
ErrFailedPoPRewardsIssuance = errorsmod.Register(ModuleName, 15, "PoP rewards issuance failed")
ErrResolvingStagedClaims = errorsmod.Register(ModuleName, 16, "resolving staged claims failed")
ErrReissuanceTxIDMissing = errorsmod.Register(ModuleName, 17, "reissuance has no transaction id")
ErrRestrictedMsg = errorsmod.Register(ModuleName, 18, "restricted validator msg")
)