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

feat(ante): allow doing vesting txs based on whitelist #216

Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
82934f7
deletes old ante and adds new ante package
danwt Apr 29, 2024
b411dcd
ads the call to must create ante handler, but with some grey args
danwt Apr 29, 2024
1a92ac4
adds in the wrong keepers (breaking)
danwt Apr 29, 2024
28f59fe
deletes the old set ante handler method
danwt Apr 29, 2024
a699bc8
uses evmos ante instead
danwt Apr 29, 2024
410fc9c
rename ethante -> evmosante (fix)
danwt Apr 29, 2024
e8a3eff
use the evmos sig checker
danwt Apr 29, 2024
f716a07
removed recover call
danwt Apr 29, 2024
4a7f142
fix two types to the correct evmante package
danwt Apr 29, 2024
781a85a
fix args to must*, now need to fix disabeldauthz
danwt Apr 29, 2024
40b8841
adds todos, need to fix disabled auth z messages
danwt Apr 29, 2024
5a43c5e
removes the disabled auth z messages arg as its unnecessary
danwt Apr 29, 2024
76fe6af
fix evm handler
danwt Apr 29, 2024
29c0fd1
finito with todo
danwt Apr 29, 2024
2a43326
tidy and confirms builds
danwt Apr 29, 2024
b05bbde
adds a todo for the blocked messages
danwt Apr 29, 2024
1830429
do not completely disable authz message
danwt Apr 29, 2024
6ddfe1d
typo
danwt Apr 29, 2024
88f264e
use the denom metadata is address permissioned
danwt Apr 29, 2024
9a6b69f
removes todos
danwt Apr 29, 2024
aaf1730
use sig gas consumer
danwt Apr 29, 2024
0909a8a
still one broken
danwt Apr 29, 2024
b33fec8
removes ethermint dependency
danwt Apr 29, 2024
69f738b
fix must sig
danwt Apr 29, 2024
e6dbe78
fix sig readability
danwt Apr 29, 2024
4554d2d
add another check for keepers
danwt Apr 29, 2024
1739b2d
chores(deps): bump be-rpc libs (#228)
0xbcdev May 3, 2024
bb1ac57
Merge branch 'release/v2.1.x' into danwt/193-use-native-ante-handler-…
danwt May 7, 2024
6c4e657
shorten line
danwt May 7, 2024
a4a924f
omit the eth vesting transaction decorator
danwt May 7, 2024
dd1774a
use _, ok := c.GetCachedValue().(*etherminttypes.ExtensionOptions…
danwt May 7, 2024
c615271
add a clarification
danwt May 7, 2024
4190847
revert change to use web3tx validation
danwt May 7, 2024
d312841
removes cosmosante.NewVestingDelegationDecorator
danwt May 9, 2024
b00a4f9
add tx extension option checker for legacy path
danwt May 9, 2024
0f27ba7
simplify and move extension checker
danwt May 9, 2024
9c090f6
reject all extensions for regular comsos tx
danwt May 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 0 additions & 67 deletions app/ante.go

This file was deleted.

167 changes: 167 additions & 0 deletions app/ante/ante.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package ante

import (
"fmt"
"runtime/debug"

"github.com/cosmos/cosmos-sdk/codec"

errorsmod "cosmossdk.io/errors"

"github.com/cosmos/cosmos-sdk/client"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
ibckeeper "github.com/cosmos/ibc-go/v6/modules/core/keeper"
evmosante "github.com/evmos/evmos/v12/app/ante"
evmosanteevm "github.com/evmos/evmos/v12/app/ante/evm"
anteutils "github.com/evmos/evmos/v12/app/ante/utils"
evmostypes "github.com/evmos/evmos/v12/types"
evmtypes "github.com/evmos/evmos/v12/x/evm/types"
evmosvestingtypes "github.com/evmos/evmos/v12/x/vesting/types"
tmlog "github.com/tendermint/tendermint/libs/log"
)

type HasPermission = func(ctx sdk.Context, accAddr sdk.AccAddress, perm string) bool

func MustCreateHandler(codec codec.BinaryCodec, txConfig client.TxConfig, maxGasWanted uint64, hasPermission HasPermission, accountKeeper evmtypes.AccountKeeper, stakingKeeper evmosvestingtypes.StakingKeeper, bankKeeper evmtypes.BankKeeper, feeMarketKeeper evmosanteevm.FeeMarketKeeper, evmKeeper evmosanteevm.EVMKeeper, ibcKeeper *ibckeeper.Keeper, distrKeeper anteutils.DistributionKeeper) sdk.AnteHandler {
ethOpts := evmosante.HandlerOptions{
Cdc: codec,
AccountKeeper: accountKeeper,
BankKeeper: bankKeeper,
ExtensionOptionChecker: evmostypes.HasDynamicFeeExtensionOption,
danwt marked this conversation as resolved.
Show resolved Hide resolved
EvmKeeper: evmKeeper,
StakingKeeper: stakingKeeper,
FeegrantKeeper: nil,
DistributionKeeper: distrKeeper,
IBCKeeper: ibcKeeper,
FeeMarketKeeper: feeMarketKeeper,
SignModeHandler: txConfig.SignModeHandler(),
SigGasConsumer: evmosante.SigVerificationGasConsumer,
MaxTxGasWanted: maxGasWanted,
TxFeeChecker: evmosanteevm.NewDynamicFeeChecker(evmKeeper),
}

opts := HandlerOptions{
HandlerOptions: ethOpts,
hasPermission: hasPermission,
}

h, err := NewHandler(opts)
if err != nil {
panic(fmt.Errorf("new ante handler: %w", err))
}
return h
}

// HandlerOptions are the options required for constructing a default SDK AnteHandler.
type HandlerOptions struct {
evmosante.HandlerOptions
hasPermission HasPermission
}

func (o HandlerOptions) validate() error {
/*
First check the eth stuff - the validate method is not exported so this is copy-pasted
*/
if o.AccountKeeper == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "account keeper missing")
}
if o.BankKeeper == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "bank keeper missing")
}
if o.SignModeHandler == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "sign mode handler missing")
}
if o.FeeMarketKeeper == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "fee market keeper missing")
}
if o.EvmKeeper == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "evm keeper missing")
}
if o.DistributionKeeper == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "distribution keeper missing")
}
if o.StakingKeeper == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "staking keeper missing")
}

