move feegrant ante to auth ante (#8682)

* move feegrant ante to auth ante

* update ante builder

* remove commented code

* review changes

* fix lint

* review changes

* review changes

* review changes

* review changes

* fix ante builder

* review changes

* update ante builder with options struct

* review changes

* review changes

* add changelog

Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com>
Co-authored-by: Aaron Craelius <aaron@regen.network>
This commit is contained in:
atheeshp 2021-03-23 13:01:09 +05:30 committed by GitHub
parent e30959ce4a
commit 025d226099
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 161 additions and 294 deletions

View File

@ -64,6 +64,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) `SupplyI` interface and `Supply` are removed and uses `sdk.Coins` for supply tracking
* (x/upgrade) [\#8743](https://github.com/cosmos/cosmos-sdk/pull/8743) `UpgradeHandler` includes a new argument `VersionMap` which helps facilitate in-place migrations.
* (x/auth) [\#8129](https://github.com/cosmos/cosmos-sdk/pull/8828) Updated `SigVerifiableTx.GetPubKeys` method signature to return error.
* [\#8682](https://github.com/cosmos/cosmos-sdk/pull/8682) `ante.NewAnteHandler` updated to receive all positional params as `ante.HandlerOptions` struct. If required fields aren't set, throws error accordingly.
### State Machine Breaking

View File

@ -56,7 +56,6 @@ import (
evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper"
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
feegrant "github.com/cosmos/cosmos-sdk/x/feegrant"
feegrantante "github.com/cosmos/cosmos-sdk/x/feegrant/ante"
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
feegranttypes "github.com/cosmos/cosmos-sdk/x/feegrant/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
@ -375,12 +374,22 @@ func NewSimApp(
// initialize BaseApp
app.SetInitChainer(app.InitChainer)
app.SetBeginBlocker(app.BeginBlocker)
app.SetAnteHandler(
feegrantante.NewAnteHandler(
app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, ante.DefaultSigVerificationGasConsumer,
encodingConfig.TxConfig.SignModeHandler(),
),
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
app.SetAnteHandler(anteHandler)
app.SetEndBlocker(app.EndBlocker)
if loadLatest {

View File

@ -2,32 +2,57 @@ package ante
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
// HandlerOptions are the options required for constructing a default SDK AnteHandler.
type HandlerOptions struct {
AccountKeeper AccountKeeper
BankKeeper types.BankKeeper
FeegrantKeeper FeegrantKeeper
SignModeHandler authsigning.SignModeHandler
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error
}
// NewAnteHandler returns an AnteHandler that checks and increments sequence
// numbers, checks signatures & account numbers, and deducts fees from the first
// signer.
func NewAnteHandler(
ak AccountKeeper, bankKeeper types.BankKeeper,
sigGasConsumer SignatureVerificationGasConsumer,
signModeHandler signing.SignModeHandler,
) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if options.AccountKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for ante builder")
}
if options.BankKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for ante builder")
}
if options.SignModeHandler == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
}
var sigGasConsumer = options.SigGasConsumer
if sigGasConsumer == nil {
sigGasConsumer = DefaultSigVerificationGasConsumer
}
anteDecorators := []sdk.AnteDecorator{
NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
NewRejectExtensionOptionsDecorator(),
NewMempoolFeeDecorator(),
NewValidateBasicDecorator(),
TxTimeoutHeightDecorator{},
NewValidateMemoDecorator(ak),
NewConsumeGasForTxSizeDecorator(ak),
NewRejectFeeGranterDecorator(),
NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
NewValidateSigCountDecorator(ak),
NewDeductFeeDecorator(ak, bankKeeper),
NewSigGasConsumeDecorator(ak, sigGasConsumer),
NewSigVerificationDecorator(ak, signModeHandler),
NewIncrementSequenceDecorator(ak),
)
NewValidateMemoDecorator(options.AccountKeeper),
NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
NewValidateSigCountDecorator(options.AccountKeeper),
NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer),
NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
NewIncrementSequenceDecorator(options.AccountKeeper),
}
return sdk.ChainAnteDecorators(anteDecorators...), nil
}

View File

@ -1010,15 +1010,26 @@ func (suite *AnteTestSuite) TestCustomSignatureVerificationGasConsumer() {
suite.SetupTest(false) // setup
// setup an ante handler that only accepts PubKeyEd25519
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error {
switch pubkey := sig.PubKey.(type) {
case *ed25519.PubKey:
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
return nil
default:
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey)
}
}, suite.clientCtx.TxConfig.SignModeHandler())
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: suite.app.AccountKeeper,
BankKeeper: suite.app.BankKeeper,
FeegrantKeeper: suite.app.FeeGrantKeeper,
SignModeHandler: suite.clientCtx.TxConfig.SignModeHandler(),
SigGasConsumer: func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error {
switch pubkey := sig.PubKey.(type) {
case *ed25519.PubKey:
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
return nil
default:
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey)
}
},
},
)
suite.Require().NoError(err)
suite.anteHandler = anteHandler
// Same data for every test cases
accounts := suite.CreateTestAccounts(1)

