diff --git a/app/ante.go b/app/ante.go index 4a83135a06..3106816df2 100644 --- a/app/ante.go +++ b/app/ante.go @@ -124,7 +124,6 @@ func NewAnteHandlerAndDepGenerator(options HandlerOptions) (sdk.AnteHandler, sdk sdk.DefaultWrappedAnteDecorator(evmante.NewGasLimitDecorator(options.EVMKeeper)), } evmAnteHandler, evmAnteDepGenerator := sdk.ChainAnteDecorators(evmAnteDecorators...) - evmAnteHandler = evmante.NewAnteErrorHandler(evmAnteHandler, options.EVMKeeper).Handle router := evmante.NewEVMRouterDecorator(anteHandler, evmAnteHandler, anteDepGenerator, evmAnteDepGenerator) diff --git a/app/ante_test.go b/app/ante_test.go index 608b97deeb..7d2a7544ca 100644 --- a/app/ante_test.go +++ b/app/ante_test.go @@ -259,7 +259,9 @@ func TestEvmAnteErrorHandler(t *testing.T) { require.NotEqual(t, 0, res.Code) testkeeper.EVMTestApp.EvmKeeper.SetTxResults([]*abci.ExecTxResult{{ Code: res.Code, + Log: "nonce too high", }}) + testkeeper.EVMTestApp.EvmKeeper.SetMsgs([]*evmtypes.MsgEVMTransaction{req}) deferredInfo := testkeeper.EVMTestApp.EvmKeeper.GetEVMTxDeferredInfo(ctx) require.Equal(t, 1, len(deferredInfo)) require.Contains(t, deferredInfo[0].Error, "nonce too high") diff --git a/app/app.go b/app/app.go index 8eae8ecd2b..b50cf36a7b 100644 --- a/app/app.go +++ b/app/app.go @@ -433,7 +433,7 @@ func New( // this line is used by starport scaffolding # stargate/app/storeKey ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientStoreKey) - memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey, dexmoduletypes.MemStoreKey, banktypes.DeferredCacheStoreKey, evmtypes.MemStoreKey, oracletypes.MemStoreKey) + memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey, dexmoduletypes.MemStoreKey, banktypes.DeferredCacheStoreKey, oracletypes.MemStoreKey) app := &App{ BaseApp: bApp, @@ -622,7 +622,7 @@ func New( panic(fmt.Sprintf("error while creating receipt store: %s", err)) } } - app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey], + app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), app.receiptStore, app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper, app.TransferKeeper, wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper), &app.WasmKeeper) @@ -1589,6 +1589,7 @@ func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequ beginBlockResp := app.BeginBlock(ctx, beginBlockReq) events = append(events, beginBlockResp.Events...) + evmTxs := make([]*evmtypes.MsgEVMTransaction, len(txs)) // nil for non-EVM txs txResults := make([]*abci.ExecTxResult, len(txs)) typedTxs := app.DecodeTransactionsConcurrently(ctx, txs) @@ -1598,6 +1599,11 @@ func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequ prioritizedResults, ctx := app.ExecuteTxsConcurrently(ctx, prioritizedTxs, prioritizedTypedTxs, prioritizedIndices) for relativePrioritizedIndex, originalIndex := range prioritizedIndices { txResults[originalIndex] = prioritizedResults[relativePrioritizedIndex] + if emsg := evmtypes.GetEVMTransactionMessage(prioritizedTypedTxs[relativePrioritizedIndex]); emsg != nil && !emsg.IsAssociateTx() { + evmTxs[originalIndex] = emsg + } else { + evmTxs[originalIndex] = nil + } } // Finalize all Bank Module Transfers here so that events are included for prioritiezd txs @@ -1610,8 +1616,14 @@ func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequ otherResults, ctx := app.ExecuteTxsConcurrently(ctx, otherTxs, otherTypedTxs, otherIndices) for relativeOtherIndex, originalIndex := range otherIndices { txResults[originalIndex] = otherResults[relativeOtherIndex] + if emsg := evmtypes.GetEVMTransactionMessage(otherTypedTxs[relativeOtherIndex]); emsg != nil && !emsg.IsAssociateTx() { + evmTxs[originalIndex] = emsg + } else { + evmTxs[originalIndex] = nil + } } app.EvmKeeper.SetTxResults(txResults) + app.EvmKeeper.SetMsgs(evmTxs) // Finalize all Bank Module Transfers here so that events are included lazyWriteEvents := app.BankKeeper.WriteDeferredBalances(ctx) diff --git a/go.mod b/go.mod index 06a52bd876..f819fe22b7 100644 --- a/go.mod +++ b/go.mod @@ -126,6 +126,7 @@ require ( github.com/fzipp/gocyclo v0.5.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect + github.com/ghodss/yaml v1.0.0 // indirect github.com/go-critic/go-critic v0.6.3 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -173,6 +174,7 @@ require ( github.com/gostaticanalysis/nilerr v0.1.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect diff --git a/go.sum b/go.sum index 60c7f93541..c623f691ca 100644 --- a/go.sum +++ b/go.sum @@ -457,6 +457,7 @@ github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2Gihuqh github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -765,6 +766,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/guptarohit/asciigraph v0.5.5/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= @@ -2255,8 +2258,12 @@ google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2I google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No= google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= @@ -2276,6 +2283,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/proto/evm/types.proto b/proto/evm/types.proto index 221781a9df..2dd04222a4 100644 --- a/proto/evm/types.proto +++ b/proto/evm/types.proto @@ -9,4 +9,15 @@ message Whitelist { repeated string hashes = 1 [ (gogoproto.moretags) = "yaml:\"hashes\"" ]; +} + +message DeferredInfo { + uint32 tx_index = 1; + bytes tx_hash = 2; + bytes tx_bloom = 3; + string surplus = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + string error = 5; } \ No newline at end of file diff --git a/x/evm/ante/error.go b/x/evm/ante/error.go deleted file mode 100644 index d1d7ab5a67..0000000000 --- a/x/evm/ante/error.go +++ /dev/null @@ -1,40 +0,0 @@ -package ante - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/sei-protocol/sei-chain/x/evm/keeper" - "github.com/sei-protocol/sei-chain/x/evm/types" - "github.com/sei-protocol/sei-chain/x/evm/types/ethtx" -) - -type AnteErrorHandler struct { - wrapped sdk.AnteHandler - k *keeper.Keeper -} - -func NewAnteErrorHandler(wrapped sdk.AnteHandler, k *keeper.Keeper) *AnteErrorHandler { - return &AnteErrorHandler{wrapped: wrapped, k: k} -} - -// if there is any error in ante handler, record it in deferred info so that a receipt -// can be written for it in the EndBlock. (we can't directly write receipt here since -// we still need to return an error which will cause any write here to revert) -func (a *AnteErrorHandler) Handle(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { - newCtx, err = a.wrapped(ctx, tx, simulate) - if err != nil && !ctx.IsCheckTx() && !ctx.IsReCheckTx() && !simulate { - msg := types.MustGetEVMTransactionMessage(tx) - txData, unpackerr := types.UnpackTxData(msg.Data) - if unpackerr != nil { - ctx.Logger().Error(fmt.Sprintf("failed to unpack message data %X", msg.Data.Value)) - return - } - if _, ok := txData.(*ethtx.AssociateTx); ok { - return - } - a.k.AppendErrorToEvmTxDeferredInfo(ctx, ethtypes.NewTx(txData.AsEthereumData()).Hash(), err.Error()) - } - return -} diff --git a/x/evm/ante/error_test.go b/x/evm/ante/error_test.go deleted file mode 100644 index 8b312a64f3..0000000000 --- a/x/evm/ante/error_test.go +++ /dev/null @@ -1,124 +0,0 @@ -package ante_test - -import ( - "errors" - "testing" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/golang/protobuf/proto" - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/abci/example/code" - abci "github.com/tendermint/tendermint/abci/types" - - testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" - "github.com/sei-protocol/sei-chain/x/evm/ante" - "github.com/sei-protocol/sei-chain/x/evm/keeper" - "github.com/sei-protocol/sei-chain/x/evm/types" - "github.com/sei-protocol/sei-chain/x/evm/types/ethtx" -) - -type test struct { - name string - tx proto.Message - simulate bool - ctxSetup func(ctx sdk.Context) sdk.Context - handlerErr error - txResultCode uint32 - assertions func(t *testing.T, ctx sdk.Context, k *keeper.Keeper, err error) -} - -var testErr = errors.New("test") - -func TestAnteErrorHandler_Handle(t *testing.T) { - tests := []test{ - { - name: "no error should avoid appending an error", - txResultCode: abci.CodeTypeOK, - tx: ðtx.LegacyTx{}, - assertions: func(t *testing.T, ctx sdk.Context, k *keeper.Keeper, err error) { - require.Len(t, k.GetEVMTxDeferredInfo(ctx), 0) - }, - }, - { - name: "error should append error to deferred info", - handlerErr: testErr, - txResultCode: code.CodeTypeUnknownError, - tx: ðtx.LegacyTx{}, - assertions: func(t *testing.T, ctx sdk.Context, k *keeper.Keeper, err error) { - require.ErrorIs(t, err, testErr) - require.Len(t, k.GetEVMTxDeferredInfo(ctx), 1) - require.Equal(t, k.GetEVMTxDeferredInfo(ctx)[0].Error, testErr.Error()) - }, - }, - { - name: "error on check tx should avoid appending an error", - txResultCode: code.CodeTypeUnknownError, - ctxSetup: func(ctx sdk.Context) sdk.Context { - return ctx.WithIsCheckTx(true) - }, - handlerErr: testErr, - tx: ðtx.LegacyTx{}, - assertions: func(t *testing.T, ctx sdk.Context, k *keeper.Keeper, err error) { - require.Len(t, k.GetEVMTxDeferredInfo(ctx), 0) - }, - }, - { - name: "error on re-check tx should avoid appending an error", - txResultCode: code.CodeTypeUnknownError, - ctxSetup: func(ctx sdk.Context) sdk.Context { - return ctx.WithIsReCheckTx(true) - }, - handlerErr: testErr, - tx: ðtx.LegacyTx{}, - assertions: func(t *testing.T, ctx sdk.Context, k *keeper.Keeper, err error) { - require.Len(t, k.GetEVMTxDeferredInfo(ctx), 0) - }, - }, - { - name: "error with simulate should avoid appending an error", - txResultCode: code.CodeTypeUnknownError, - handlerErr: testErr, - simulate: true, - tx: ðtx.LegacyTx{}, - assertions: func(t *testing.T, ctx sdk.Context, k *keeper.Keeper, err error) { - require.Len(t, k.GetEVMTxDeferredInfo(ctx), 0) - }, - }, - { - name: "error should not append error to deferred info if associate tx", - handlerErr: testErr, - txResultCode: code.CodeTypeUnknownError, - tx: ðtx.AssociateTx{}, - assertions: func(t *testing.T, ctx sdk.Context, k *keeper.Keeper, err error) { - require.ErrorIs(t, err, testErr) - require.Len(t, k.GetEVMTxDeferredInfo(ctx), 0) - }, - }, - { - name: "error should not append error if data of tx cannot be decoded (not an evm message)", - handlerErr: testErr, - txResultCode: code.CodeTypeUnknownError, - tx: &sdk.GasInfo{ // not a valid eth tx, just a random proto so it will fail - GasWanted: 100, - GasUsed: 100, - }, - assertions: func(t *testing.T, ctx sdk.Context, k *keeper.Keeper, err error) { - require.Error(t, err, "failed to unpack message data") - require.Len(t, k.GetEVMTxDeferredInfo(ctx), 0) - }, - }, - } - for _, test := range tests { - k, ctx := testkeeper.MockEVMKeeper() - if test.ctxSetup != nil { - ctx = test.ctxSetup(ctx) - } - eh := ante.NewAnteErrorHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { - return ctx, test.handlerErr - }, k) - k.SetTxResults([]*abci.ExecTxResult{{Code: test.txResultCode}}) - msg, _ := types.NewMsgEVMTransaction(test.tx) - newCtx, err := eh.Handle(ctx, &mockTx{msgs: []sdk.Msg{msg}}, test.simulate) - test.assertions(t, newCtx, k, err) - } -} diff --git a/x/evm/keeper/ante.go b/x/evm/keeper/ante.go index 4499a84ee5..f39252c0a4 100644 --- a/x/evm/keeper/ante.go +++ b/x/evm/keeper/ante.go @@ -8,7 +8,7 @@ import ( ) func (k *Keeper) AddAnteSurplus(ctx sdk.Context, txHash common.Hash, surplus sdk.Int) error { - store := prefix.NewStore(ctx.KVStore(k.memStoreKey), types.AnteSurplusPrefix) + store := prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.AnteSurplusPrefix) bz, err := surplus.Marshal() if err != nil { return err @@ -18,7 +18,7 @@ func (k *Keeper) AddAnteSurplus(ctx sdk.Context, txHash common.Hash, surplus sdk } func (k *Keeper) GetAnteSurplusSum(ctx sdk.Context) sdk.Int { - iter := prefix.NewStore(ctx.KVStore(k.memStoreKey), types.AnteSurplusPrefix).Iterator(nil, nil) + iter := prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.AnteSurplusPrefix).Iterator(nil, nil) defer iter.Close() res := sdk.ZeroInt() for ; iter.Valid(); iter.Next() { @@ -28,7 +28,3 @@ func (k *Keeper) GetAnteSurplusSum(ctx sdk.Context) sdk.Int { } return res } - -func (k *Keeper) DeleteAllAnteSurplus(ctx sdk.Context) { - _ = prefix.NewStore(ctx.KVStore(k.memStoreKey), types.AnteSurplusPrefix).DeleteAll(nil, nil) -} diff --git a/x/evm/keeper/deferred.go b/x/evm/keeper/deferred.go new file mode 100644 index 0000000000..e8f930b52f --- /dev/null +++ b/x/evm/keeper/deferred.go @@ -0,0 +1,65 @@ +package keeper + +import ( + "encoding/binary" + "fmt" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/sei-protocol/sei-chain/x/evm/types" +) + +func (k *Keeper) GetEVMTxDeferredInfo(ctx sdk.Context) (res []*types.DeferredInfo) { + store := prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.DeferredInfoPrefix) + for txIdx, msg := range k.msgs { + if msg == nil { + continue + } + txRes := k.txResults[txIdx] + key := make([]byte, 8) + binary.BigEndian.PutUint64(key, uint64(txIdx)) + val := store.Get(key) + if val == nil { + // this means the transaction got reverted during execution, either in ante handler + // or due to a panic in msg server + etx, _ := msg.AsTransaction() + if txRes.Code == 0 { + ctx.Logger().Error(fmt.Sprintf("transaction %s has code 0 but no deferred info", etx.Hash().Hex())) + } + res = append(res, &types.DeferredInfo{ + TxIndex: uint32(txIdx), + TxHash: etx.Hash().Bytes(), + Error: txRes.Log, + }) + } else { + info := &types.DeferredInfo{} + if err := info.Unmarshal(val); err != nil { + // unable to unmarshal deferred info is serious, because it could cause + // balance surplus to be mishandled and thus affect total supply + panic(err) + } + res = append(res, info) + } + } + return +} + +func (k *Keeper) AppendToEvmTxDeferredInfo(ctx sdk.Context, bloom ethtypes.Bloom, txHash common.Hash, surplus sdk.Int) { + key := make([]byte, 8) + binary.BigEndian.PutUint64(key, uint64(ctx.TxIndex())) + val := &types.DeferredInfo{ + TxIndex: uint32(ctx.TxIndex()), + TxBloom: bloom[:], + TxHash: txHash[:], + Surplus: surplus, + } + bz, err := val.Marshal() + if err != nil { + // unable to marshal deferred info is serious, because it could cause + // balance surplus to be mishandled and thus affect total supply + panic(err) + } + prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.DeferredInfoPrefix).Set(key, bz) +} diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index f361ba890a..895baf7b51 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -14,7 +14,6 @@ import ( wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" @@ -44,13 +43,12 @@ import ( type Keeper struct { storeKey sdk.StoreKey - memStoreKey sdk.StoreKey transientStoreKey sdk.StoreKey Paramstore paramtypes.Subspace - deferredInfo *sync.Map - txResults []*abci.ExecTxResult + txResults []*abci.ExecTxResult + msgs []*types.MsgEVMTransaction bankKeeper bankkeeper.Keeper accountKeeper *authkeeper.AccountKeeper @@ -84,14 +82,6 @@ type Keeper struct { receiptStore seidbtypes.StateStore } -type EvmTxDeferredInfo struct { - TxIndx int - TxHash common.Hash - TxBloom ethtypes.Bloom - Surplus sdk.Int - Error string -} - type AddressNoncePair struct { Address common.Address Nonce uint64 @@ -121,7 +111,7 @@ func (ctx *ReplayChainContext) GetHeader(hash common.Hash, number uint64) *ethty } func NewKeeper( - storeKey sdk.StoreKey, memStoreKey sdk.StoreKey, transientStoreKey sdk.StoreKey, paramstore paramtypes.Subspace, receiptStateStore seidbtypes.StateStore, + storeKey sdk.StoreKey, transientStoreKey sdk.StoreKey, paramstore paramtypes.Subspace, receiptStateStore seidbtypes.StateStore, bankKeeper bankkeeper.Keeper, accountKeeper *authkeeper.AccountKeeper, stakingKeeper *stakingkeeper.Keeper, transferKeeper ibctransferkeeper.Keeper, wasmKeeper *wasmkeeper.PermissionedKeeper, wasmViewKeeper *wasmkeeper.Keeper) *Keeper { if !paramstore.HasKeyTable() { @@ -129,7 +119,6 @@ func NewKeeper( } k := &Keeper{ storeKey: storeKey, - memStoreKey: memStoreKey, transientStoreKey: transientStoreKey, Paramstore: paramstore, bankKeeper: bankKeeper, @@ -142,7 +131,6 @@ func NewKeeper( nonceMx: &sync.RWMutex{}, cachedFeeCollectorAddressMtx: &sync.RWMutex{}, keyToNonce: make(map[tmtypes.TxKey]*AddressNoncePair), - deferredInfo: &sync.Map{}, receiptStore: receiptStateStore, } return k @@ -249,43 +237,6 @@ func (k *Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { } } -func (k *Keeper) GetEVMTxDeferredInfo(ctx sdk.Context) (res []EvmTxDeferredInfo) { - k.deferredInfo.Range(func(key, value any) bool { - txIdx := key.(int) - if txIdx < 0 || txIdx >= len(k.txResults) { - ctx.Logger().Error(fmt.Sprintf("getting invalid tx index in EVM deferred info: %d, num of txs: %d", txIdx, len(k.txResults))) - return true - } - if k.txResults[txIdx].Code == 0 || k.txResults[txIdx].Code == sdkerrors.ErrEVMVMError.ABCICode() || value.(*EvmTxDeferredInfo).Error != "" { - res = append(res, *(value.(*EvmTxDeferredInfo))) - } - return true - }) - sort.SliceStable(res, func(i, j int) bool { return res[i].TxIndx < res[j].TxIndx }) - return -} - -func (k *Keeper) AppendToEvmTxDeferredInfo(ctx sdk.Context, bloom ethtypes.Bloom, txHash common.Hash, surplus sdk.Int) { - k.deferredInfo.Store(ctx.TxIndex(), &EvmTxDeferredInfo{ - TxIndx: ctx.TxIndex(), - TxBloom: bloom, - TxHash: txHash, - Surplus: surplus, - }) -} - -func (k *Keeper) AppendErrorToEvmTxDeferredInfo(ctx sdk.Context, txHash common.Hash, err string) { - k.deferredInfo.Store(ctx.TxIndex(), &EvmTxDeferredInfo{ - TxIndx: ctx.TxIndex(), - TxHash: txHash, - Error: err, - }) -} - -func (k *Keeper) ClearEVMTxDeferredInfo() { - k.deferredInfo = &sync.Map{} -} - func (k *Keeper) getHistoricalHash(ctx sdk.Context, h int64) common.Hash { histInfo, found := k.stakingKeeper.GetHistoricalInfo(ctx, h) if !found { @@ -406,6 +357,10 @@ func (k *Keeper) SetTxResults(txResults []*abci.ExecTxResult) { k.txResults = txResults } +func (k *Keeper) SetMsgs(msgs []*types.MsgEVMTransaction) { + k.msgs = msgs +} + // Test use only func (k *Keeper) GetPendingTxs() map[string][]*PendingTx { return k.pendingTxs diff --git a/x/evm/keeper/keeper_test.go b/x/evm/keeper/keeper_test.go index 1dbd34b563..90de9a83b9 100644 --- a/x/evm/keeper/keeper_test.go +++ b/x/evm/keeper/keeper_test.go @@ -1,7 +1,10 @@ package keeper_test import ( + "context" + "encoding/hex" "math" + "math/big" "sync" "testing" @@ -9,10 +12,14 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/sei-protocol/sei-chain/app" "github.com/sei-protocol/sei-chain/testutil/keeper" + testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm/config" evmkeeper "github.com/sei-protocol/sei-chain/x/evm/keeper" "github.com/sei-protocol/sei-chain/x/evm/types" + "github.com/sei-protocol/sei-chain/x/evm/types/ethtx" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/rand" @@ -198,26 +205,36 @@ func TestKeeper_CalculateNextNonce(t *testing.T) { } func TestDeferredInfo(t *testing.T) { - k, ctx := keeper.MockEVMKeeper() + a := app.Setup(false, false) + k := a.EvmKeeper + ctx := a.GetContextForDeliverTx([]byte{}) ctx = ctx.WithTxIndex(1) k.AppendToEvmTxDeferredInfo(ctx, ethtypes.Bloom{1, 2, 3}, common.Hash{4, 5, 6}, sdk.NewInt(1)) ctx = ctx.WithTxIndex(2) k.AppendToEvmTxDeferredInfo(ctx, ethtypes.Bloom{7, 8}, common.Hash{9, 0}, sdk.NewInt(1)) - ctx = ctx.WithTxIndex(3) // should be ignored because txResult has non-zero code - k.AppendToEvmTxDeferredInfo(ctx, ethtypes.Bloom{11, 12}, common.Hash{13, 14}, sdk.NewInt(1)) - k.SetTxResults([]*abci.ExecTxResult{{Code: 0}, {Code: 0}, {Code: 0}, {Code: 1}}) + k.SetTxResults([]*abci.ExecTxResult{{Code: 0}, {Code: 0}, {Code: 0}, {Code: 1, Log: "test error"}}) + msg := mockEVMTransactionMessage(t) + k.SetMsgs([]*types.MsgEVMTransaction{nil, {}, {}, msg}) infoList := k.GetEVMTxDeferredInfo(ctx) - require.Equal(t, 2, len(infoList)) - require.Equal(t, 1, infoList[0].TxIndx) - require.Equal(t, ethtypes.Bloom{1, 2, 3}, infoList[0].TxBloom) - require.Equal(t, common.Hash{4, 5, 6}, infoList[0].TxHash) + require.Equal(t, 3, len(infoList)) + require.Equal(t, uint32(1), infoList[0].TxIndex) + require.Equal(t, ethtypes.Bloom{1, 2, 3}, ethtypes.BytesToBloom(infoList[0].TxBloom)) + require.Equal(t, common.Hash{4, 5, 6}, common.BytesToHash(infoList[0].TxHash)) require.Equal(t, sdk.NewInt(1), infoList[0].Surplus) - require.Equal(t, 2, infoList[1].TxIndx) - require.Equal(t, ethtypes.Bloom{7, 8}, infoList[1].TxBloom) - require.Equal(t, common.Hash{9, 0}, infoList[1].TxHash) + require.Equal(t, uint32(2), infoList[1].TxIndex) + require.Equal(t, ethtypes.Bloom{7, 8}, ethtypes.BytesToBloom(infoList[1].TxBloom)) + require.Equal(t, common.Hash{9, 0}, common.BytesToHash(infoList[1].TxHash)) require.Equal(t, sdk.NewInt(1), infoList[1].Surplus) + require.Equal(t, uint32(3), infoList[2].TxIndex) + require.Equal(t, ethtypes.Bloom{}, ethtypes.BytesToBloom(infoList[2].TxBloom)) + etx, _ := msg.AsTransaction() + require.Equal(t, etx.Hash(), common.BytesToHash(infoList[2].TxHash)) + require.Equal(t, "test error", infoList[2].Error) // test clear tx deferred info - k.ClearEVMTxDeferredInfo() + a.SetDeliverStateToCommit() + a.Commit(context.Background()) // commit would clear transient stores + k.SetTxResults([]*abci.ExecTxResult{}) + k.SetMsgs([]*types.MsgEVMTransaction{}) infoList = k.GetEVMTxDeferredInfo(ctx) require.Empty(t, len(infoList)) } @@ -242,3 +259,31 @@ func TestAddPendingNonce(t *testing.T) { require.Equal(t, uint64(2), keyToNonce[tmtypes.TxKey{3}].Nonce) require.NotContains(t, keyToNonce, tmtypes.TxKey{2}) } + +func mockEVMTransactionMessage(t *testing.T) *types.MsgEVMTransaction { + k, ctx := testkeeper.MockEVMKeeper() + chainID := k.ChainID(ctx) + chainCfg := types.DefaultChainConfig() + ethCfg := chainCfg.EthereumConfig(chainID) + blockNum := big.NewInt(ctx.BlockHeight()) + privKey := testkeeper.MockPrivateKey() + testPrivHex := hex.EncodeToString(privKey.Bytes()) + key, _ := crypto.HexToECDSA(testPrivHex) + to := new(common.Address) + txData := ethtypes.DynamicFeeTx{ + Nonce: 1, + GasFeeCap: big.NewInt(10000000000000), + Gas: 1000, + To: to, + Value: big.NewInt(1000000000000000), + Data: []byte("abc"), + ChainID: chainID, + } + + signer := ethtypes.MakeSigner(ethCfg, blockNum, uint64(ctx.BlockTime().Unix())) + tx, err := ethtypes.SignTx(ethtypes.NewTx(&txData), signer, key) + typedTx, err := ethtx.NewDynamicFeeTx(tx) + msg, err := types.NewMsgEVMTransaction(typedTx) + require.Nil(t, err) + return msg +} diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index 1ee18a7d3b..4c01d43be3 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -69,8 +69,6 @@ func (server msgServer) EVMTransaction(goCtx context.Context, msg *types.MsgEVMT ctx.Logger().Error(fmt.Sprintf("EVM PANIC: %s", pe)) telemetry.IncrCounter(1, types.ModuleName, "panics") } - server.AppendErrorToEvmTxDeferredInfo(ctx, tx.Hash(), fmt.Sprintf("%s", pe)) - panic(pe) } if err != nil { diff --git a/x/evm/module.go b/x/evm/module.go index 9f6209c797..e7f0491b6b 100644 --- a/x/evm/module.go +++ b/x/evm/module.go @@ -186,10 +186,9 @@ func (AppModule) ConsensusVersion() uint64 { return 8 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { - // clear tx responses from last block + // clear tx/tx responses from last block + am.keeper.SetMsgs([]*types.MsgEVMTransaction{}) am.keeper.SetTxResults([]*abci.ExecTxResult{}) - // clear the TxDeferredInfo - am.keeper.ClearEVMTxDeferredInfo() // mock beacon root if replaying if am.keeper.EthReplayConfig.Enabled { if beaconRoot := am.keeper.ReplayBlock.BeaconRoot(); beaconRoot != nil { @@ -229,16 +228,17 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val denom := am.keeper.GetBaseDenom(ctx) surplus := am.keeper.GetAnteSurplusSum(ctx) for _, deferredInfo := range evmTxDeferredInfoList { - if deferredInfo.Error != "" && deferredInfo.TxHash.Cmp(ethtypes.EmptyTxsHash) != 0 { - _ = am.keeper.SetTransientReceipt(ctx, deferredInfo.TxHash, &types.Receipt{ - TxHashHex: deferredInfo.TxHash.Hex(), - TransactionIndex: uint32(deferredInfo.TxIndx), + txHash := common.BytesToHash(deferredInfo.TxHash) + if deferredInfo.Error != "" && txHash.Cmp(ethtypes.EmptyTxsHash) != 0 { + _ = am.keeper.SetTransientReceipt(ctx, txHash, &types.Receipt{ + TxHashHex: txHash.Hex(), + TransactionIndex: deferredInfo.TxIndex, VmError: deferredInfo.Error, BlockNumber: uint64(ctx.BlockHeight()), }) continue } - idx := deferredInfo.TxIndx + idx := int(deferredInfo.TxIndex) coinbaseAddress := state.GetCoinbaseAddress(idx) balance := am.keeper.BankKeeper().SpendableCoins(ctx, coinbaseAddress).AmountOf(denom) weiBalance := am.keeper.BankKeeper().GetWeiBalance(ctx, coinbaseAddress) @@ -262,8 +262,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val } } } - am.keeper.SetTxHashesOnHeight(ctx, ctx.BlockHeight(), utils.Filter(utils.Map(evmTxDeferredInfoList, func(i keeper.EvmTxDeferredInfo) common.Hash { return i.TxHash }), func(h common.Hash) bool { return h.Cmp(ethtypes.EmptyTxsHash) != 0 })) - am.keeper.SetBlockBloom(ctx, ctx.BlockHeight(), utils.Map(evmTxDeferredInfoList, func(i keeper.EvmTxDeferredInfo) ethtypes.Bloom { return i.TxBloom })) - am.keeper.DeleteAllAnteSurplus(ctx) + am.keeper.SetTxHashesOnHeight(ctx, ctx.BlockHeight(), utils.Filter(utils.Map(evmTxDeferredInfoList, func(i *types.DeferredInfo) common.Hash { return common.BytesToHash(i.TxHash) }), func(h common.Hash) bool { return h.Cmp(ethtypes.EmptyTxsHash) != 0 })) + am.keeper.SetBlockBloom(ctx, ctx.BlockHeight(), utils.Map(evmTxDeferredInfoList, func(i *types.DeferredInfo) ethtypes.Bloom { return ethtypes.BytesToBloom(i.TxBloom) })) return []abci.ValidatorUpdate{} } diff --git a/x/evm/module_test.go b/x/evm/module_test.go index 12d1b99036..6309406e84 100644 --- a/x/evm/module_test.go +++ b/x/evm/module_test.go @@ -1,12 +1,15 @@ package evm_test import ( - "github.com/cosmos/cosmos-sdk/client" - "github.com/grpc-ecosystem/grpc-gateway/runtime" + "context" + "encoding/hex" "math" "math/big" "testing" + "github.com/cosmos/cosmos-sdk/client" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" @@ -14,10 +17,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/tracing" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/sei-protocol/sei-chain/app" testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm" "github.com/sei-protocol/sei-chain/x/evm/state" "github.com/sei-protocol/sei-chain/x/evm/types" + "github.com/sei-protocol/sei-chain/x/evm/types/ethtx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" @@ -86,6 +92,7 @@ func TestABCI(t *testing.T) { require.Equal(t, sdk.ZeroInt(), surplus) k.AppendToEvmTxDeferredInfo(ctx.WithTxIndex(3), ethtypes.Bloom{}, common.Hash{3}, surplus) k.SetTxResults([]*abci.ExecTxResult{{Code: 0}, {Code: 0}, {Code: 0}, {Code: 0}}) + k.SetMsgs([]*types.MsgEVMTransaction{nil, {}, nil, {}}) m.EndBlock(ctx, abci.RequestEndBlock{}) require.Equal(t, uint64(0), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(types.ModuleName), "usei").Amount.Uint64()) require.Equal(t, uint64(2), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(authtypes.FeeCollectorName), "usei").Amount.Uint64()) @@ -101,18 +108,21 @@ func TestABCI(t *testing.T) { require.Equal(t, sdk.NewInt(1000000000000), surplus) k.AppendToEvmTxDeferredInfo(ctx.WithTxIndex(2), ethtypes.Bloom{}, common.Hash{2}, surplus) k.SetTxResults([]*abci.ExecTxResult{{Code: 0}, {Code: 0}, {Code: 0}}) + k.SetMsgs([]*types.MsgEVMTransaction{nil, nil, {}}) m.EndBlock(ctx, abci.RequestEndBlock{}) require.Equal(t, uint64(1), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(types.ModuleName), "usei").Amount.Uint64()) require.Equal(t, uint64(2), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(authtypes.FeeCollectorName), "usei").Amount.Uint64()) // third block m.BeginBlock(ctx, abci.RequestBeginBlock{}) - k.AppendErrorToEvmTxDeferredInfo(ctx.WithTxIndex(0), common.Hash{1}, "test error") - k.SetTxResults([]*abci.ExecTxResult{{Code: 1}}) + msg := mockEVMTransactionMessage(t) + k.SetMsgs([]*types.MsgEVMTransaction{msg}) + k.SetTxResults([]*abci.ExecTxResult{{Code: 1, Log: "test error"}}) m.EndBlock(ctx, abci.RequestEndBlock{}) err = k.FlushTransientReceipts(ctx) require.NoError(t, err) - receipt, err := k.GetReceipt(ctx, common.Hash{1}) + tx, _ := msg.AsTransaction() + receipt, err := k.GetReceipt(ctx, tx.Hash()) require.Nil(t, err) require.Equal(t, receipt.BlockNumber, uint64(ctx.BlockHeight())) require.Equal(t, receipt.VmError, "test error") @@ -136,6 +146,7 @@ func TestABCI(t *testing.T) { require.Nil(t, err) k.AppendToEvmTxDeferredInfo(ctx.WithTxIndex(2), ethtypes.Bloom{}, common.Hash{}, surplus) k.SetTxResults([]*abci.ExecTxResult{{Code: 0}, {Code: 0}, {Code: 0}}) + k.SetMsgs([]*types.MsgEVMTransaction{nil, nil, {}}) require.Equal(t, sdk.OneInt(), k.BankKeeper().SpendableCoins(ctx, coinbase).AmountOf("usei")) m.EndBlock(ctx, abci.RequestEndBlock{}) // should not crash require.Equal(t, sdk.OneInt(), k.BankKeeper().GetBalance(ctx, coinbase, "usei").Amount) @@ -143,8 +154,10 @@ func TestABCI(t *testing.T) { } func TestAnteSurplus(t *testing.T) { - k, ctx := testkeeper.MockEVMKeeper() - m := evm.NewAppModule(nil, k) + a := app.Setup(false, false) + k := a.EvmKeeper + ctx := a.GetContextForDeliverTx([]byte{}) + m := evm.NewAppModule(nil, &k) // first block m.BeginBlock(ctx, abci.RequestBeginBlock{}) k.AddAnteSurplus(ctx, common.BytesToHash([]byte("1234")), sdk.NewInt(1_000_000_000_001)) @@ -152,6 +165,8 @@ func TestAnteSurplus(t *testing.T) { require.Equal(t, uint64(1), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(types.ModuleName), "usei").Amount.Uint64()) require.Equal(t, uint64(1), k.BankKeeper().GetWeiBalance(ctx, k.AccountKeeper().GetModuleAddress(types.ModuleName)).Uint64()) // ante surplus should be cleared + a.SetDeliverStateToCommit() + a.Commit(context.Background()) require.Equal(t, uint64(0), k.GetAnteSurplusSum(ctx).Uint64()) } @@ -164,3 +179,31 @@ func TestRoutesAddition(t *testing.T) { require.NotNil(t, appModule) } + +func mockEVMTransactionMessage(t *testing.T) *types.MsgEVMTransaction { + k, ctx := testkeeper.MockEVMKeeper() + chainID := k.ChainID(ctx) + chainCfg := types.DefaultChainConfig() + ethCfg := chainCfg.EthereumConfig(chainID) + blockNum := big.NewInt(ctx.BlockHeight()) + privKey := testkeeper.MockPrivateKey() + testPrivHex := hex.EncodeToString(privKey.Bytes()) + key, _ := crypto.HexToECDSA(testPrivHex) + to := new(common.Address) + txData := ethtypes.DynamicFeeTx{ + Nonce: 1, + GasFeeCap: big.NewInt(10000000000000), + Gas: 1000, + To: to, + Value: big.NewInt(1000000000000000), + Data: []byte("abc"), + ChainID: chainID, + } + + signer := ethtypes.MakeSigner(ethCfg, blockNum, uint64(ctx.BlockTime().Unix())) + tx, err := ethtypes.SignTx(ethtypes.NewTx(&txData), signer, key) + typedTx, err := ethtx.NewDynamicFeeTx(tx) + msg, err := types.NewMsgEVMTransaction(typedTx) + require.Nil(t, err) + return msg +} diff --git a/x/evm/types/keys.go b/x/evm/types/keys.go index 946cf78947..3234b73c88 100644 --- a/x/evm/types/keys.go +++ b/x/evm/types/keys.go @@ -16,8 +16,6 @@ const ( // StoreKey is string representation of the store key for auth StoreKey = "evm" - MemStoreKey = "evm_mem" - TransientStoreKey = "evm_transient" ReceiptStoreKey = "receipt" @@ -42,9 +40,9 @@ var ( BlockBloomPrefix = []byte{0x0d} TxHashesPrefix = []byte{0x0e} WhitelistedCodeHashesForDelegateCallPrefix = []byte{0x0f} - //mem - TxHashPrefix = []byte{0x10} - TxBloomPrefix = []byte{0x11} + + // TxHashPrefix = []byte{0x10} + // TxBloomPrefix = []byte{0x11} ReplaySeenAddrPrefix = []byte{0x12} ReplayedHeight = []byte{0x13} @@ -54,7 +52,8 @@ var ( PointerCWCodePrefix = []byte{0x16} PointerReverseRegistryPrefix = []byte{0x17} - AnteSurplusPrefix = []byte{0x18} + AnteSurplusPrefix = []byte{0x18} // transient + DeferredInfoPrefix = []byte{0x19} // transient ) var ( diff --git a/x/evm/types/message_evm_transaction.go b/x/evm/types/message_evm_transaction.go index b68793830a..affcc37014 100644 --- a/x/evm/types/message_evm_transaction.go +++ b/x/evm/types/message_evm_transaction.go @@ -79,6 +79,17 @@ func MustGetEVMTransactionMessage(tx sdk.Tx) *MsgEVMTransaction { return msg } +func GetEVMTransactionMessage(tx sdk.Tx) *MsgEVMTransaction { + if len(tx.GetMsgs()) != 1 { + return nil + } + msg, ok := tx.GetMsgs()[0].(*MsgEVMTransaction) + if !ok { + return nil + } + return msg +} + func (res *MsgEVMTransactionResponse) DecorateSdkResult(sdkRes *sdk.Result) { if res == nil { return diff --git a/x/evm/types/types.pb.go b/x/evm/types/types.pb.go index e3156fffe1..9f4976c0ba 100644 --- a/x/evm/types/types.pb.go +++ b/x/evm/types/types.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" io "io" @@ -67,26 +68,105 @@ func (m *Whitelist) GetHashes() []string { return nil } +type DeferredInfo struct { + TxIndex uint32 `protobuf:"varint,1,opt,name=tx_index,json=txIndex,proto3" json:"tx_index,omitempty"` + TxHash []byte `protobuf:"bytes,2,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` + TxBloom []byte `protobuf:"bytes,3,opt,name=tx_bloom,json=txBloom,proto3" json:"tx_bloom,omitempty"` + Surplus github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=surplus,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"surplus"` + Error string `protobuf:"bytes,5,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *DeferredInfo) Reset() { *m = DeferredInfo{} } +func (m *DeferredInfo) String() string { return proto.CompactTextString(m) } +func (*DeferredInfo) ProtoMessage() {} +func (*DeferredInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_6eba926c274d8fd0, []int{1} +} +func (m *DeferredInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DeferredInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DeferredInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DeferredInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeferredInfo.Merge(m, src) +} +func (m *DeferredInfo) XXX_Size() int { + return m.Size() +} +func (m *DeferredInfo) XXX_DiscardUnknown() { + xxx_messageInfo_DeferredInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_DeferredInfo proto.InternalMessageInfo + +func (m *DeferredInfo) GetTxIndex() uint32 { + if m != nil { + return m.TxIndex + } + return 0 +} + +func (m *DeferredInfo) GetTxHash() []byte { + if m != nil { + return m.TxHash + } + return nil +} + +func (m *DeferredInfo) GetTxBloom() []byte { + if m != nil { + return m.TxBloom + } + return nil +} + +func (m *DeferredInfo) GetError() string { + if m != nil { + return m.Error + } + return "" +} + func init() { proto.RegisterType((*Whitelist)(nil), "seiprotocol.seichain.evm.Whitelist") + proto.RegisterType((*DeferredInfo)(nil), "seiprotocol.seichain.evm.DeferredInfo") } func init() { proto.RegisterFile("evm/types.proto", fileDescriptor_6eba926c274d8fd0) } var fileDescriptor_6eba926c274d8fd0 = []byte{ - // 184 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4f, 0x2d, 0xcb, 0xd5, - 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x28, 0x4e, 0xcd, - 0x04, 0xb3, 0x92, 0xf3, 0x73, 0xf4, 0x8a, 0x53, 0x33, 0x93, 0x33, 0x12, 0x33, 0xf3, 0xf4, 0x52, - 0xcb, 0x72, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x52, 0xfa, 0x20, 0x16, 0x44, 0xbd, 0x92, - 0x19, 0x17, 0x67, 0x78, 0x46, 0x66, 0x49, 0x6a, 0x4e, 0x66, 0x71, 0x89, 0x90, 0x26, 0x17, 0x5b, - 0x46, 0x62, 0x71, 0x46, 0x6a, 0xb1, 0x04, 0xa3, 0x02, 0xb3, 0x06, 0xa7, 0x93, 0xe0, 0xa7, 0x7b, - 0xf2, 0xbc, 0x95, 0x89, 0xb9, 0x39, 0x56, 0x4a, 0x10, 0x71, 0xa5, 0x20, 0xa8, 0x02, 0x27, 0xf7, - 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, - 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4d, 0xcf, 0x2c, 0xc9, 0x28, - 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x2f, 0x4e, 0xcd, 0xd4, 0x85, 0xb9, 0x06, 0xcc, 0x01, 0x3b, - 0x47, 0xbf, 0x42, 0x1f, 0xee, 0xec, 0x24, 0x36, 0xb0, 0xbc, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, - 0x04, 0x5a, 0x09, 0xa5, 0xca, 0x00, 0x00, 0x00, + // 325 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0x31, 0x6b, 0xf2, 0x40, + 0x18, 0xc7, 0x73, 0xaf, 0xaf, 0xa6, 0x1e, 0x4a, 0x69, 0x10, 0x7a, 0xed, 0x10, 0x43, 0x86, 0x92, + 0x0e, 0x26, 0x43, 0xa1, 0x43, 0xc7, 0x50, 0xa8, 0xae, 0x59, 0x0a, 0x5d, 0x24, 0xc6, 0x47, 0x73, + 0x34, 0xc9, 0xc9, 0x3d, 0xa7, 0x9c, 0xdf, 0xa2, 0x5f, 0xa8, 0xbb, 0xa3, 0x63, 0xe9, 0x20, 0x45, + 0xbf, 0x41, 0x3f, 0x41, 0x49, 0x8c, 0xa5, 0xd3, 0x3d, 0xbf, 0xfb, 0x3f, 0xff, 0x3b, 0xf8, 0xd1, + 0x73, 0x58, 0xe5, 0x81, 0x5a, 0x2f, 0x00, 0xfd, 0x85, 0x14, 0x4a, 0x58, 0x0c, 0x81, 0x57, 0x53, + 0x22, 0x32, 0x1f, 0x81, 0x27, 0x69, 0xcc, 0x0b, 0x1f, 0x56, 0xf9, 0x75, 0x6f, 0x2e, 0xe6, 0xa2, + 0x8a, 0x82, 0x72, 0x3a, 0xee, 0xbb, 0xf7, 0xb4, 0xfd, 0x9c, 0x72, 0x05, 0x19, 0x47, 0x65, 0xdd, + 0xd2, 0x56, 0x1a, 0x63, 0x0a, 0xc8, 0x88, 0xd3, 0xf0, 0xda, 0xe1, 0xc5, 0xf7, 0xae, 0xdf, 0x5d, + 0xc7, 0x79, 0xf6, 0xe0, 0x1e, 0xef, 0xdd, 0xa8, 0x5e, 0x70, 0xdf, 0x09, 0xed, 0x3c, 0xc2, 0x0c, + 0xa4, 0x84, 0xe9, 0xa8, 0x98, 0x09, 0xeb, 0x8a, 0x9e, 0x29, 0x3d, 0xe6, 0xc5, 0x14, 0x34, 0x23, + 0x0e, 0xf1, 0xba, 0x91, 0xa9, 0xf4, 0xa8, 0x44, 0xeb, 0x92, 0x9a, 0x4a, 0x8f, 0xcb, 0x22, 0xfb, + 0xe7, 0x10, 0xaf, 0x13, 0xb5, 0x94, 0x1e, 0xc6, 0x98, 0xd6, 0x9d, 0x49, 0x26, 0x44, 0xce, 0x1a, + 0x55, 0x62, 0x2a, 0x1d, 0x96, 0x68, 0x0d, 0xa9, 0x89, 0x4b, 0xb9, 0xc8, 0x96, 0xc8, 0xfe, 0x3b, + 0xc4, 0x6b, 0x87, 0xfe, 0x66, 0xd7, 0x37, 0x3e, 0x77, 0xfd, 0x9b, 0x39, 0x57, 0xe9, 0x72, 0xe2, + 0x27, 0x22, 0x0f, 0x12, 0x81, 0xb9, 0xc0, 0xfa, 0x18, 0xe0, 0xf4, 0xb5, 0x56, 0x31, 0x2a, 0x54, + 0x74, 0xaa, 0x5b, 0x3d, 0xda, 0x04, 0x29, 0x85, 0x64, 0xcd, 0xf2, 0x9d, 0xe8, 0x08, 0xe1, 0xd3, + 0x66, 0x6f, 0x93, 0xed, 0xde, 0x26, 0x5f, 0x7b, 0x9b, 0xbc, 0x1d, 0x6c, 0x63, 0x7b, 0xb0, 0x8d, + 0x8f, 0x83, 0x6d, 0xbc, 0x0c, 0xfe, 0x7c, 0x80, 0xc0, 0x07, 0x27, 0x9b, 0x15, 0x54, 0x3a, 0x03, + 0x1d, 0xfc, 0x6a, 0x9f, 0xb4, 0xaa, 0xfc, 0xee, 0x27, 0x00, 0x00, 0xff, 0xff, 0xc8, 0xbe, 0x17, + 0x45, 0x8a, 0x01, 0x00, 0x00, } func (m *Whitelist) Marshal() (dAtA []byte, err error) { @@ -121,6 +201,65 @@ func (m *Whitelist) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *DeferredInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DeferredInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DeferredInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Error) > 0 { + i -= len(m.Error) + copy(dAtA[i:], m.Error) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Error))) + i-- + dAtA[i] = 0x2a + } + { + size := m.Surplus.Size() + i -= size + if _, err := m.Surplus.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.TxBloom) > 0 { + i -= len(m.TxBloom) + copy(dAtA[i:], m.TxBloom) + i = encodeVarintTypes(dAtA, i, uint64(len(m.TxBloom))) + i-- + dAtA[i] = 0x1a + } + if len(m.TxHash) > 0 { + i -= len(m.TxHash) + copy(dAtA[i:], m.TxHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.TxHash))) + i-- + dAtA[i] = 0x12 + } + if m.TxIndex != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.TxIndex)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { offset -= sovTypes(v) base := offset @@ -147,6 +286,32 @@ func (m *Whitelist) Size() (n int) { return n } +func (m *DeferredInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.TxIndex != 0 { + n += 1 + sovTypes(uint64(m.TxIndex)) + } + l = len(m.TxHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.TxBloom) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Surplus.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.Error) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + func sovTypes(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -235,6 +400,209 @@ func (m *Whitelist) Unmarshal(dAtA []byte) error { } return nil } +func (m *DeferredInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DeferredInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DeferredInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TxIndex", wireType) + } + m.TxIndex = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TxIndex |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TxHash = append(m.TxHash[:0], dAtA[iNdEx:postIndex]...) + if m.TxHash == nil { + m.TxHash = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxBloom", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TxBloom = append(m.TxBloom[:0], dAtA[iNdEx:postIndex]...) + if m.TxBloom == nil { + m.TxBloom = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Surplus", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Surplus.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTypes(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0