/*
Our stuff
*/
if o.hasPermission == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "permission checker missing")
}
if o.IBCKeeper == nil {
return errorsmod.Wrap(sdkerrors.ErrLogic, "IBC keeper missing")
}
return nil
}

func NewHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if err := options.validate(); err != nil {
return nil, fmt.Errorf("options validate: %w", err)
}

return func(
ctx sdk.Context, tx sdk.Tx, sim bool,
) (newCtx sdk.Context, err error) {
var anteHandler sdk.AnteHandler

defer Recover(ctx.Logger(), &err)

txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
if ok {
opts := txWithExtensions.GetExtensionOptions()
if len(opts) > 0 {
switch typeURL := opts[0].GetTypeUrl(); typeURL {
case "/ethermint.evm.v1.ExtensionOptionsEthereumTx":
// handle as *evmtypes.MsgEthereumTx. It will get checked by the EVM handler to make sure it is.
anteHandler = newEVMAnteHandler(options)
case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
// Deprecated: Handle as normal Cosmos SDK tx, except signature is checked for Legacy EIP712 representation
anteHandler = newLegacyCosmosAnteHandlerEip712(options)
case "/ethermint.types.v1.ExtensionOptionDynamicFeeTx": // TODO: can delete?
// cosmos-sdk tx with dynamic fee extension
anteHandler = newCosmosAnteHandler(options)
default:
return ctx, errorsmod.Wrapf(
sdkerrors.ErrUnknownExtensionOptions,
"rejecting tx with unsupported extension option: %s", typeURL,
)
}

return anteHandler(ctx, tx, sim)
}
}

// handle as totally normal Cosmos SDK tx
switch tx.(type) {
case sdk.Tx:
anteHandler = newCosmosAnteHandler(options)
default:
return ctx, errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
}

return anteHandler(ctx, tx, sim)
}, nil
}

func Recover(logger tmlog.Logger, err *error) {
if r := recover(); r != nil {
*err = errorsmod.Wrapf(sdkerrors.ErrPanic, "%v", r)

if e, ok := r.(error); ok {
logger.Error(
"ante handler panicked",
"error", e,
"stack trace", string(debug.Stack()),
)
} else {
logger.Error(
"ante handler panicked",
"recover", fmt.Sprintf("%v", r),
)
}
}
}
39 changes: 39 additions & 0 deletions app/ante/decorator_permissioned_urls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ante

import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"golang.org/x/exp/slices"
)

// PermissionedURLsDecorator prevents invalid msg types from being executed
type PermissionedURLsDecorator struct {
hasPermission func(ctx sdk.Context, accAddr sdk.AccAddress) bool
permissionedURls []string
}

func NewPermissionedURLsDecorator(hasPermission func(ctx sdk.Context, accAddr sdk.AccAddress) bool, msgTypeURLs []string) PermissionedURLsDecorator {
return PermissionedURLsDecorator{
hasPermission: hasPermission,
permissionedURls: msgTypeURLs,
}
}

// AnteHandle rejects vesting messages that signer does not have permission
func (d PermissionedURLsDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
for _, msg := range tx.GetMsgs() {
if slices.Contains(d.permissionedURls, sdk.MsgTypeURL(msg)) {
// Check if vesting tx signer is 1
if len(msg.GetSigners()) != 1 {
return ctx, errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "expect 1 signer: signers: %v", msg.GetSigners())
}

signer := msg.GetSigners()[0]
if !d.hasPermission(ctx, signer) {
return ctx, sdkerrors.ErrUnauthorized
}
}
}
return next(ctx, tx, simulate)
}
103 changes: 103 additions & 0 deletions app/ante/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package ante