View File

@ -13,3 +13,8 @@ type AccountKeeper interface {
SetAccount(ctx sdk.Context, acc types.AccountI)
GetModuleAddress(moduleName string) sdk.AccAddress
}
// FeegrantKeeper defines the expected feegrant keeper.
type FeegrantKeeper interface {
UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins) error
}

View File

@ -59,14 +59,16 @@ func (mfd MempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b
// Call next AnteHandler if fees successfully deducted
// CONTRACT: Tx must implement FeeTx interface to use DeductFeeDecorator
type DeductFeeDecorator struct {
ak AccountKeeper
bankKeeper types.BankKeeper
ak AccountKeeper
bankKeeper types.BankKeeper
feegrantKeeper FeegrantKeeper
}
func NewDeductFeeDecorator(ak AccountKeeper, bk types.BankKeeper) DeductFeeDecorator {
func NewDeductFeeDecorator(ak AccountKeeper, bk types.BankKeeper, fk FeegrantKeeper) DeductFeeDecorator {
return DeductFeeDecorator{
ak: ak,
bankKeeper: bk,
ak: ak,
bankKeeper: bk,
feegrantKeeper: fk,
}
}
@ -80,16 +82,36 @@ func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
panic(fmt.Sprintf("%s module account has not been set", types.FeeCollectorName))
}
fee := feeTx.GetFee()
feePayer := feeTx.FeePayer()
feePayerAcc := dfd.ak.GetAccount(ctx, feePayer)
feeGranter := feeTx.FeeGranter()
if feePayerAcc == nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", feePayer)
deductFeesFrom := feePayer
// if feegranter set deduct fee from feegranter account.
// this works with only when feegrant enabled.
if feeGranter != nil {
if dfd.feegrantKeeper == nil {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants are not enabled")
} else if !feeGranter.Equals(feePayer) {
err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee)
if err != nil {
return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer)
}
}
deductFeesFrom = feeGranter
}
deductFeesFromAcc := dfd.ak.GetAccount(ctx, deductFeesFrom)
if deductFeesFromAcc == nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", deductFeesFrom)
}
// deduct the fees
if !feeTx.GetFee().IsZero() {
err = DeductFees(dfd.bankKeeper, ctx, feePayerAcc, feeTx.GetFee())
err = DeductFees(dfd.bankKeeper, ctx, deductFeesFromAcc, feeTx.GetFee())
if err != nil {
return ctx, err
}

View File

@ -1,27 +0,0 @@
package ante
import (
"github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// RejectFeeGranterDecorator is an AnteDecorator which rejects transactions which
// have the Fee.granter field set. It is to be used by chains which do not support
// fee grants.
type RejectFeeGranterDecorator struct{}
// NewRejectFeeGranterDecorator returns a new RejectFeeGranterDecorator.
func NewRejectFeeGranterDecorator() RejectFeeGranterDecorator {
return RejectFeeGranterDecorator{}
}
var _ types.AnteDecorator = RejectFeeGranterDecorator{}
func (d RejectFeeGranterDecorator) AnteHandle(ctx types.Context, tx types.Tx, simulate bool, next types.AnteHandler) (newCtx types.Context, err error) {
feeTx, ok := tx.(types.FeeTx)
if ok && len(feeTx.FeeGranter()) != 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants are not supported")
}
return next(ctx, tx, simulate)
}

View File

@ -1,32 +0,0 @@
package ante_test
import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
)
type setFeeGranter interface {
SetFeeGranter(feeGranter sdk.AccAddress)
}
func (suite *AnteTestSuite) TestRejectFeeGranter() {
suite.SetupTest(true) // setup
txConfig := tx.NewTxConfig(codec.NewProtoCodec(types.NewInterfaceRegistry()), tx.DefaultSignModes)
txBuilder := txConfig.NewTxBuilder()
d := ante.NewRejectFeeGranterDecorator()
antehandler := sdk.ChainAnteDecorators(d)
_, err := antehandler(suite.ctx, txBuilder.GetTx(), false)
suite.Require().NoError(err)
setGranterTx := txBuilder.(setFeeGranter)
_, _, addr := testdata.KeyTestPubAddr()
setGranterTx.SetFeeGranter(addr)
_, err = antehandler(suite.ctx, txBuilder.GetTx(), false)
suite.Require().Error(err)
}

