Skip to content

Commit 2934281

Browse files
mmsqeAlex | Interchain Labsvladjdk
authored
fix: use PriorityMempool with signer extractor to prevent missing signers error in tx execution (#245)
* Problem: diff mempool max-txs trigger apphash mismatch add test * upstream repeated tx sender recovery is wastful #227 * sender address verification is not decoupled from execution #358 * fix main lint * Apply suggestions from code review * Problem: EVMChainID is not aligned in tests * lint * fix test * align cfg * eth signer not accurate in state machine #470 * keep deprecated * Update config.go --------- Co-authored-by: Alex | Interchain Labs <alex@interchainlabs.io> Co-authored-by: Vlad J <vladjdk@gmail.com>
1 parent 099f44e commit 2934281

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+808
-484
lines changed

ante/evm/04_validate.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ func ValidateMsg(
2424
txData evmtypes.TxData,
2525
from sdktypes.AccAddress,
2626
) error {
27-
if from != nil {
28-
return errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid from address; expected nil; got: %q", from.String())
27+
if txData == nil {
28+
return errorsmod.Wrap(errortypes.ErrInvalidRequest, "transaction is nil")
2929
}
30-
3130
return checkDisabledCreateCall(
3231
txData,
3332
&evmParams.AccessControl,

ante/evm/05_signature_verification.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,8 @@ func SignatureVerification(
8383
}
8484
}
8585

86-
sender, err := signer.Sender(ethTx)
87-
if err != nil {
88-
return errorsmod.Wrapf(
89-
errortypes.ErrorInvalidSigner,
90-
"couldn't retrieve sender address from the ethereum transaction: %s",
91-
err.Error(),
92-
)
86+
if err := msg.VerifySender(signer); err != nil {
87+
return errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "signature verification failed: %s", err.Error())
9388
}
94-
95-
// set up the sender to the transaction field if not already
96-
msg.From = sender.Hex()
9789
return nil
9890
}

ante/evm/mono_decorator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func (md MonoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne
156156
}
157157

158158
// 7. can transfer
159-
coreMsg, err := ethMsg.AsMessage(decUtils.Signer, decUtils.BaseFee)
159+
coreMsg, err := ethMsg.AsMessage(decUtils.BaseFee)
160160
if err != nil {
161161
return ctx, errorsmod.Wrapf(
162162
err,

ante/evm/mono_decorator_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,9 @@ func signMsgEthereumTx(t *testing.T, privKey *ethsecp256k1.PrivKey, args *evmsdk
117117
t.Helper()
118118
msg := evmsdktypes.NewTx(args)
119119
fromAddr := common.BytesToAddress(privKey.PubKey().Address().Bytes())
120-
msg.From = fromAddr.Hex()
120+
msg.From = fromAddr.Bytes()
121121
ethSigner := ethtypes.LatestSignerForChainID(evmsdktypes.GetEthChainConfig().ChainID)
122122
require.NoError(t, msg.Sign(ethSigner, utiltx.NewSigner(privKey)))
123-
msg.From = ""
124123
return msg
125124
}
126125

api/cosmos/evm/vm/v1/tx.pulsar.go

Lines changed: 258 additions & 179 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

encoding/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func TestTxEncoding(t *testing.T) {
2626
Input: []byte{},
2727
}
2828
msg := evmtypes.NewTx(&ethTxParams)
29-
msg.From = addr.Hex()
29+
msg.From = addr.Bytes()
3030

3131
ethSigner := ethtypes.LatestSignerForChainID(big.NewInt(1))
3232
err := msg.Sign(ethSigner, signer)

evmd/cmd/evmd/cmd/root.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,12 @@ import (
3535
"github.com/cosmos/cosmos-sdk/client/pruning"
3636
"github.com/cosmos/cosmos-sdk/client/rpc"
3737
"github.com/cosmos/cosmos-sdk/client/snapshot"
38+
"github.com/cosmos/cosmos-sdk/server"
3839
sdkserver "github.com/cosmos/cosmos-sdk/server"
3940
servertypes "github.com/cosmos/cosmos-sdk/server/types"
4041
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
4142
sdk "github.com/cosmos/cosmos-sdk/types"
42-
sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool"
43+
"github.com/cosmos/cosmos-sdk/types/mempool"
4344
sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
4445
"github.com/cosmos/cosmos-sdk/types/tx/signing"
4546
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
@@ -316,10 +317,19 @@ func newApp(
316317

317318
// Set up the required mempool and ABCI proposal handlers for Cosmos EVM
318319
baseappOptions = append(baseappOptions, func(app *baseapp.BaseApp) {
319-
mempool := sdkmempool.NoOpMempool{}
320-
app.SetMempool(mempool)
321-
322-
handler := baseapp.NewDefaultProposalHandler(mempool, app)
320+
var mpool mempool.Mempool
321+
if maxTxs := cast.ToInt(appOpts.Get(server.FlagMempoolMaxTxs)); maxTxs >= 0 {
322+
// Setup Mempool and Proposal Handlers
323+
mpool = mempool.NewPriorityMempool(mempool.PriorityNonceMempoolConfig[int64]{
324+
TxPriority: mempool.NewDefaultTxPriority(),
325+
SignerExtractor: evmd.NewEthSignerExtractionAdapter(mempool.NewDefaultSignerExtractionAdapter()),
326+
MaxTx: maxTxs,
327+
})
328+
} else {
329+
mpool = mempool.NoOpMempool{}
330+
}
331+
app.SetMempool(mpool)
332+
handler := baseapp.NewDefaultProposalHandler(mpool, app)
323333
app.SetPrepareProposal(handler.PrepareProposalHandler())
324334
app.SetProcessProposal(handler.ProcessProposalHandler())
325335
})

evmd/signer.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package evmd
2+
3+
import (
4+
sdk "github.com/cosmos/cosmos-sdk/types"
5+
mempool "github.com/cosmos/cosmos-sdk/types/mempool"
6+
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
7+
evmtypes "github.com/cosmos/evm/x/vm/types"
8+
)
9+
10+
var _ mempool.SignerExtractionAdapter = EthSignerExtractionAdapter{}
11+
12+
// EthSignerExtractionAdapter is the default implementation of SignerExtractionAdapter. It extracts the signers
13+
// from a cosmos-sdk tx via GetSignaturesV2.
14+
type EthSignerExtractionAdapter struct {
15+
fallback mempool.SignerExtractionAdapter
16+
}
17+
18+
// NewEthSignerExtractionAdapter constructs a new EthSignerExtractionAdapter instance
19+
func NewEthSignerExtractionAdapter(fallback mempool.SignerExtractionAdapter) EthSignerExtractionAdapter {
20+
return EthSignerExtractionAdapter{fallback}
21+
}
22+
23+
// GetSigners implements the Adapter interface
24+
// NOTE: only the first item is used by the mempool
25+
func (s EthSignerExtractionAdapter) GetSigners(tx sdk.Tx) ([]mempool.SignerData, error) {
26+
if txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx); ok {
27+
opts := txWithExtensions.GetExtensionOptions()
28+
if len(opts) > 0 && opts[0].GetTypeUrl() == "/cosmos.evm.vm.v1.ExtensionOptionsEthereumTx" {
29+
for _, msg := range tx.GetMsgs() {
30+
if ethMsg, ok := msg.(*evmtypes.MsgEthereumTx); ok {
31+
return []mempool.SignerData{
32+
mempool.NewSignerData(
33+
ethMsg.GetFrom(),
34+
ethMsg.AsTransaction().Nonce(),
35+
),
36+
}, nil
37+
}
38+
}
39+
}
40+
}
41+
42+
return s.fallback.GetSigners(tx)
43+
}

evmd/signer_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package evmd_test
2+
3+
import (
4+
"math/big"
5+
"testing"
6+
7+
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
8+
sdk "github.com/cosmos/cosmos-sdk/types"
9+
mempool "github.com/cosmos/cosmos-sdk/types/mempool"
10+
"github.com/cosmos/evm/evmd"
11+
"github.com/cosmos/evm/x/vm/types"
12+
"github.com/stretchr/testify/require"
13+
protov2 "google.golang.org/protobuf/proto"
14+
)
15+
16+
type mockFallback struct {
17+
called bool
18+
}
19+
20+
func (m *mockFallback) GetSigners(tx sdk.Tx) ([]mempool.SignerData, error) {
21+
m.called = true
22+
return []mempool.SignerData{mempool.NewSignerData(sdk.AccAddress("fallback"), 1)}, nil
23+
}
24+
25+
type mockHasExtOptions struct {
26+
msg sdk.Msg
27+
}
28+
29+
func (m *mockHasExtOptions) GetMsgs() []sdk.Msg { return []sdk.Msg{m.msg} }
30+
func (m *mockHasExtOptions) GetMsgsV2() ([]protov2.Message, error) {
31+
return []protov2.Message{}, nil
32+
}
33+
func (m *mockHasExtOptions) GetExtensionOptions() []*codectypes.Any {
34+
return []*codectypes.Any{
35+
{
36+
TypeUrl: "/cosmos.evm.vm.v1.ExtensionOptionsEthereumTx",
37+
Value: []byte{},
38+
},
39+
}
40+
}
41+
func (m *mockHasExtOptions) GetNonCriticalExtensionOptions() []*codectypes.Any { return nil }
42+
43+
func TestGetSigners(t *testing.T) {
44+
ethAddr := sdk.AccAddress("ethsigner")
45+
evmTx := &types.EvmTxArgs{
46+
ChainID: big.NewInt(100),
47+
Nonce: 1,
48+
Amount: big.NewInt(10),
49+
GasLimit: 100000,
50+
GasPrice: big.NewInt(150),
51+
GasFeeCap: big.NewInt(200),
52+
}
53+
ethMsg := types.NewTx(evmTx)
54+
ethMsg.From = ethAddr.Bytes()
55+
txWithEth := &mockHasExtOptions{
56+
msg: ethMsg,
57+
}
58+
fallback := &mockFallback{}
59+
adapter := evmd.NewEthSignerExtractionAdapter(fallback)
60+
signers, err := adapter.GetSigners(txWithEth)
61+
require.NoError(t, err)
62+
require.Equal(t, []mempool.SignerData{
63+
mempool.NewSignerData(
64+
ethMsg.GetFrom(),
65+
ethMsg.AsTransaction().Nonce(),
66+
),
67+
}, signers)
68+
require.False(t, fallback.called)
69+
70+
fallback = &mockFallback{}
71+
txWithEth = &mockHasExtOptions{}
72+
adapter = evmd.NewEthSignerExtractionAdapter(fallback)
73+
signers, err = adapter.GetSigners(txWithEth)
74+
require.NoError(t, err)
75+
fallbackSigners, err := new(mockFallback).GetSigners(txWithEth)
76+
require.NoError(t, err)
77+
require.Equal(t, fallbackSigners, signers)
78+
require.True(t, fallback.called)
79+
}

evmd/tests/integration/create_app.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/cosmos/evm/evmd"
99
"github.com/cosmos/evm/evmd/cmd/evmd/config"
1010
testconfig "github.com/cosmos/evm/testutil/config"
11+
"github.com/cosmos/evm/testutil/constants"
1112
feemarkettypes "github.com/cosmos/evm/x/feemarket/types"
1213
ibctesting "github.com/cosmos/ibc-go/v10/testing"
1314

@@ -54,7 +55,7 @@ func SetupEvmd() (ibctesting.TestingApp, map[string]json.RawMessage) {
5455
nil,
5556
true,
5657
simutils.EmptyAppOptions{},
57-
9001,
58+
constants.ExampleEIP155ChainID,
5859
testconfig.EvmAppOptions,
5960
)
6061
// disable base fee for testing

0 commit comments

Comments
 (0)