From 344b3b31019c7a7aea99e52d6c4ab4617b05a7c6 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Fri, 7 Apr 2023 11:06:45 +0800 Subject: [PATCH] feat: cosmos tx support ethsecp256k1 --- ante/handler_options.go | 7 +--- ante/reject_msgs.go | 26 ++++++++++++ ante/sigverify.go | 88 +++++++++++++++++++++++++++++++++++++++++ app/app.go | 1 - 4 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 ante/reject_msgs.go create mode 100644 ante/sigverify.go diff --git a/ante/handler_options.go b/ante/handler_options.go index 2a824905c..6008d4de1 100644 --- a/ante/handler_options.go +++ b/ante/handler_options.go @@ -52,11 +52,8 @@ func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler { // newCosmosAnteHandler creates the default ante handler for Cosmos transactions func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler { - var sigGasConsumer = options.SigGasConsumer - if sigGasConsumer == nil { - sigGasConsumer = ante.DefaultSigVerificationGasConsumer - } return sdk.ChainAnteDecorators( + RejectMessagesDecorator{}, ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker), ante.NewValidateBasicDecorator(), @@ -66,7 +63,7 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler { ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker), ante.NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators ante.NewValidateSigCountDecorator(options.AccountKeeper), - ante.NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer), + ante.NewSigGasConsumeDecorator(options.AccountKeeper, DefaultSigVerificationGasConsumer), ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), NewValidateTokenDecorator(options.TokenKeeper), tokenkeeper.NewValidateTokenFeeDecorator(options.TokenKeeper, options.BankKeeper), diff --git a/ante/reject_msgs.go b/ante/reject_msgs.go new file mode 100644 index 000000000..f2728895c --- /dev/null +++ b/ante/reject_msgs.go @@ -0,0 +1,26 @@ +package ante + +import ( + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + errortypes "github.com/cosmos/cosmos-sdk/types/errors" + evmtypes "github.com/evmos/ethermint/x/evm/types" +) + +// RejectMessagesDecorator prevents invalid msg types from being executed +type RejectMessagesDecorator struct{} + +// AnteHandle rejects messages that requires ethereum-specific authentication. +// For example `MsgEthereumTx` requires fee to be deducted in the antehandler in +// order to perform the refund. +func (rmd RejectMessagesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + for _, msg := range tx.GetMsgs() { + if _, ok := msg.(*evmtypes.MsgEthereumTx); ok { + return ctx, errorsmod.Wrapf( + errortypes.ErrInvalidType, + "MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option", + ) + } + } + return next(ctx, tx, simulate) +} diff --git a/ante/sigverify.go b/ante/sigverify.go new file mode 100644 index 000000000..d9b66b166 --- /dev/null +++ b/ante/sigverify.go @@ -0,0 +1,88 @@ +package ante + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1" + "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/evmos/ethermint/crypto/ethsecp256k1" +) + +const ( + Secp256k1VerifyCost uint64 = 21000 +) + +// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas +// for signature verification based upon the public key type. The cost is fetched from the given params and is matched +// by the concrete type. +func DefaultSigVerificationGasConsumer( + meter sdk.GasMeter, sig signing.SignatureV2, params types.Params, +) error { + pubkey := sig.PubKey + switch pubkey := pubkey.(type) { + case *ed25519.PubKey: + meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519") + return sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "ED25519 public keys are unsupported") + + case *secp256k1.PubKey: + meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1") + return nil + + case *ethsecp256k1.PubKey: + // Ethereum keys + meter.ConsumeGas(Secp256k1VerifyCost, "ante verify: eth_secp256k1") + return nil + + case *secp256r1.PubKey: + meter.ConsumeGas(params.SigVerifyCostSecp256r1(), "ante verify: secp256r1") + return nil + + case multisig.PubKey: + multisignature, ok := sig.Data.(*signing.MultiSignatureData) + if !ok { + return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data) + } + err := ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence) + if err != nil { + return err + } + return nil + + default: + return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey) + } +} + +// ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature +func ConsumeMultisignatureVerificationGas( + meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey, + params types.Params, accSeq uint64, +) error { + size := sig.BitArray.Count() + sigIndex := 0 + + for i := 0; i < size; i++ { + if !sig.BitArray.GetIndex(i) { + continue + } + sigV2 := signing.SignatureV2{ + PubKey: pubkey.GetPubKeys()[i], + Data: sig.Signatures[sigIndex], + Sequence: accSeq, + } + err := DefaultSigVerificationGasConsumer(meter, sigV2, params) + if err != nil { + return err + } + sigIndex++ + } + + return nil +} diff --git a/app/app.go b/app/app.go index 3f4d09b2f..02997304f 100644 --- a/app/app.go +++ b/app/app.go @@ -611,7 +611,6 @@ func NewIrisApp( BankKeeper: app.BankKeeper, FeegrantKeeper: app.FeeGrantKeeper, SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), - SigGasConsumer: ante.DefaultSigVerificationGasConsumer, }, AccountKeeper: app.AccountKeeper, BankKeeper: app.BankKeeper,