View File

@ -86,7 +86,7 @@ func (suite *AnteTestSuite) TestDeductFees() {
err = simapp.FundAccount(suite.app, suite.ctx, addr1, coins)
suite.Require().NoError(err)
dfd := ante.NewDeductFeeDecorator(suite.app.AccountKeeper, suite.app.BankKeeper)
dfd := ante.NewDeductFeeDecorator(suite.app.AccountKeeper, suite.app.BankKeeper, nil)
antehandler := sdk.ChainAnteDecorators(dfd)
_, err = antehandler(suite.ctx, tx, false)

View File

@ -5,9 +5,7 @@ import (
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/tendermint/tendermint/crypto"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
@ -19,42 +17,13 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authsign "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/feegrant/ante"
"github.com/cosmos/cosmos-sdk/x/feegrant/types"
)
// AnteTestSuite is a test suite to be used with ante handler tests.
type AnteTestSuite struct {
suite.Suite
app *simapp.SimApp
anteHandler sdk.AnteHandler
ctx sdk.Context
clientCtx client.Context
txBuilder client.TxBuilder
}
// SetupTest setups a new test, with new app, context, and anteHandler.
func (suite *AnteTestSuite) SetupTest(isCheckTx bool) {
suite.app, suite.ctx = createTestApp(isCheckTx)
suite.ctx = suite.ctx.WithBlockHeight(1)
// Set up TxConfig.
encodingConfig := simapp.MakeTestEncodingConfig()
// We're using TestMsg encoding in some tests, so register it here.
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
testdata.RegisterInterfaces(encodingConfig.InterfaceRegistry)
suite.clientCtx = client.Context{}.
WithTxConfig(encodingConfig.TxConfig)
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.FeeGrantKeeper, authante.DefaultSigVerificationGasConsumer, encodingConfig.TxConfig.SignModeHandler())
}
func (suite *AnteTestSuite) TestDeductFeesNoDelegation() {
suite.SetupTest(false)
// setup
@ -63,8 +32,8 @@ func (suite *AnteTestSuite) TestDeductFeesNoDelegation() {
protoTxCfg := tx.NewTxConfig(codec.NewProtoCodec(app.InterfaceRegistry()), tx.DefaultSignModes)
// this just tests our handler
dfd := ante.NewDeductGrantedFeeDecorator(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper)
ourAnteHandler := sdk.ChainAnteDecorators(dfd)
dfd := ante.NewDeductFeeDecorator(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper)
feeAnteHandler := sdk.ChainAnteDecorators(dfd)
// this tests the whole stack
anteHandlerStack := suite.anteHandler
@ -97,79 +66,68 @@ func (suite *AnteTestSuite) TestDeductFeesNoDelegation() {
suite.Require().NoError(err)
cases := map[string]struct {
signerKey cryptotypes.PrivKey
signer sdk.AccAddress
feeAccount sdk.AccAddress
feeAccountKey cryptotypes.PrivKey
handler sdk.AnteHandler
fee int64
valid bool
signerKey cryptotypes.PrivKey
signer sdk.AccAddress
feeAccount sdk.AccAddress
fee int64
valid bool
}{
"paying with low funds (only ours)": {
"paying with low funds": {
signerKey: priv1,
signer: addr1,
fee: 50,
handler: ourAnteHandler,
valid: false,
},
"paying with good funds (only ours)": {
"paying with good funds": {
signerKey: priv2,
signer: addr2,
fee: 50,
handler: ourAnteHandler,
valid: true,
},
"paying with no account (only ours)": {
"paying with no account": {
signerKey: priv3,
signer: addr3,
fee: 1,
handler: ourAnteHandler,
valid: false,
},
"no fee with real account (only ours)": {
"no fee with real account": {
signerKey: priv1,
signer: addr1,
fee: 0,
handler: ourAnteHandler,
valid: true,
},
"no fee with no account (only ours)": {
"no fee with no account": {
signerKey: priv5,
signer: addr5,
fee: 0,
handler: ourAnteHandler,
valid: false,
},
"valid fee grant without account (only ours)": {
"valid fee grant without account": {
signerKey: priv3,
signer: addr3,
feeAccount: addr2,
fee: 50,
handler: ourAnteHandler,
valid: true,
},
"no fee grant (only ours)": {
"no fee grant": {
signerKey: priv3,
signer: addr3,
feeAccount: addr1,
fee: 2,
handler: ourAnteHandler,
valid: false,
},
"allowance smaller than requested fee (only ours)": {
"allowance smaller than requested fee": {
signerKey: priv4,
signer: addr4,
feeAccount: addr2,
fee: 50,
handler: ourAnteHandler,
valid: false,
},
"granter cannot cover allowed fee grant (only ours)": {
"granter cannot cover allowed fee grant": {
signerKey: priv4,
signer: addr4,
feeAccount: addr1,
fee: 50,
handler: ourAnteHandler,
valid: false,
},
}
@ -188,14 +146,14 @@ func (suite *AnteTestSuite) TestDeductFeesNoDelegation() {
tx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...)
suite.Require().NoError(err)
_, err = ourAnteHandler(ctx, tx, false)
_, err = feeAnteHandler(ctx, tx, false) // tests only feegrant ante
if tc.valid {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
_, err = anteHandlerStack(ctx, tx, false)
_, err = anteHandlerStack(ctx, tx, false) // tests while stack
if tc.valid {
suite.Require().NoError(err)
} else {
@ -205,15 +163,6 @@ func (suite *AnteTestSuite) TestDeductFeesNoDelegation() {
}
}
// returns context and app with params set on account keeper
func createTestApp(isCheckTx bool) (*simapp.SimApp, sdk.Context) {
app := simapp.Setup(isCheckTx)
ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{})
app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams())
return app, ctx
}
// don't consume any gas
func SigGasNoConsumer(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params authtypes.Params) error {
return nil
@ -280,7 +229,3 @@ func genTxWithFeeGranter(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins,
return tx.GetTx(), nil
}
func TestAnteTestSuite(t *testing.T) {
suite.Run(t, new(AnteTestSuite))
}

View File

@ -203,7 +203,18 @@ func (suite *AnteTestSuite) TestSigVerification_ExplicitAmino() {
suite.clientCtx = client.Context{}.
WithTxConfig(txConfig)
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, ante.DefaultSigVerificationGasConsumer, txConfig.SignModeHandler())
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: suite.app.AccountKeeper,
BankKeeper: suite.app.BankKeeper,
FeegrantKeeper: suite.app.FeeGrantKeeper,
SignModeHandler: txConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
suite.Require().NoError(err)
suite.anteHandler = anteHandler
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()

View File

@ -63,7 +63,18 @@ func (suite *AnteTestSuite) SetupTest(isCheckTx bool) {
suite.clientCtx = client.Context{}.
WithTxConfig(encodingConfig.TxConfig)
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, ante.DefaultSigVerificationGasConsumer, encodingConfig.TxConfig.SignModeHandler())
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: suite.app.AccountKeeper,
BankKeeper: suite.app.BankKeeper,
FeegrantKeeper: suite.app.FeeGrantKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
suite.Require().NoError(err)
suite.anteHandler = anteHandler
}
// CreateTestAccounts creates `numAccs` accounts, and return all relevant

View File

@ -1,35 +0,0 @@
package ante
import (
sdk "github.com/cosmos/cosmos-sdk/types"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
feegranttypes "github.com/cosmos/cosmos-sdk/x/feegrant/types"
)
// NewAnteHandler returns an AnteHandler that checks and increments sequence
// numbers, checks signatures & account numbers, and deducts fees from the
// fee_payer or from fee_granter (if valid grant exist).
func NewAnteHandler(
ak authkeeper.AccountKeeper, bankKeeper feegranttypes.BankKeeper, feeGrantKeeper feegrantkeeper.Keeper,
sigGasConsumer authante.SignatureVerificationGasConsumer, signModeHandler signing.SignModeHandler,
) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
authante.NewRejectExtensionOptionsDecorator(),
authante.NewMempoolFeeDecorator(),
authante.NewValidateBasicDecorator(),
authante.TxTimeoutHeightDecorator{},
authante.NewValidateMemoDecorator(ak),
authante.NewConsumeGasForTxSizeDecorator(ak),
NewDeductGrantedFeeDecorator(ak, bankKeeper, feeGrantKeeper),
authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
authante.NewValidateSigCountDecorator(ak),
authante.NewSigGasConsumeDecorator(ak, sigGasConsumer),
authante.NewSigVerificationDecorator(ak, signModeHandler),
authante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator
)
}

View File

@ -1,82 +0,0 @@
package ante
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
"github.com/cosmos/cosmos-sdk/x/feegrant/types"
)
// DeductGrantedFeeDecorator deducts fees from fee_payer or fee_granter (if exists a valid fee allowance) of the tx
// If the fee_payer or fee_granter does not have the funds to pay for the fees, return with InsufficientFunds error
// Call next AnteHandler if fees successfully deducted
// CONTRACT: Tx must implement GrantedFeeTx interface to use DeductGrantedFeeDecorator
type DeductGrantedFeeDecorator struct {
ak types.AccountKeeper
k keeper.Keeper
bk types.BankKeeper
}
func NewDeductGrantedFeeDecorator(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) DeductGrantedFeeDecorator {
return DeductGrantedFeeDecorator{
ak: ak,
k: k,
bk: bk,
}
}
// AnteHandle performs a decorated ante-handler responsible for deducting transaction
// fees. Fees will be deducted from the account designated by the FeePayer on a
// transaction by default. However, if the fee payer differs from the transaction
// signer, the handler will check if a fee grant has been authorized. If the
// transaction's signer does not exist, it will be created.
func (d DeductGrantedFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a GrantedFeeTx")
}
// sanity check from DeductFeeDecorator
if addr := d.ak.GetModuleAddress(authtypes.FeeCollectorName); addr == nil {
panic(fmt.Sprintf("%s module account has not been set", authtypes.FeeCollectorName))
}
fee := feeTx.GetFee()
feePayer := feeTx.FeePayer()
feeGranter := feeTx.FeeGranter()
deductFeesFrom := feePayer
// ensure the grant is allowed, if we request a different fee payer
if feeGranter != nil && !feeGranter.Equals(feePayer) {
err := d.k.UseGrantedFees(ctx, feeGranter, feePayer, fee)
if err != nil {
return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer)
}
deductFeesFrom = feeGranter
}
// now, either way, we know that we are authorized to deduct the fees from the deductFeesFrom account
deductFeesFromAcc := d.ak.GetAccount(ctx, deductFeesFrom)
if deductFeesFromAcc == nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", deductFeesFrom)
}
// move on if there is no fee to deduct
if fee.IsZero() {
return next(ctx, tx, simulate)
}
// deduct fee if non-zero
err = authante.DeductFees(d.bk, ctx, deductFeesFromAcc, fee)
if err != nil {
return ctx, err
}
return next(ctx, tx, simulate)
}

View File

@ -8,6 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/feegrant/types"
)
@ -19,6 +20,8 @@ type Keeper struct {
authKeeper types.AccountKeeper
}
var _ ante.FeegrantKeeper = &Keeper{}
// NewKeeper creates a fee grant Keeper
func NewKeeper(cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, ak types.AccountKeeper) Keeper {
return Keeper{