import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
sdkvestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
ibcante "github.com/cosmos/ibc-go/v6/modules/core/ante"
cosmosante "github.com/evmos/evmos/v12/app/ante/cosmos"
evmante "github.com/evmos/evmos/v12/app/ante/evm"
evmtypes "github.com/evmos/evmos/v12/x/evm/types"
)

// NOTE: this function is copied from evmos
func newEVMAnteHandler(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
// outermost AnteDecorator. SetUpContext must be called first
evmante.NewEthSetUpContextDecorator(options.EvmKeeper),
// Check eth effective gas price against the node's minimal-gas-prices config
evmante.NewEthMempoolFeeDecorator(options.EvmKeeper),
// Check eth effective gas price against the global MinGasPrice
evmante.NewEthMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
evmante.NewEthValidateBasicDecorator(options.EvmKeeper),
evmante.NewEthSigVerificationDecorator(options.EvmKeeper),
evmante.NewEthAccountVerificationDecorator(options.AccountKeeper, options.EvmKeeper),
evmante.NewCanTransferDecorator(options.EvmKeeper),
evmante.NewEthVestingTransactionDecorator(options.AccountKeeper, options.BankKeeper, options.EvmKeeper),
danwt marked this conversation as resolved.
Show resolved Hide resolved
evmante.NewEthGasConsumeDecorator(options.BankKeeper, options.DistributionKeeper, options.EvmKeeper, options.StakingKeeper, options.MaxTxGasWanted),
evmante.NewEthIncrementSenderSequenceDecorator(options.AccountKeeper),
evmante.NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
// emit eth tx hash and index at the very last ante handler.
evmante.NewEthEmitEventDecorator(options.EvmKeeper),
)
}

func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
cosmosDecorators(
options,
options.ExtensionOptionChecker, // make sure there are no extension options
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), // Use modern signature verification
)...,
)
}

// Deprecated: NewLegacyCosmosAnteHandlerEip712 creates an AnteHandler to process legacy EIP-712
// transactions, as defined by the presence of an ExtensionOptionsWeb3Tx extension.
func newLegacyCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
cosmosDecorators(
options,
func(c *codectypes.Any) bool { return true }, // allows any extension, this is consistent with the evmos behavior
danwt marked this conversation as resolved.
Show resolved Hide resolved
cosmosante.NewLegacyEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), // Use old signature verification: uses EIP instead of the cosmos signature validator
)...,
)
}

func cosmosDecorators(options HandlerOptions, extensionChecker authante.ExtensionOptionChecker, sigChecker sdk.AnteDecorator) []sdk.AnteDecorator {
sigGasConsumer := options.SigGasConsumer
if sigGasConsumer == nil {
sigGasConsumer = authante.DefaultSigVerificationGasConsumer
Fixed Show fixed Hide fixed
}
return []sdk.AnteDecorator{
cosmosante.NewRejectMessagesDecorator(
[]string{
sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}),
},
),
cosmosante.NewAuthzLimiterDecorator( // disable the Msg types that cannot be included on an authz.MsgExec msgs field
sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}),
sdk.MsgTypeURL(&sdkvestingtypes.MsgCreateVestingAccount{}),
sdk.MsgTypeURL(&sdkvestingtypes.MsgCreatePermanentLockedAccount{}),
sdk.MsgTypeURL(&sdkvestingtypes.MsgCreatePeriodicVestingAccount{}),
),
ante.NewSetUpContextDecorator(),
ante.NewExtensionOptionsDecorator(extensionChecker),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
NewPermissionedURLsDecorator(
func(ctx sdk.Context, accAddr sdk.AccAddress) bool {
return options.hasPermission(ctx, accAddr, vestingtypes.ModuleName)
}, []string{
sdk.MsgTypeURL(&vestingtypes.MsgCreateVestingAccount{}),
sdk.MsgTypeURL(&vestingtypes.MsgCreatePermanentLockedAccount{}),
sdk.MsgTypeURL(&vestingtypes.MsgCreatePeriodicVestingAccount{}),
}),
ante.NewValidateMemoDecorator(options.AccountKeeper),
cosmosante.NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
cosmosante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.DistributionKeeper, options.FeegrantKeeper, options.StakingKeeper, options.TxFeeChecker),
cosmosante.NewVestingDelegationDecorator(options.AccountKeeper, options.StakingKeeper, options.Cdc),
danwt marked this conversation as resolved.
Show resolved Hide resolved
// SetPubKeyDecorator must be called before all signature verification decorators
ante.NewSetPubKeyDecorator(options.AccountKeeper),
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer),
sigChecker,
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
evmante.NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
}
}
Loading
Loading