Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(x/**): rewrite ante handlers as tx validators #19949

Merged
merged 16 commits into from
Apr 25, 2024
6 changes: 3 additions & 3 deletions x/auth/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
}

anteDecorators := []sdk.AnteDecorator{
NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
NewSetUpContextDecorator(options.AccountKeeper), // outermost AnteDecorator. SetUpContext must be called first
NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
NewValidateBasicDecorator(),
NewTxTimeoutHeightDecorator(),
NewValidateBasicDecorator(options.AccountKeeper),
NewTxTimeoutHeightDecorator(options.AccountKeeper),
NewValidateMemoDecorator(options.AccountKeeper),
NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
Expand Down
108 changes: 79 additions & 29 deletions x/auth/ante/basic.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ante

import (
"context"

errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"
"cosmossdk.io/x/auth/migrations/legacytx"
Expand All @@ -18,25 +20,37 @@
// If ValidateBasic passes, decorator calls next AnteHandler in chain. Note,
// ValidateBasicDecorator decorator will not get executed on ReCheckTx since it
// is not dependent on application state.
type ValidateBasicDecorator struct{}
type ValidateBasicDecorator struct {
ak AccountKeeper
}

func NewValidateBasicDecorator(ak AccountKeeper) ValidateBasicDecorator {
return ValidateBasicDecorator{
ak: ak,
}
}

func NewValidateBasicDecorator() ValidateBasicDecorator {
return ValidateBasicDecorator{}
func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if err := vbd.ValidateTx(ctx, tx); err != nil {
return ctx, err
}

return next(ctx, tx, false)
}

func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
func (vbd ValidateBasicDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
// no need to validate basic on recheck tx, call next antehandler
if ctx.ExecMode() == sdk.ExecModeReCheck {

Check failure on line 43 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / dependency-review

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 43 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (03)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 43 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (00)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 43 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (00)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 43 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (01)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 43 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (01)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 43 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (02)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 43 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (02)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)
return next(ctx, tx, false)
return nil
}

if validateBasic, ok := tx.(sdk.HasValidateBasic); ok {
if err := validateBasic.ValidateBasic(); err != nil {
return ctx, err
return err
}
}

return next(ctx, tx, ctx.ExecMode() == sdk.ExecModeSimulate)
return nil
}

// ValidateMemoDecorator will validate memo given the parameters passed in
Expand All @@ -52,24 +66,32 @@
}
}

func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
memoTx, ok := tx.(sdk.TxWithMemo)
func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if err := vmd.ValidateTx(ctx, tx); err != nil {
return ctx, err
}

return next(ctx, tx, false)
}

func (vmd ValidateMemoDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
memoTx, ok := tx.(sdk.TxWithMemo) // TODO: what do we do with this.
if !ok {
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}

memoLength := len(memoTx.GetMemo())
if memoLength > 0 {
params := vmd.ak.GetParams(ctx)
if uint64(memoLength) > params.MaxMemoCharacters {
return ctx, errorsmod.Wrapf(sdkerrors.ErrMemoTooLarge,
return errorsmod.Wrapf(sdkerrors.ErrMemoTooLarge,
"maximum number of characters is %d but received %d characters",
params.MaxMemoCharacters, memoLength,
)
}
}

return next(ctx, tx, ctx.ExecMode() == sdk.ExecModeSimulate)
return nil
}

// ConsumeTxSizeGasDecorator will take in parameters and consume gas proportional
Expand All @@ -91,21 +113,32 @@
}
}

func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if err := cgts.ValidateTx(ctx, tx); err != nil {
return ctx, err
}

return next(ctx, tx, false)
}

func (cgts ConsumeTxSizeGasDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
sigTx, ok := tx.(authsigning.SigVerifiableTx) // TODO: what do we do with this.
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
if !ok {
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
}
params := cgts.ak.GetParams(ctx)

ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*storetypes.Gas(len(ctx.TxBytes())), "txSize")
gasService := cgts.ak.Environment().GasService
if err := gasService.GetGasMeter(ctx).Consume(params.TxSizeCostPerByte*storetypes.Gas(len(tx.Bytes())), "txSize"); err != nil {
return err
}

// simulate gas cost for signatures in simulate mode
if ctx.ExecMode() == sdk.ExecModeSimulate {

Check failure on line 137 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / dependency-review

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 137 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (03)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 137 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (00)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 137 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (00)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 137 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (01)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 137 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (01)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 137 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (02)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)

Check failure on line 137 in x/auth/ante/basic.go

View workflow job for this annotation

GitHub Actions / tests (02)

ctx.ExecMode undefined (type context.Context has no field or method ExecMode)
// in simulate mode, each element should be a nil signature
sigs, err := sigTx.GetSignaturesV2()
if err != nil {
return ctx, err
return err
}
n := len(sigs)

Expand Down Expand Up @@ -139,11 +172,13 @@
cost *= params.TxSigLimit
}

ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*cost, "txSize")
if err := gasService.GetGasMeter(ctx).Consume(params.TxSizeCostPerByte*cost, "txSize"); err != nil {
return err
}
}
}

return next(ctx, tx, ctx.ExecMode() == sdk.ExecModeSimulate)
return nil
}

// isIncompleteSignature tests whether SignatureData is fully filled in for simulation purposes
Expand Down Expand Up @@ -172,7 +207,9 @@
type (
// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
// tx height timeout.
TxTimeoutHeightDecorator struct{}
TxTimeoutHeightDecorator struct {
ak AccountKeeper
}

// TxWithTimeoutHeight defines the interface a tx must implement in order for
// TxHeightTimeoutDecorator to process the tx.
Expand All @@ -185,26 +222,39 @@

// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
// tx height timeout.
func NewTxTimeoutHeightDecorator() TxTimeoutHeightDecorator {
return TxTimeoutHeightDecorator{}
func NewTxTimeoutHeightDecorator(ak AccountKeeper) TxTimeoutHeightDecorator {
return TxTimeoutHeightDecorator{
ak: ak,
}
}

// AnteHandle implements an AnteHandler decorator for the TxHeightTimeoutDecorator.
func (txh TxTimeoutHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if err := txh.ValidateTx(ctx, tx); err != nil {
return ctx, err
}

return next(ctx, tx, false)
}

// AnteHandle implements an AnteHandler decorator for the TxHeightTimeoutDecorator
// ValidateTx implements an TxValidator decorator for the TxHeightTimeoutDecorator
// type where the current block height is checked against the tx's height timeout.
// If a height timeout is provided (non-zero) and is less than the current block
// height, then an error is returned.
func (txh TxTimeoutHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
func (txh TxTimeoutHeightDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
timeoutTx, ok := tx.(TxWithTimeoutHeight)
if !ok {
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "expected tx to implement TxWithTimeoutHeight")
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "expected tx to implement TxWithTimeoutHeight")
}

timeoutHeight := timeoutTx.GetTimeoutHeight()
if timeoutHeight > 0 && uint64(ctx.BlockHeight()) > timeoutHeight {
return ctx, errorsmod.Wrapf(
sdkerrors.ErrTxTimeoutHeight, "block height: %d, timeout height: %d", ctx.BlockHeight(), timeoutHeight,
headerInfo := txh.ak.Environment().HeaderService.GetHeaderInfo(ctx)

if timeoutHeight > 0 && uint64(headerInfo.Height) > timeoutHeight {
return errorsmod.Wrapf(
sdkerrors.ErrTxTimeoutHeight, "block height: %d, timeout height: %d", headerInfo.Height, timeoutHeight,
)
}

return next(ctx, tx, ctx.ExecMode() == sdk.ExecModeSimulate)
return nil
}
4 changes: 2 additions & 2 deletions x/auth/ante/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestValidateBasic(t *testing.T) {
invalidTx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
require.NoError(t, err)

vbd := ante.NewValidateBasicDecorator()
vbd := ante.NewValidateBasicDecorator(suite.accountKeeper)
antehandler := sdk.ChainAnteDecorators(vbd)
_, err = antehandler(suite.ctx, invalidTx, false)

Expand Down Expand Up @@ -182,7 +182,7 @@ func TestConsumeGasForTxSize(t *testing.T) {
func TestTxHeightTimeoutDecorator(t *testing.T) {
suite := SetupTestSuite(t, true)

antehandler := sdk.ChainAnteDecorators(ante.NewTxTimeoutHeightDecorator())
antehandler := sdk.ChainAnteDecorators(ante.NewTxTimeoutHeightDecorator(suite.accountKeeper))

// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
Expand Down
2 changes: 2 additions & 0 deletions x/auth/ante/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

"cosmossdk.io/core/address"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/x/auth/types"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -18,6 +19,7 @@ type AccountKeeper interface {
GetModuleAddress(moduleName string) sdk.AccAddress
AddressCodec() address.Codec
NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI
Environment() appmodule.Environment
}

// FeegrantKeeper defines the expected feegrant keeper.
Expand Down
36 changes: 25 additions & 11 deletions x/auth/ante/setup.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ante

import (
"context"
"fmt"

errorsmod "cosmossdk.io/errors"
Expand All @@ -21,29 +22,42 @@
// on gas provided and gas used.
// CONTRACT: Must be first decorator in the chain
// CONTRACT: Tx must implement GasTx interface
type SetUpContextDecorator struct{}
type SetUpContextDecorator struct {
ak AccountKeeper
}

func NewSetUpContextDecorator() SetUpContextDecorator {
return SetUpContextDecorator{}
func NewSetUpContextDecorator(ak AccountKeeper) SetUpContextDecorator {
return SetUpContextDecorator{
ak: ak,
}
}

func (sud SetUpContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if err := sud.ValidateTx(ctx, tx); err != nil {
return ctx, err
}

return next(ctx, tx, false)
}

func (sud SetUpContextDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) (err error) {
gasService := sud.ak.Environment().GasService

// all transactions must implement GasTx
gasTx, ok := tx.(GasTx)
gasTx, ok := tx.(GasTx) // TODO: what to do here
if !ok {
// Set a gas meter with limit 0 as to prevent an infinite gas meter attack
// during runTx.
newCtx = SetGasMeter(ctx, 0)
return newCtx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
// Set a gas meter with limit 0 as to prevent an infinite gas meter attack during runTx.
// newCtx = SetGasMeter(ctx, 0)
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
}

newCtx = SetGasMeter(ctx, gasTx.GetGas())

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / dependency-review

cannot use ctx (variable of type context.Context) as "github.com/cosmos/cosmos-sdk/types".Context value in argument to SetGasMeter: need type assertion

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / dependency-review

undefined: newCtx

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (03)

undefined: newCtx

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (03)

cannot use ctx (variable of type context.Context) as "github.com/cosmos/cosmos-sdk/types".Context value in argument to SetGasMeter: need type assertion

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (00)

undefined: newCtx

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (00)

cannot use ctx (variable of type context.Context) as "github.com/cosmos/cosmos-sdk/types".Context value in argument to SetGasMeter: need type assertion

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (00)

undefined: newCtx

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (00)

cannot use ctx (variable of type context.Context) as "github.com/cosmos/cosmos-sdk/types".Context value in argument to SetGasMeter: need type assertion

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (01)

undefined: newCtx

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (01)

cannot use ctx (variable of type context.Context) as "github.com/cosmos/cosmos-sdk/types".Context value in argument to SetGasMeter: need type assertion

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (01)

undefined: newCtx

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (01)

cannot use ctx (variable of type context.Context) as "github.com/cosmos/cosmos-sdk/types".Context value in argument to SetGasMeter: need type assertion

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (02)

undefined: newCtx

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (02)

cannot use ctx (variable of type context.Context) as "github.com/cosmos/cosmos-sdk/types".Context value in argument to SetGasMeter: need type assertion

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (02)

undefined: newCtx

Check failure on line 54 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (02)

cannot use ctx (variable of type context.Context) as "github.com/cosmos/cosmos-sdk/types".Context value in argument to SetGasMeter: need type assertion

if cp := ctx.ConsensusParams(); cp.Block != nil {

Check failure on line 56 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / dependency-review

ctx.ConsensusParams undefined (type context.Context has no field or method ConsensusParams)

Check failure on line 56 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (03)

ctx.ConsensusParams undefined (type context.Context has no field or method ConsensusParams)

Check failure on line 56 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (00)

ctx.ConsensusParams undefined (type context.Context has no field or method ConsensusParams)

Check failure on line 56 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (00)

ctx.ConsensusParams undefined (type context.Context has no field or method ConsensusParams)

Check failure on line 56 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (01)

ctx.ConsensusParams undefined (type context.Context has no field or method ConsensusParams)

Check failure on line 56 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (01)

ctx.ConsensusParams undefined (type context.Context has no field or method ConsensusParams)

Check failure on line 56 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (02)

ctx.ConsensusParams undefined (type context.Context has no field or method ConsensusParams)

Check failure on line 56 in x/auth/ante/setup.go

View workflow job for this annotation

GitHub Actions / tests (02)

ctx.ConsensusParams undefined (type context.Context has no field or method ConsensusParams)
// If there exists a maximum block gas limit, we must ensure that the tx
// does not exceed it.
if cp.Block.MaxGas > 0 && gasTx.GetGas() > uint64(cp.Block.MaxGas) {
return newCtx, errorsmod.Wrapf(sdkerrors.ErrInvalidGasLimit, "tx gas limit %d exceeds block max gas %d", gasTx.GetGas(), cp.Block.MaxGas)
return errorsmod.Wrapf(sdkerrors.ErrInvalidGasLimit, "tx gas limit %d exceeds block max gas %d", gasTx.GetGas(), cp.Block.MaxGas)
}
}

Expand All @@ -58,7 +72,7 @@
case storetypes.ErrorOutOfGas:
log := fmt.Sprintf(
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
rType.Descriptor, gasTx.GetGas(), newCtx.GasMeter().GasConsumed())
rType.Descriptor, gasTx.GetGas(), gasService.GetGasMeter(ctx).Consumed())

err = errorsmod.Wrap(sdkerrors.ErrOutOfGas, log)
default:
Expand All @@ -67,7 +81,7 @@
}
}()

return next(newCtx, tx, ctx.ExecMode() == sdk.ExecModeSimulate)
return err
}

// SetGasMeter returns a new context with a gas meter set from a given context.
Expand Down
6 changes: 3 additions & 3 deletions x/auth/ante/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestSetupDecorator_BlockMaxGas(t *testing.T) {
tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
require.NoError(t, err)

sud := ante.NewSetUpContextDecorator()
sud := ante.NewSetUpContextDecorator(suite.accountKeeper)
antehandler := sdk.ChainAnteDecorators(sud)

suite.ctx = suite.ctx.
Expand Down Expand Up @@ -69,7 +69,7 @@ func TestSetup(t *testing.T) {
tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
require.NoError(t, err)

sud := ante.NewSetUpContextDecorator()
sud := ante.NewSetUpContextDecorator(suite.accountKeeper)
antehandler := sdk.ChainAnteDecorators(sud)

// Set height to non-zero value for GasMeter to be set
Expand Down Expand Up @@ -104,7 +104,7 @@ func TestRecoverPanic(t *testing.T) {
tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
require.NoError(t, err)

sud := ante.NewSetUpContextDecorator()
sud := ante.NewSetUpContextDecorator(suite.accountKeeper)
antehandler := sdk.ChainAnteDecorators(sud, OutOfGasDecorator{})

// Set height to non-zero value for GasMeter to be set
Expand Down
20 changes: 14 additions & 6 deletions x/auth/ante/sigverify.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,27 +459,35 @@ func NewValidateSigCountDecorator(ak AccountKeeper) ValidateSigCountDecorator {
}
}

func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if err := vscd.ValidateTx(ctx, tx); err != nil {
return ctx, err
}

return next(ctx, tx, false)
}

func (vscd ValidateSigCountDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
sigTx, ok := tx.(authsigning.SigVerifiableTx) // TODO: what do we do with this.
if !ok {
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
}

params := vscd.ak.GetParams(ctx)
pubKeys, err := sigTx.GetPubKeys()
if err != nil {
return ctx, err
return err
}

sigCount := 0
for _, pk := range pubKeys {
sigCount += CountSubKeys(pk)
if uint64(sigCount) > params.TxSigLimit {
return ctx, errorsmod.Wrapf(sdkerrors.ErrTooManySignatures, "signatures: %d, limit: %d", sigCount, params.TxSigLimit)
return errorsmod.Wrapf(sdkerrors.ErrTooManySignatures, "signatures: %d, limit: %d", sigCount, params.TxSigLimit)
}
}

return next(ctx, tx, ctx.ExecMode() == sdk.ExecModeSimulate)
return nil
}

// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
Expand Down
Loading
Loading