From 90d53e6f447570e2fdc7ef27b33c8e42fb002c52 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Fri, 21 Jun 2024 17:03:59 -0400 Subject: [PATCH 01/26] add transient receipts --- app/app.go | 13 +++++++--- go.mod | 2 +- go.sum | 4 +-- x/evm/keeper/keeper.go | 11 +++++--- x/evm/keeper/msg_server.go | 2 +- x/evm/keeper/receipt.go | 51 +++++++++++++++++++++++++++++++++----- x/evm/module.go | 2 +- x/evm/types/keys.go | 4 +++ 8 files changed, 71 insertions(+), 18 deletions(-) diff --git a/app/app.go b/app/app.go index e65a1038fe..844f21ce08 100644 --- a/app/app.go +++ b/app/app.go @@ -407,6 +407,7 @@ func New( interfaceRegistry := encodingConfig.InterfaceRegistry bAppOptions := SetupSeiDB(logger, homePath, appOpts, baseAppOptions) + bApp := baseapp.NewBaseApp(AppName, logger, db, encodingConfig.TxConfig.TxDecoder(), tmConfig, appOpts, bAppOptions...) bApp.SetCommitMultiStoreTracer(traceStore) bApp.SetVersion(version.Version) @@ -423,7 +424,7 @@ func New( tokenfactorytypes.StoreKey, // this line is used by starport scaffolding # stargate/app/storeKey ) - tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) + tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey, dexmoduletypes.MemStoreKey, banktypes.DeferredCacheStoreKey, evmtypes.MemStoreKey, oracletypes.MemStoreKey) app := &App{ @@ -597,8 +598,14 @@ func New( ) app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey], - app.GetSubspace(evmtypes.ModuleName), app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper, - app.TransferKeeper, wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper), &app.WasmKeeper) + tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), app.BankKeeper, + &app.AccountKeeper, &app.StakingKeeper, app.TransferKeeper, + wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper), &app.WasmKeeper) + + bApp.SetPreCommitHandler(func(ctx sdk.Context) error { + return app.EvmKeeper.FlushTransientReceipts(ctx) + }) + app.evmRPCConfig, err = evmrpc.ReadConfig(appOpts) if err != nil { panic(fmt.Sprintf("error reading EVM config due to %s", err)) diff --git a/go.mod b/go.mod index 60712c4180..6491967863 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.1.5 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.19 + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.20-0.20240621204049-6dc0c7f906b2 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-22 diff --git a/go.sum b/go.sum index 324467253c..933168cb12 100644 --- a/go.sum +++ b/go.sum @@ -1347,8 +1347,8 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-22 h1:t/m1qXER+DEMrcpqgoYmUxifkA github.com/sei-protocol/go-ethereum v1.13.5-sei-22/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA= github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= -github.com/sei-protocol/sei-cosmos v0.3.19 h1:EQZ+i0virWhmE6XY4w9Dc4tYhVOdZos6Gl9qU39eMGU= -github.com/sei-protocol/sei-cosmos v0.3.19/go.mod h1:rWb90yP2YTqF3CxcdcMvxHYsdLihTNMA5wZi7FwtaeI= +github.com/sei-protocol/sei-cosmos v0.3.20-0.20240621204049-6dc0c7f906b2 h1:oIEZVUucXZEe7Ej9y0vPPTXfrjZmERSTVyuV240keag= +github.com/sei-protocol/sei-cosmos v0.3.20-0.20240621204049-6dc0c7f906b2/go.mod h1:rWb90yP2YTqF3CxcdcMvxHYsdLihTNMA5wZi7FwtaeI= github.com/sei-protocol/sei-db v0.0.38 h1:GiQl3qBd6XgGsHkJd4I8GnOmGjGoWQg3SJAS82TTNao= github.com/sei-protocol/sei-db v0.0.38/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE= diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 1bc21c2dd6..c9159b1c4d 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -42,9 +42,11 @@ import ( ) type Keeper struct { - storeKey sdk.StoreKey - memStoreKey sdk.StoreKey - Paramstore paramtypes.Subspace + storeKey sdk.StoreKey + memStoreKey sdk.StoreKey + transientStoreKey sdk.StoreKey + + Paramstore paramtypes.Subspace deferredInfo *sync.Map txResults []*abci.ExecTxResult @@ -116,7 +118,7 @@ func (ctx *ReplayChainContext) GetHeader(hash common.Hash, number uint64) *ethty } func NewKeeper( - storeKey sdk.StoreKey, memStoreKey sdk.StoreKey, paramstore paramtypes.Subspace, + storeKey sdk.StoreKey, memStoreKey sdk.StoreKey, transientStoreKey sdk.StoreKey, paramstore paramtypes.Subspace, bankKeeper bankkeeper.Keeper, accountKeeper *authkeeper.AccountKeeper, stakingKeeper *stakingkeeper.Keeper, transferKeeper ibctransferkeeper.Keeper, wasmKeeper *wasmkeeper.PermissionedKeeper, wasmViewKeeper *wasmkeeper.Keeper) *Keeper { if !paramstore.HasKeyTable() { @@ -125,6 +127,7 @@ func NewKeeper( k := &Keeper{ storeKey: storeKey, memStoreKey: memStoreKey, + transientStoreKey: transientStoreKey, Paramstore: paramstore, bankKeeper: bankKeeper, accountKeeper: accountKeeper, diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index 2ec76736e2..1ee18a7d3b 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -254,7 +254,7 @@ func (server msgServer) writeReceipt(ctx sdk.Context, origMsg *types.MsgEVMTrans receipt.From = origMsg.Derived.SenderEVMAddr.Hex() - return receipt, server.SetReceipt(ctx, tx.Hash(), receipt) + return receipt, server.SetTransientReceipt(ctx, tx.Hash(), receipt) } func (server msgServer) Send(goCtx context.Context, msg *types.MsgSend) (*types.MsgSendResponse, error) { diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 43e6c93880..1bd0e937a5 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -2,28 +2,53 @@ package keeper import ( "errors" - + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" "github.com/sei-protocol/sei-chain/x/evm/types" ) -// Receipt is a data structure that stores EVM specific transaction metadata. +// SetTransientReceipt sets a data structure that stores EVM specific transaction metadata. +func (k *Keeper) SetTransientReceipt(ctx sdk.Context, txHash common.Hash, receipt *types.Receipt) error { + store := ctx.TransientStore(k.transientStoreKey) + bz, err := receipt.Marshal() + if err != nil { + return err + } + store.Set(types.ReceiptKey(txHash), bz) + return nil +} + +// GetReceipt returns a data structure that stores EVM specific transaction metadata. // Many EVM applications (e.g. MetaMask) relies on being on able to query receipt // by EVM transaction hash (not Sei transaction hash) to function properly. func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt, error) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.ReceiptKey(txHash)) + bz, err := ctx.EvmReceiptStateStore().Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) + if err != nil { + return nil, err + } + if bz == nil { - return nil, errors.New("not found") + // fallback because these used to exist in application state + store := ctx.KVStore(k.storeKey) + bz = store.Get(types.ReceiptKey(txHash)) + if bz == nil { + return nil, errors.New("not found") + } } - r := types.Receipt{} + + var r types.Receipt if err := r.Unmarshal(bz); err != nil { return nil, err } return &r, nil } +// SetReceipt sets a data structure that stores EVM specific transaction metadata. +// +// Deprecated: in favor of SetTransientReceipt +// this is currently used by a number of tests to set receipts at the moment +// TODO: remove this once we move off of SetReceipt (tests are using it) func (k *Keeper) SetReceipt(ctx sdk.Context, txHash common.Hash, receipt *types.Receipt) error { store := ctx.KVStore(k.storeKey) bz, err := receipt.Marshal() @@ -33,3 +58,17 @@ func (k *Keeper) SetReceipt(ctx sdk.Context, txHash common.Hash, receipt *types. store.Set(types.ReceiptKey(txHash), bz) return nil } + +func (k *Keeper) FlushTransientReceipts(ctx sdk.Context) error { + //TODO implement flush receipts + //receiptStore := ctx.EvmReceiptStateStore() + iter := prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.ReceiptKeyPrefix).Iterator(nil, nil) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + //txHash := common.BytesToHash(iter.Key()) + //bz := iter.Value() + // TODO: write this tx to store to receiptStore + // Make sure the key aligns with GetReceipt ^ + } + return ctx.TransientStore(k.transientStoreKey).DeleteAll(nil, nil) +} diff --git a/x/evm/module.go b/x/evm/module.go index 0fa5a2d8a1..9f6209c797 100644 --- a/x/evm/module.go +++ b/x/evm/module.go @@ -230,7 +230,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val surplus := am.keeper.GetAnteSurplusSum(ctx) for _, deferredInfo := range evmTxDeferredInfoList { if deferredInfo.Error != "" && deferredInfo.TxHash.Cmp(ethtypes.EmptyTxsHash) != 0 { - _ = am.keeper.SetReceipt(ctx, deferredInfo.TxHash, &types.Receipt{ + _ = am.keeper.SetTransientReceipt(ctx, deferredInfo.TxHash, &types.Receipt{ TxHashHex: deferredInfo.TxHash.Hex(), TransactionIndex: uint32(deferredInfo.TxIndx), VmError: deferredInfo.Error, diff --git a/x/evm/types/keys.go b/x/evm/types/keys.go index 70bd371192..946cf78947 100644 --- a/x/evm/types/keys.go +++ b/x/evm/types/keys.go @@ -18,6 +18,10 @@ const ( MemStoreKey = "evm_mem" + TransientStoreKey = "evm_transient" + + ReceiptStoreKey = "receipt" + // QuerierRoute is the querier route for auth QuerierRoute = ModuleName ) From 1c6dfc9cab0317d3fc5f65245013e7acab609b86 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Tue, 25 Jun 2024 13:05:45 -0400 Subject: [PATCH 02/26] add state store to keeper --- app/app.go | 33 +++++++++++++++++---------------- x/evm/keeper/keeper.go | 6 +++++- x/evm/keeper/receipt.go | 9 +++++---- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/app/app.go b/app/app.go index 844f21ce08..a136b5555c 100644 --- a/app/app.go +++ b/app/app.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "encoding/json" "fmt" + seidbtypes "github.com/sei-protocol/sei-db/ss/types" "io" "net/http" "os" @@ -26,14 +27,6 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" - "github.com/sei-protocol/sei-chain/aclmapping" - aclutils "github.com/sei-protocol/sei-chain/aclmapping/utils" - appparams "github.com/sei-protocol/sei-chain/app/params" - "github.com/sei-protocol/sei-chain/app/upgrades" - v0upgrade "github.com/sei-protocol/sei-chain/app/upgrades/v0" - "github.com/sei-protocol/sei-chain/utils" - "github.com/sei-protocol/sei-chain/wasmbinding" - wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" @@ -47,20 +40,16 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" sdkacltypes "github.com/cosmos/cosmos-sdk/types/accesscontrol" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/ante" - "github.com/cosmos/cosmos-sdk/x/authz" - authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" - authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" aclmodule "github.com/cosmos/cosmos-sdk/x/accesscontrol" aclclient "github.com/cosmos/cosmos-sdk/x/accesscontrol/client" aclconstants "github.com/cosmos/cosmos-sdk/x/accesscontrol/constants" aclkeeper "github.com/cosmos/cosmos-sdk/x/accesscontrol/keeper" acltypes "github.com/cosmos/cosmos-sdk/x/accesscontrol/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/ante" authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" @@ -68,6 +57,9 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/cosmos/cosmos-sdk/x/authz" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -118,6 +110,13 @@ import ( ibcporttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper" + "github.com/sei-protocol/sei-chain/aclmapping" + aclutils "github.com/sei-protocol/sei-chain/aclmapping/utils" + appparams "github.com/sei-protocol/sei-chain/app/params" + "github.com/sei-protocol/sei-chain/app/upgrades" + v0upgrade "github.com/sei-protocol/sei-chain/app/upgrades/v0" + "github.com/sei-protocol/sei-chain/utils" + "github.com/sei-protocol/sei-chain/wasmbinding" "github.com/sei-protocol/sei-chain/x/mint" mintclient "github.com/sei-protocol/sei-chain/x/mint/client/cli" mintkeeper "github.com/sei-protocol/sei-chain/x/mint/keeper" @@ -597,8 +596,10 @@ func New( wasmOpts..., ) + //TODO: create state store + var receiptStore seidbtypes.StateStore app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey], - tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), app.BankKeeper, + tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), receiptStore, app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper, app.TransferKeeper, wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper), &app.WasmKeeper) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index c9159b1c4d..f361ba890a 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/tests" + seidbtypes "github.com/sei-protocol/sei-db/ss/types" abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" @@ -79,6 +80,8 @@ type Keeper struct { DB ethstate.Database Root common.Hash ReplayBlock *ethtypes.Block + + receiptStore seidbtypes.StateStore } type EvmTxDeferredInfo struct { @@ -118,7 +121,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, + storeKey sdk.StoreKey, memStoreKey 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() { @@ -140,6 +143,7 @@ func NewKeeper( cachedFeeCollectorAddressMtx: &sync.RWMutex{}, keyToNonce: make(map[tmtypes.TxKey]*AddressNoncePair), deferredInfo: &sync.Map{}, + receiptStore: receiptStateStore, } return k } diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 1bd0e937a5..2a498ff682 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -60,15 +60,16 @@ func (k *Keeper) SetReceipt(ctx sdk.Context, txHash common.Hash, receipt *types. } func (k *Keeper) FlushTransientReceipts(ctx sdk.Context) error { - //TODO implement flush receipts - //receiptStore := ctx.EvmReceiptStateStore() iter := prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.ReceiptKeyPrefix).Iterator(nil, nil) defer iter.Close() for ; iter.Valid(); iter.Next() { + // TODO: write this tx to store to receiptStore + //txHash := common.BytesToHash(iter.Key()) //bz := iter.Value() - // TODO: write this tx to store to receiptStore - // Make sure the key aligns with GetReceipt ^ + //k.receiptStore.ApplyChangeset(...) } + + //TODO: we may not actually need this if transient stores are auto-cleared, we'll need to verify return ctx.TransientStore(k.transientStoreKey).DeleteAll(nil, nil) } From 289434b6ff717ef35f2e60cdc3cf5f6f08535e75 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Tue, 25 Jun 2024 13:08:07 -0400 Subject: [PATCH 03/26] avoid using ctx evm store --- x/evm/keeper/receipt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 2a498ff682..755c34ce21 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -23,7 +23,7 @@ func (k *Keeper) SetTransientReceipt(ctx sdk.Context, txHash common.Hash, receip // Many EVM applications (e.g. MetaMask) relies on being on able to query receipt // by EVM transaction hash (not Sei transaction hash) to function properly. func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt, error) { - bz, err := ctx.EvmReceiptStateStore().Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) + bz, err := k.receiptStore.Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) if err != nil { return nil, err } From 7bde4f7e942e7f99b376dff453efcbd553b8a453 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Tue, 25 Jun 2024 14:01:53 -0400 Subject: [PATCH 04/26] goimports --- app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index a136b5555c..a11d5993e5 100644 --- a/app/app.go +++ b/app/app.go @@ -6,7 +6,6 @@ import ( "crypto/sha256" "encoding/json" "fmt" - seidbtypes "github.com/sei-protocol/sei-db/ss/types" "io" "net/http" "os" @@ -121,6 +120,7 @@ import ( mintclient "github.com/sei-protocol/sei-chain/x/mint/client/cli" mintkeeper "github.com/sei-protocol/sei-chain/x/mint/keeper" minttypes "github.com/sei-protocol/sei-chain/x/mint/types" + seidbtypes "github.com/sei-protocol/sei-db/ss/types" "github.com/sei-protocol/sei-chain/x/evm" evmante "github.com/sei-protocol/sei-chain/x/evm/ante" From 7bf55e95d354b0cc547a0514e1e2a5a0a5f81227 Mon Sep 17 00:00:00 2001 From: yzang2019 Date: Tue, 25 Jun 2024 11:28:18 -0700 Subject: [PATCH 05/26] Merge conflicts --- app/app.go | 22 ++++++++++++++-------- go.mod | 2 +- go.sum | 4 ++-- x/evm/keeper/receipt.go | 20 +++++++++++++++----- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/app/app.go b/app/app.go index a11d5993e5..c4a2e4fc70 100644 --- a/app/app.go +++ b/app/app.go @@ -14,8 +14,10 @@ import ( "sync" "time" + "github.com/cosmos/cosmos-sdk/server" "github.com/gorilla/mux" "github.com/rakyll/statik/fs" + "github.com/sei-protocol/sei-db/ss" "github.com/ethereum/go-ethereum/ethclient" ethrpc "github.com/ethereum/go-ethereum/rpc" @@ -116,12 +118,6 @@ import ( v0upgrade "github.com/sei-protocol/sei-chain/app/upgrades/v0" "github.com/sei-protocol/sei-chain/utils" "github.com/sei-protocol/sei-chain/wasmbinding" - "github.com/sei-protocol/sei-chain/x/mint" - mintclient "github.com/sei-protocol/sei-chain/x/mint/client/cli" - mintkeeper "github.com/sei-protocol/sei-chain/x/mint/keeper" - minttypes "github.com/sei-protocol/sei-chain/x/mint/types" - seidbtypes "github.com/sei-protocol/sei-db/ss/types" - "github.com/sei-protocol/sei-chain/x/evm" evmante "github.com/sei-protocol/sei-chain/x/evm/ante" "github.com/sei-protocol/sei-chain/x/evm/blocktest" @@ -129,6 +125,10 @@ import ( "github.com/sei-protocol/sei-chain/x/evm/querier" "github.com/sei-protocol/sei-chain/x/evm/replay" evmtypes "github.com/sei-protocol/sei-chain/x/evm/types" + "github.com/sei-protocol/sei-chain/x/mint" + mintclient "github.com/sei-protocol/sei-chain/x/mint/client/cli" + mintkeeper "github.com/sei-protocol/sei-chain/x/mint/keeper" + minttypes "github.com/sei-protocol/sei-chain/x/mint/types" "github.com/spf13/cast" abci "github.com/tendermint/tendermint/abci/types" tmcfg "github.com/tendermint/tendermint/config" @@ -165,6 +165,8 @@ import ( // unnamed import of statik for openapi/swagger UI support _ "github.com/sei-protocol/sei-chain/docs/swagger" + + ssconfig "github.com/sei-protocol/sei-db/config" ) // this line is used by starport scaffolding # stargate/wasm/app/enabledProposals @@ -596,8 +598,12 @@ func New( wasmOpts..., ) - //TODO: create state store - var receiptStore seidbtypes.StateStore + receiptStorePath := filepath.Join(homePath, "data", "receipt.db") + receiptStore, err := ss.NewStateStore(logger, receiptStorePath, ssconfig.StateStoreConfig{ + DedicatedChangelog: true, + AsyncWriteBuffer: 10, + KeepRecent: cast.ToInt(appOpts.Get(server.FlagMinRetainBlocks)), + }) app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey], tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), receiptStore, app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper, app.TransferKeeper, diff --git a/go.mod b/go.mod index 6491967863..7927ea3fc7 100644 --- a/go.mod +++ b/go.mod @@ -351,7 +351,7 @@ replace ( github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-22 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.38 + github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed // Latest goleveldb is broken, we have to stick to this version github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/tendermint/tendermint => github.com/sei-protocol/sei-tendermint v0.3.3 diff --git a/go.sum b/go.sum index 933168cb12..00a4ac9d2a 100644 --- a/go.sum +++ b/go.sum @@ -1349,8 +1349,8 @@ github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQp github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= github.com/sei-protocol/sei-cosmos v0.3.20-0.20240621204049-6dc0c7f906b2 h1:oIEZVUucXZEe7Ej9y0vPPTXfrjZmERSTVyuV240keag= github.com/sei-protocol/sei-cosmos v0.3.20-0.20240621204049-6dc0c7f906b2/go.mod h1:rWb90yP2YTqF3CxcdcMvxHYsdLihTNMA5wZi7FwtaeI= -github.com/sei-protocol/sei-db v0.0.38 h1:GiQl3qBd6XgGsHkJd4I8GnOmGjGoWQg3SJAS82TTNao= -github.com/sei-protocol/sei-db v0.0.38/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= +github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed h1:h7RO/5AvVNBoGReLsVjcKuNU24liR5nKmQZ9zhM2/Do= +github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE= github.com/sei-protocol/sei-iavl v0.1.9/go.mod h1:7PfkEVT5dcoQE+s/9KWdoXJ8VVVP1QpYYPLdxlkSXFk= github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 h1:BPG9LWe27x3SATpY9nj8JPe+0igyKyrcpB0z2ZvdcXQ= diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 755c34ce21..e7fea13c39 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -4,8 +4,10 @@ import ( "errors" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/iavl" "github.com/ethereum/go-ethereum/common" "github.com/sei-protocol/sei-chain/x/evm/types" + "github.com/sei-protocol/sei-db/proto" ) // SetTransientReceipt sets a data structure that stores EVM specific transaction metadata. @@ -62,12 +64,20 @@ func (k *Keeper) SetReceipt(ctx sdk.Context, txHash common.Hash, receipt *types. func (k *Keeper) FlushTransientReceipts(ctx sdk.Context) error { iter := prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.ReceiptKeyPrefix).Iterator(nil, nil) defer iter.Close() + var pairs []*iavl.KVPair + var changesets []*proto.NamedChangeSet for ; iter.Valid(); iter.Next() { - // TODO: write this tx to store to receiptStore - - //txHash := common.BytesToHash(iter.Key()) - //bz := iter.Value() - //k.receiptStore.ApplyChangeset(...) + kvPair := &iavl.KVPair{Key: iter.Key(), Value: iter.Value()} + pairs = append(pairs, kvPair) + } + ncs := &proto.NamedChangeSet{ + Name: types.ReceiptStoreKey, + Changeset: iavl.ChangeSet{Pairs: pairs}, + } + changesets = append(changesets, ncs) + err := k.receiptStore.ApplyChangesetAsync(ctx.BlockHeight(), changesets) + if err != nil { + return err } //TODO: we may not actually need this if transient stores are auto-cleared, we'll need to verify From 3ba4688f28f75b5a83e4f0a534d9a3ba331e9a5e Mon Sep 17 00:00:00 2001 From: yzang2019 Date: Tue, 25 Jun 2024 11:49:37 -0700 Subject: [PATCH 06/26] Update cosmos --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7927ea3fc7..04b285aef3 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.1.5 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.20-0.20240621204049-6dc0c7f906b2 + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625184415-25b139ecc98a github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-22 diff --git a/go.sum b/go.sum index 00a4ac9d2a..00b51a18c9 100644 --- a/go.sum +++ b/go.sum @@ -1347,8 +1347,8 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-22 h1:t/m1qXER+DEMrcpqgoYmUxifkA github.com/sei-protocol/go-ethereum v1.13.5-sei-22/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA= github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= -github.com/sei-protocol/sei-cosmos v0.3.20-0.20240621204049-6dc0c7f906b2 h1:oIEZVUucXZEe7Ej9y0vPPTXfrjZmERSTVyuV240keag= -github.com/sei-protocol/sei-cosmos v0.3.20-0.20240621204049-6dc0c7f906b2/go.mod h1:rWb90yP2YTqF3CxcdcMvxHYsdLihTNMA5wZi7FwtaeI= +github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625184415-25b139ecc98a h1:t/KHLSlgsgQ4c+6iRal+3vApSVp9ucErHY3bE+MJkTs= +github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625184415-25b139ecc98a/go.mod h1:Lvn+ea+ThIDZgQno5I2qNjAUJu5DaNSePKOqfU4CvPc= github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed h1:h7RO/5AvVNBoGReLsVjcKuNU24liR5nKmQZ9zhM2/Do= github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE= From 98385e5f5c704ee99f5dc5872be0c69b12d67814 Mon Sep 17 00:00:00 2001 From: yzang2019 Date: Tue, 25 Jun 2024 13:06:49 -0700 Subject: [PATCH 07/26] Add backend --- app/app.go | 1 + 1 file changed, 1 insertion(+) diff --git a/app/app.go b/app/app.go index c4a2e4fc70..4702b5811e 100644 --- a/app/app.go +++ b/app/app.go @@ -603,6 +603,7 @@ func New( DedicatedChangelog: true, AsyncWriteBuffer: 10, KeepRecent: cast.ToInt(appOpts.Get(server.FlagMinRetainBlocks)), + Backend: string(ss.PebbleDBBackend), }) app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey], tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), receiptStore, app.BankKeeper, From e514541d9ac7823424a9cdc77d6ee552365e0be7 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Tue, 25 Jun 2024 16:28:45 -0400 Subject: [PATCH 08/26] add close function --- app/app.go | 28 +++++++++++++++++++++++----- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/app/app.go b/app/app.go index 4702b5811e..ee1d471f4b 100644 --- a/app/app.go +++ b/app/app.go @@ -129,6 +129,7 @@ import ( mintclient "github.com/sei-protocol/sei-chain/x/mint/client/cli" mintkeeper "github.com/sei-protocol/sei-chain/x/mint/keeper" minttypes "github.com/sei-protocol/sei-chain/x/mint/types" + seidb "github.com/sei-protocol/sei-db/ss/types" "github.com/spf13/cast" abci "github.com/tendermint/tendermint/abci/types" tmcfg "github.com/tendermint/tendermint/config" @@ -383,6 +384,8 @@ type App struct { encodingConfig appparams.EncodingConfig evmRPCConfig evmrpc.Config lightInvarianceConfig LightInvarianceConfig + + receiptStore seidb.StateStore } // New returns a reference to an initialized blockchain app @@ -599,20 +602,22 @@ func New( ) receiptStorePath := filepath.Join(homePath, "data", "receipt.db") - receiptStore, err := ss.NewStateStore(logger, receiptStorePath, ssconfig.StateStoreConfig{ + app.receiptStore, err = ss.NewStateStore(logger, receiptStorePath, ssconfig.StateStoreConfig{ DedicatedChangelog: true, AsyncWriteBuffer: 10, KeepRecent: cast.ToInt(appOpts.Get(server.FlagMinRetainBlocks)), Backend: string(ss.PebbleDBBackend), }) + if err != nil { + panic(fmt.Sprintf("error while creating receipt store: %s", err)) + } app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey], - tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), receiptStore, app.BankKeeper, + tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), app.receiptStore, app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper, app.TransferKeeper, wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper), &app.WasmKeeper) - bApp.SetPreCommitHandler(func(ctx sdk.Context) error { - return app.EvmKeeper.FlushTransientReceipts(ctx) - }) + bApp.SetPreCommitHandler(app.HandlePreCommit) + bApp.SetCloseHandler(app.Close) app.evmRPCConfig, err = evmrpc.ReadConfig(appOpts) if err != nil { @@ -985,6 +990,19 @@ func New( return app } +// HandlePreCommit happens right before the block is committed +func (app *App) HandlePreCommit(ctx sdk.Context) error { + return app.EvmKeeper.FlushTransientReceipts(ctx) +} + +// Close closes all items that needs closing (called by baseapp) +func (app *App) Close() error { + if app.receiptStore != nil { + return app.receiptStore.Close() + } + return nil +} + // Add (or remove) keepers when they are introduced / removed in different versions func (app *App) SetStoreUpgradeHandlers() { upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() diff --git a/go.mod b/go.mod index 04b285aef3..49b62f2c55 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.1.5 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625184415-25b139ecc98a + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625202439-377fcacf1a97 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-22 diff --git a/go.sum b/go.sum index 00b51a18c9..f9a6fe06bc 100644 --- a/go.sum +++ b/go.sum @@ -1347,8 +1347,8 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-22 h1:t/m1qXER+DEMrcpqgoYmUxifkA github.com/sei-protocol/go-ethereum v1.13.5-sei-22/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA= github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= -github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625184415-25b139ecc98a h1:t/KHLSlgsgQ4c+6iRal+3vApSVp9ucErHY3bE+MJkTs= -github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625184415-25b139ecc98a/go.mod h1:Lvn+ea+ThIDZgQno5I2qNjAUJu5DaNSePKOqfU4CvPc= +github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625202439-377fcacf1a97 h1:YiqZHQ5DdLYup34WPcQ9W2wH3Mc9FJg+DkODCBRrtiM= +github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625202439-377fcacf1a97/go.mod h1:Lvn+ea+ThIDZgQno5I2qNjAUJu5DaNSePKOqfU4CvPc= github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed h1:h7RO/5AvVNBoGReLsVjcKuNU24liR5nKmQZ9zhM2/Do= github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE= From 8c7e16c0f2e66ff237be7d1c941e70889d0638d8 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Tue, 25 Jun 2024 17:26:25 -0400 Subject: [PATCH 09/26] add debug lines --- x/evm/keeper/receipt.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index e7fea13c39..8ab90d7a89 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -25,12 +25,20 @@ func (k *Keeper) SetTransientReceipt(ctx sdk.Context, txHash common.Hash, receip // Many EVM applications (e.g. MetaMask) relies on being on able to query receipt // by EVM transaction hash (not Sei transaction hash) to function properly. func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt, error) { - bz, err := k.receiptStore.Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) + ctx.Logger().Info("[Debug] GetReceipt START", "tx", txHash.Hex()) + v, err := k.receiptStore.GetLatestVersion() + if err != nil { + return nil, err + } + bz, err := k.receiptStore.Get(types.ReceiptStoreKey, v, types.ReceiptKey(txHash)) + ctx.Logger().Info("[Debug] GetReceipt DONE", "tx", txHash.Hex()) if err != nil { return nil, err } if bz == nil { + ctx.Logger().Info("[Debug] GetReceipt NOT FOUND", "tx", txHash.Hex()) + // fallback because these used to exist in application state store := ctx.KVStore(k.storeKey) bz = store.Get(types.ReceiptKey(txHash)) @@ -62,14 +70,19 @@ func (k *Keeper) SetReceipt(ctx sdk.Context, txHash common.Hash, receipt *types. } func (k *Keeper) FlushTransientReceipts(ctx sdk.Context) error { + ctx.Logger().Info("[Debug] Flushing transient receipts") iter := prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.ReceiptKeyPrefix).Iterator(nil, nil) defer iter.Close() var pairs []*iavl.KVPair var changesets []*proto.NamedChangeSet for ; iter.Valid(); iter.Next() { + ctx.Logger().Info("[Debug] FlushTransientReceipts", "tx", common.BytesToHash(iter.Key()).Hex()) kvPair := &iavl.KVPair{Key: iter.Key(), Value: iter.Value()} pairs = append(pairs, kvPair) } + if len(pairs) == 0 { + return nil + } ncs := &proto.NamedChangeSet{ Name: types.ReceiptStoreKey, Changeset: iavl.ChangeSet{Pairs: pairs}, From f1b7bf3566d21ff0017857795b06567cb91a463f Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Tue, 25 Jun 2024 19:45:34 -0400 Subject: [PATCH 10/26] include prefix on write --- x/evm/keeper/receipt.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 8ab90d7a89..c4b48635cf 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -2,7 +2,7 @@ package keeper import ( "errors" - "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/iavl" "github.com/ethereum/go-ethereum/common" @@ -70,13 +70,11 @@ func (k *Keeper) SetReceipt(ctx sdk.Context, txHash common.Hash, receipt *types. } func (k *Keeper) FlushTransientReceipts(ctx sdk.Context) error { - ctx.Logger().Info("[Debug] Flushing transient receipts") - iter := prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.ReceiptKeyPrefix).Iterator(nil, nil) + iter := ctx.TransientStore(k.transientStoreKey).Iterator(nil, nil) defer iter.Close() var pairs []*iavl.KVPair var changesets []*proto.NamedChangeSet for ; iter.Valid(); iter.Next() { - ctx.Logger().Info("[Debug] FlushTransientReceipts", "tx", common.BytesToHash(iter.Key()).Hex()) kvPair := &iavl.KVPair{Key: iter.Key(), Value: iter.Value()} pairs = append(pairs, kvPair) } From c05acee820c1422734be14e9fe8263e517616235 Mon Sep 17 00:00:00 2001 From: yzang2019 Date: Tue, 25 Jun 2024 17:03:09 -0700 Subject: [PATCH 11/26] Fix initialization logic --- app/app.go | 11 +++++------ docker/localnode/Dockerfile | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/app.go b/app/app.go index ee1d471f4b..dcf2ea6b91 100644 --- a/app/app.go +++ b/app/app.go @@ -602,12 +602,11 @@ func New( ) receiptStorePath := filepath.Join(homePath, "data", "receipt.db") - app.receiptStore, err = ss.NewStateStore(logger, receiptStorePath, ssconfig.StateStoreConfig{ - DedicatedChangelog: true, - AsyncWriteBuffer: 10, - KeepRecent: cast.ToInt(appOpts.Get(server.FlagMinRetainBlocks)), - Backend: string(ss.PebbleDBBackend), - }) + ssConfig := ssconfig.DefaultStateStoreConfig() + ssConfig.DedicatedChangelog = true + ssConfig.KeepRecent = cast.ToInt(appOpts.Get(server.FlagMinRetainBlocks)) + ssConfig.DBDirectory = receiptStorePath + app.receiptStore, err = ss.NewStateStore(logger, receiptStorePath, ssConfig) if err != nil { panic(fmt.Sprintf("error while creating receipt store: %s", err)) } diff --git a/docker/localnode/Dockerfile b/docker/localnode/Dockerfile index 49283c86d3..ca705b2b61 100644 --- a/docker/localnode/Dockerfile +++ b/docker/localnode/Dockerfile @@ -2,8 +2,8 @@ FROM ubuntu:latest RUN apt-get update && \ apt-get install -y make git wget build-essential jq python3 curl vim uuid-runtime RUN rm -rf build/generated -RUN wget https://go.dev/dl/go1.21.4.linux-amd64.tar.gz -RUN tar -xvf go1.21.4.linux-amd64.tar.gz +RUN wget https://go.dev/dl/go1.22.4.linux-amd64.tar.gz +RUN tar -xvf go1.22.4.linux-amd64.tar.gz RUN mv go /usr/local/ RUN curl -L https://foundry.paradigm.xyz | bash RUN /root/.foundry/bin/foundryup From 744374301907ca4d36e7b049cb221057a2cecc3b Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 10:32:39 -0400 Subject: [PATCH 12/26] rename close to handle close --- app/app.go | 4 ++-- x/evm/keeper/receipt.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/app.go b/app/app.go index dcf2ea6b91..d1ace9a5ff 100644 --- a/app/app.go +++ b/app/app.go @@ -616,7 +616,7 @@ func New( wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper), &app.WasmKeeper) bApp.SetPreCommitHandler(app.HandlePreCommit) - bApp.SetCloseHandler(app.Close) + bApp.SetCloseHandler(app.HandleClose) app.evmRPCConfig, err = evmrpc.ReadConfig(appOpts) if err != nil { @@ -995,7 +995,7 @@ func (app *App) HandlePreCommit(ctx sdk.Context) error { } // Close closes all items that needs closing (called by baseapp) -func (app *App) Close() error { +func (app *App) HandleClose() error { if app.receiptStore != nil { return app.receiptStore.Close() } diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index c4b48635cf..67f2850e5f 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -2,7 +2,7 @@ package keeper import ( "errors" - + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/iavl" "github.com/ethereum/go-ethereum/common" From c847aff389f49253edd96f8f3e6f1276d06f2959 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 10:39:13 -0400 Subject: [PATCH 13/26] remove transient deletion --- x/evm/keeper/receipt.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 67f2850e5f..9ba3ab4e12 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -86,11 +86,6 @@ func (k *Keeper) FlushTransientReceipts(ctx sdk.Context) error { Changeset: iavl.ChangeSet{Pairs: pairs}, } changesets = append(changesets, ncs) - err := k.receiptStore.ApplyChangesetAsync(ctx.BlockHeight(), changesets) - if err != nil { - return err - } - //TODO: we may not actually need this if transient stores are auto-cleared, we'll need to verify - return ctx.TransientStore(k.transientStoreKey).DeleteAll(nil, nil) + return k.receiptStore.ApplyChangesetAsync(ctx.BlockHeight(), changesets) } From ab1b6e060e5557bc85224515a2086c0756370941 Mon Sep 17 00:00:00 2001 From: yzang2019 Date: Wed, 26 Jun 2024 08:27:15 -0700 Subject: [PATCH 14/26] Update seidb version --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 49b62f2c55..ae02c24da9 100644 --- a/go.mod +++ b/go.mod @@ -351,7 +351,7 @@ replace ( github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-22 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed + github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.39 // Latest goleveldb is broken, we have to stick to this version github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/tendermint/tendermint => github.com/sei-protocol/sei-tendermint v0.3.3 diff --git a/go.sum b/go.sum index f9a6fe06bc..b9b90379f1 100644 --- a/go.sum +++ b/go.sum @@ -1349,8 +1349,8 @@ github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQp github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625202439-377fcacf1a97 h1:YiqZHQ5DdLYup34WPcQ9W2wH3Mc9FJg+DkODCBRrtiM= github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625202439-377fcacf1a97/go.mod h1:Lvn+ea+ThIDZgQno5I2qNjAUJu5DaNSePKOqfU4CvPc= -github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed h1:h7RO/5AvVNBoGReLsVjcKuNU24liR5nKmQZ9zhM2/Do= -github.com/sei-protocol/sei-db v0.0.39-0.20240625173036-9959509c36ed/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= +github.com/sei-protocol/sei-db v0.0.39 h1:/XwwlObPhWnX8zH8GDbDvyn+a/K2911HZlmlBZzN+gQ= +github.com/sei-protocol/sei-db v0.0.39/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE= github.com/sei-protocol/sei-iavl v0.1.9/go.mod h1:7PfkEVT5dcoQE+s/9KWdoXJ8VVVP1QpYYPLdxlkSXFk= github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 h1:BPG9LWe27x3SATpY9nj8JPe+0igyKyrcpB0z2ZvdcXQ= From df7363cd633651f3af8f2ae0f66e524f942b1eba Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 13:00:30 -0400 Subject: [PATCH 15/26] update sei-cosmos --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ae02c24da9..681b3e11c5 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.1.5 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625202439-377fcacf1a97 + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.20-0.20240626152810-f14e25c3c39c github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-22 diff --git a/go.sum b/go.sum index b9b90379f1..601b8a5d07 100644 --- a/go.sum +++ b/go.sum @@ -1347,8 +1347,8 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-22 h1:t/m1qXER+DEMrcpqgoYmUxifkA github.com/sei-protocol/go-ethereum v1.13.5-sei-22/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA= github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= -github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625202439-377fcacf1a97 h1:YiqZHQ5DdLYup34WPcQ9W2wH3Mc9FJg+DkODCBRrtiM= -github.com/sei-protocol/sei-cosmos v0.3.20-0.20240625202439-377fcacf1a97/go.mod h1:Lvn+ea+ThIDZgQno5I2qNjAUJu5DaNSePKOqfU4CvPc= +github.com/sei-protocol/sei-cosmos v0.3.20-0.20240626152810-f14e25c3c39c h1:0wM73r6+BIxfNvTr1B+SmLnfWpCyZEAexd2wbMnCoEE= +github.com/sei-protocol/sei-cosmos v0.3.20-0.20240626152810-f14e25c3c39c/go.mod h1:og/KbejR/zSQ8otapODEDU9zYNhFSUDbq9+tgeYePyU= github.com/sei-protocol/sei-db v0.0.39 h1:/XwwlObPhWnX8zH8GDbDvyn+a/K2911HZlmlBZzN+gQ= github.com/sei-protocol/sei-db v0.0.39/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE= From 4127b51999f3dd8dc239d2917f0e45ab4725f2e7 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 13:37:12 -0400 Subject: [PATCH 16/26] add in-memory state store for tests --- app/app.go | 20 ++- app/test_helpers.go | 10 ++ app/test_state_store.go | 314 ++++++++++++++++++++++++++++++++++++ cmd/seid/cmd/blocktest.go | 1 + cmd/seid/cmd/ethreplay.go | 1 + cmd/seid/cmd/root.go | 5 +- testutil/network/network.go | 1 + 7 files changed, 346 insertions(+), 6 deletions(-) create mode 100644 app/test_state_store.go diff --git a/app/app.go b/app/app.go index d1ace9a5ff..ba5f7c1efc 100644 --- a/app/app.go +++ b/app/app.go @@ -266,7 +266,8 @@ var ( // EmptyAclmOpts defines a type alias for a list of wasm options. EmptyACLOpts []aclkeeper.Option // EnableOCC allows tests to override default OCC enablement behavior - EnableOCC = true + EnableOCC = true + EmptyAppOptions []AppOption ) var ( @@ -388,6 +389,8 @@ type App struct { receiptStore seidb.StateStore } +type AppOption func(*App) + // New returns a reference to an initialized blockchain app func New( logger log.Logger, @@ -404,6 +407,7 @@ func New( appOpts servertypes.AppOptions, wasmOpts []wasm.Option, aclOpts []aclkeeper.Option, + appOptions []AppOption, baseAppOptions ...func(*baseapp.BaseApp), ) *App { appCodec := encodingConfig.Marshaler @@ -445,6 +449,11 @@ func New( metricCounter: &map[string]float32{}, encodingConfig: encodingConfig, } + + for _, option := range appOptions { + option(app) + } + app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey]) // set the BaseApp's parameter store @@ -606,10 +615,13 @@ func New( ssConfig.DedicatedChangelog = true ssConfig.KeepRecent = cast.ToInt(appOpts.Get(server.FlagMinRetainBlocks)) ssConfig.DBDirectory = receiptStorePath - app.receiptStore, err = ss.NewStateStore(logger, receiptStorePath, ssConfig) - if err != nil { - panic(fmt.Sprintf("error while creating receipt store: %s", err)) + if app.receiptStore == nil { + app.receiptStore, err = ss.NewStateStore(logger, receiptStorePath, ssConfig) + if err != nil { + panic(fmt.Sprintf("error while creating receipt store: %s", err)) + } } + app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey], tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), app.receiptStore, app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper, app.TransferKeeper, diff --git a/app/test_helpers.go b/app/test_helpers.go index 87b501b749..d6f7916b5d 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -177,6 +177,13 @@ func Setup(isCheckTx bool, enableEVMCustomPrecompiles bool, baseAppOptions ...fu db := dbm.NewMemDB() encodingConfig := MakeEncodingConfig() cdc := encodingConfig.Marshaler + + options := []AppOption{ + func(app *App) { + app.receiptStore = NewInMemoryStateStore() + }, + } + res = New( log.NewNopLogger(), db, @@ -192,6 +199,7 @@ func Setup(isCheckTx bool, enableEVMCustomPrecompiles bool, baseAppOptions ...fu TestAppOpts{}, EmptyWasmOpts, EmptyACLOpts, + options, baseAppOptions..., ) if !isCheckTx { @@ -235,6 +243,7 @@ func SetupWithSc(isCheckTx bool, enableEVMCustomPrecompiles bool, baseAppOptions TestAppOpts{true}, EmptyWasmOpts, EmptyACLOpts, + EmptyAppOptions, baseAppOptions..., ) if !isCheckTx { @@ -285,6 +294,7 @@ func SetupTestingAppWithLevelDb(isCheckTx bool, enableEVMCustomPrecompiles bool) TestAppOpts{}, EmptyWasmOpts, EmptyACLOpts, + nil, ) if !isCheckTx { genesisState := NewDefaultGenesisState(cdc) diff --git a/app/test_state_store.go b/app/test_state_store.go new file mode 100644 index 0000000000..b380cd6907 --- /dev/null +++ b/app/test_state_store.go @@ -0,0 +1,314 @@ +package app + +import ( + "errors" + "sync" + + seidbproto "github.com/sei-protocol/sei-db/proto" + "github.com/sei-protocol/sei-db/ss/types" +) + +// InMemoryStateStore this implements seidb state store with an inmemory store +type InMemoryStateStore struct { + mu sync.RWMutex + data map[string]map[int64]map[string][]byte + latestVersion int64 + earliestVersion int64 +} + +func NewInMemoryStateStore() *InMemoryStateStore { + return &InMemoryStateStore{ + data: make(map[string]map[int64]map[string][]byte), + latestVersion: 0, + earliestVersion: 0, + } +} + +func (s *InMemoryStateStore) Get(storeKey string, version int64, key []byte) ([]byte, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + store, ok := s.data[storeKey] + if !ok { + return nil, errors.New("store not found") + } + + versionData, ok := store[version] + if !ok { + return nil, errors.New("version not found") + } + + value, ok := versionData[string(key)] + if !ok { + return nil, errors.New("key not found") + } + + return value, nil +} + +func (s *InMemoryStateStore) Has(storeKey string, version int64, key []byte) (bool, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + store, ok := s.data[storeKey] + if !ok { + return false, nil + } + + versionData, ok := store[version] + if !ok { + return false, nil + } + + _, ok = versionData[string(key)] + return ok, nil +} + +func (s *InMemoryStateStore) Iterator(storeKey string, version int64, start, end []byte) (types.DBIterator, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + store, ok := s.data[storeKey] + if !ok { + return nil, errors.New("store not found") + } + + versionData, ok := store[version] + if !ok { + return nil, errors.New("version not found") + } + + keys := []string{} + for k := range versionData { + if (start == nil || k >= string(start)) && (end == nil || k < string(end)) { + keys = append(keys, k) + } + } + + return &InMemoryIterator{ + data: versionData, + keys: keys, + current: -1, + start: start, + end: end, + }, nil +} + +func (s *InMemoryStateStore) ReverseIterator(storeKey string, version int64, start, end []byte) (types.DBIterator, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + store, ok := s.data[storeKey] + if !ok { + return nil, errors.New("store not found") + } + + versionData, ok := store[version] + if !ok { + return nil, errors.New("version not found") + } + + keys := []string{} + for k := range versionData { + if (start == nil || k >= string(start)) && (end == nil || k < string(end)) { + keys = append(keys, k) + } + } + + // Reverse the keys for reverse iteration + for i, j := 0, len(keys)-1; i < j; i, j = i+1, j-1 { + keys[i], keys[j] = keys[j], keys[i] + } + + return &InMemoryIterator{ + data: versionData, + keys: keys, + current: -1, + start: start, + end: end, + }, nil +} + +func (s *InMemoryStateStore) RawIterate(storeKey string, fn func([]byte, []byte, int64) bool) (bool, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + for version, versionData := range s.data[storeKey] { + for key, value := range versionData { + if !fn([]byte(key), value, version) { + return false, nil + } + } + } + + return true, nil +} + +func (s *InMemoryStateStore) GetLatestVersion() (int64, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + return s.latestVersion, nil +} + +func (s *InMemoryStateStore) SetLatestVersion(version int64) error { + s.mu.Lock() + defer s.mu.Unlock() + + s.latestVersion = version + return nil +} + +func (s *InMemoryStateStore) GetEarliestVersion() (int64, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + return s.earliestVersion, nil +} + +func (s *InMemoryStateStore) SetEarliestVersion(version int64) error { + s.mu.Lock() + defer s.mu.Unlock() + + s.earliestVersion = version + return nil +} + +func (s *InMemoryStateStore) ApplyChangeset(version int64, cs *seidbproto.NamedChangeSet) error { + s.mu.Lock() + defer s.mu.Unlock() + + for _, pair := range cs.Changeset.Pairs { + storeKey := cs.Name + key := pair.Key + value := pair.Value + + if s.data[storeKey] == nil { + s.data[storeKey] = make(map[int64]map[string][]byte) + } + + if s.data[storeKey][version] == nil { + s.data[storeKey][version] = make(map[string][]byte) + } + + if pair.Delete { + delete(s.data[storeKey][version], string(key)) + } else { + s.data[storeKey][version][string(key)] = value + } + } + + s.latestVersion = version + return nil +} + +func (s *InMemoryStateStore) ApplyChangesetAsync(version int64, changesets []*seidbproto.NamedChangeSet) error { + // Implementation for async write, currently just calls ApplyChangeset + for _, cs := range changesets { + if err := s.ApplyChangeset(version, cs); err != nil { + return err + } + } + return nil +} + +func (s *InMemoryStateStore) Import(version int64, ch <-chan types.SnapshotNode) error { + s.mu.Lock() + defer s.mu.Unlock() + + for node := range ch { + storeKey := node.StoreKey + key := node.Key + value := node.Value + + if s.data[storeKey] == nil { + s.data[storeKey] = make(map[int64]map[string][]byte) + } + + if s.data[storeKey][version] == nil { + s.data[storeKey][version] = make(map[string][]byte) + } + + s.data[storeKey][version][string(key)] = value + } + + s.latestVersion = version + return nil +} + +func (s *InMemoryStateStore) Prune(version int64) error { + s.mu.Lock() + defer s.mu.Unlock() + + for storeKey, store := range s.data { + for ver := range store { + if ver <= version { + delete(store, ver) + } + } + if len(store) == 0 { + delete(s.data, storeKey) + } + } + + if s.earliestVersion <= version { + s.earliestVersion = version + 1 + } + + return nil +} + +func (s *InMemoryStateStore) Close() error { + s.mu.Lock() + defer s.mu.Unlock() + + s.data = make(map[string]map[int64]map[string][]byte) + return nil +} + +// InMemoryIterator implements the DBIterator interface for an in-memory store. +type InMemoryIterator struct { + data map[string][]byte + keys []string + current int + start []byte + end []byte +} + +func (it *InMemoryIterator) Domain() (start, end []byte) { + return it.start, it.end +} + +func (it *InMemoryIterator) Valid() bool { + return it.current >= 0 && it.current < len(it.keys) +} + +func (it *InMemoryIterator) Next() { + if it.Valid() { + it.current++ + } +} + +func (it *InMemoryIterator) Key() (key []byte) { + if !it.Valid() { + panic("iterator is invalid") + } + return []byte(it.keys[it.current]) +} + +func (it *InMemoryIterator) Value() (value []byte) { + if !it.Valid() { + panic("iterator is invalid") + } + return it.data[it.keys[it.current]] +} + +func (it *InMemoryIterator) Error() error { + return nil +} + +func (it *InMemoryIterator) Close() error { + it.data = nil + it.keys = nil + return nil +} diff --git a/cmd/seid/cmd/blocktest.go b/cmd/seid/cmd/blocktest.go index 177eef0e69..61bf133d0b 100644 --- a/cmd/seid/cmd/blocktest.go +++ b/cmd/seid/cmd/blocktest.go @@ -81,6 +81,7 @@ func BlocktestCmd(defaultNodeHome string) *cobra.Command { ), }, []aclkeeper.Option{}, + app.EmptyAppOptions, baseapp.SetPruning(storetypes.PruneEverything), baseapp.SetMinGasPrices(cast.ToString(serverCtx.Viper.Get(server.FlagMinGasPrices))), baseapp.SetMinRetainBlocks(cast.ToUint64(serverCtx.Viper.Get(server.FlagMinRetainBlocks))), diff --git a/cmd/seid/cmd/ethreplay.go b/cmd/seid/cmd/ethreplay.go index 5c331393cb..620c398d68 100644 --- a/cmd/seid/cmd/ethreplay.go +++ b/cmd/seid/cmd/ethreplay.go @@ -76,6 +76,7 @@ func ReplayCmd(defaultNodeHome string) *cobra.Command { ), }, []aclkeeper.Option{}, + app.EmptyAppOptions, baseapp.SetPruning(storetypes.PruneEverything), baseapp.SetMinGasPrices(cast.ToString(serverCtx.Viper.Get(server.FlagMinGasPrices))), baseapp.SetMinRetainBlocks(cast.ToUint64(serverCtx.Viper.Get(server.FlagMinRetainBlocks))), diff --git a/cmd/seid/cmd/root.go b/cmd/seid/cmd/root.go index 3c267eec53..f8f5a51f65 100644 --- a/cmd/seid/cmd/root.go +++ b/cmd/seid/cmd/root.go @@ -287,6 +287,7 @@ func newApp( ), }, []aclkeeper.Option{}, + app.EmptyAppOptions, baseapp.SetPruning(pruningOpts), baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(server.FlagMinGasPrices))), baseapp.SetMinRetainBlocks(cast.ToUint64(appOpts.Get(server.FlagMinRetainBlocks))), @@ -324,12 +325,12 @@ func appExport( } if height != -1 { - exportableApp = app.New(logger, db, traceStore, false, map[int64]bool{}, cast.ToString(appOpts.Get(flags.FlagHome)), uint(1), true, nil, encCfg, app.GetWasmEnabledProposals(), appOpts, app.EmptyWasmOpts, app.EmptyACLOpts) + exportableApp = app.New(logger, db, traceStore, false, map[int64]bool{}, cast.ToString(appOpts.Get(flags.FlagHome)), uint(1), true, nil, encCfg, app.GetWasmEnabledProposals(), appOpts, app.EmptyWasmOpts, app.EmptyACLOpts, app.EmptyAppOptions) if err := exportableApp.LoadHeight(height); err != nil { return servertypes.ExportedApp{}, err } } else { - exportableApp = app.New(logger, db, traceStore, true, map[int64]bool{}, cast.ToString(appOpts.Get(flags.FlagHome)), uint(1), true, nil, encCfg, app.GetWasmEnabledProposals(), appOpts, app.EmptyWasmOpts, app.EmptyACLOpts) + exportableApp = app.New(logger, db, traceStore, true, map[int64]bool{}, cast.ToString(appOpts.Get(flags.FlagHome)), uint(1), true, nil, encCfg, app.GetWasmEnabledProposals(), appOpts, app.EmptyWasmOpts, app.EmptyACLOpts, app.EmptyAppOptions) } return exportableApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs) diff --git a/testutil/network/network.go b/testutil/network/network.go index 836703fa6f..14b0e6d22b 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -76,6 +76,7 @@ func DefaultConfig() network.Config { &TestAppOptions{}, nil, app.EmptyACLOpts, + app.EmptyAppOptions, baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.Pruning)), baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices), ) From 5409b3803dca8a97c1fba7377978d112fb6e45c0 Mon Sep 17 00:00:00 2001 From: yzang2019 Date: Wed, 26 Jun 2024 10:54:39 -0700 Subject: [PATCH 17/26] Set KeepLastVersion to false --- app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index ba5f7c1efc..8eae8ecd2b 100644 --- a/app/app.go +++ b/app/app.go @@ -615,13 +615,13 @@ func New( ssConfig.DedicatedChangelog = true ssConfig.KeepRecent = cast.ToInt(appOpts.Get(server.FlagMinRetainBlocks)) ssConfig.DBDirectory = receiptStorePath + ssConfig.KeepLastVersion = false if app.receiptStore == nil { app.receiptStore, err = ss.NewStateStore(logger, receiptStorePath, ssConfig) if err != nil { panic(fmt.Sprintf("error while creating receipt store: %s", err)) } } - app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey], tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), app.receiptStore, app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper, app.TransferKeeper, From 0c685eab1491c753e3cbbde72011f96c758c0e5a Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 13:56:27 -0400 Subject: [PATCH 18/26] fix mocking of receipts --- app/test_helpers.go | 9 ++++++++- evmrpc/filter_test.go | 2 +- evmrpc/setup_test.go | 12 ++++++------ evmrpc/tx_test.go | 6 +++--- x/evm/genesis_test.go | 2 +- x/evm/keeper/receipt.go | 19 +++++-------------- x/evm/keeper/receipt_test.go | 2 +- 7 files changed, 25 insertions(+), 27 deletions(-) diff --git a/app/test_helpers.go b/app/test_helpers.go index d6f7916b5d..e80e7f3573 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -228,6 +228,13 @@ func SetupWithSc(isCheckTx bool, enableEVMCustomPrecompiles bool, baseAppOptions db := dbm.NewMemDB() encodingConfig := MakeEncodingConfig() cdc := encodingConfig.Marshaler + + options := []AppOption{ + func(app *App) { + app.receiptStore = NewInMemoryStateStore() + }, + } + res = New( log.NewNopLogger(), db, @@ -243,7 +250,7 @@ func SetupWithSc(isCheckTx bool, enableEVMCustomPrecompiles bool, baseAppOptions TestAppOpts{true}, EmptyWasmOpts, EmptyACLOpts, - EmptyAppOptions, + options, baseAppOptions..., ) if !isCheckTx { diff --git a/evmrpc/filter_test.go b/evmrpc/filter_test.go index 051dc28b71..abab66aa16 100644 --- a/evmrpc/filter_test.go +++ b/evmrpc/filter_test.go @@ -255,7 +255,7 @@ func TestFilterGetFilterChanges(t *testing.T) { Address: common.HexToAddress("0x1111111111111111111111111111111111111112"), Topics: []common.Hash{}, }}}}) - EVMKeeper.SetReceipt(Ctx, common.HexToHash("0x123456789012345678902345678901234567890123456789012345678900005"), &types.Receipt{ + EVMKeeper.MockReceipt(Ctx, common.HexToHash("0x123456789012345678902345678901234567890123456789012345678900005"), &types.Receipt{ BlockNumber: 9, LogsBloom: bloom[:], Logs: []*types.Log{{ diff --git a/evmrpc/setup_test.go b/evmrpc/setup_test.go index 03e132d488..73b861e388 100644 --- a/evmrpc/setup_test.go +++ b/evmrpc/setup_test.go @@ -540,7 +540,7 @@ func generateTxData() { MultiTxBlockTx4 = txBuilder4.GetTx() DebugTraceTx = debugTraceTxBuilder.GetTx() TxNonEvm = app.TestTx{} - if err := EVMKeeper.SetReceipt(Ctx, tx1.Hash(), &types.Receipt{ + if err := EVMKeeper.MockReceipt(Ctx, tx1.Hash(), &types.Receipt{ From: "0x1234567890123456789012345678901234567890", To: "0x1234567890123456789012345678901234567890", TransactionIndex: 0, @@ -646,7 +646,7 @@ func setupLogs() { common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000123"), }, }}}}) - EVMKeeper.SetReceipt(Ctx, multiTxBlockTx1.Hash(), &types.Receipt{ + EVMKeeper.MockReceipt(Ctx, multiTxBlockTx1.Hash(), &types.Receipt{ BlockNumber: MultiTxBlockHeight, TransactionIndex: 1, // start at 1 bc 0 is the non-evm tx TxHashHex: multiTxBlockTx1.Hash().Hex(), @@ -666,7 +666,7 @@ func setupLogs() { common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000456"), }, }}}}) - EVMKeeper.SetReceipt(Ctx, multiTxBlockTx2.Hash(), &types.Receipt{ + EVMKeeper.MockReceipt(Ctx, multiTxBlockTx2.Hash(), &types.Receipt{ BlockNumber: MultiTxBlockHeight, TransactionIndex: 3, TxHashHex: multiTxBlockTx2.Hash().Hex(), @@ -683,7 +683,7 @@ func setupLogs() { common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000456"), }, }}}}) - EVMKeeper.SetReceipt(Ctx, multiTxBlockTx3.Hash(), &types.Receipt{ + EVMKeeper.MockReceipt(Ctx, multiTxBlockTx3.Hash(), &types.Receipt{ BlockNumber: MultiTxBlockHeight, TransactionIndex: 4, TxHashHex: multiTxBlockTx3.Hash().Hex(), @@ -700,7 +700,7 @@ func setupLogs() { common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000456"), }, }}}}) - EVMKeeper.SetReceipt(Ctx, multiTxBlockTx4.Hash(), &types.Receipt{ + EVMKeeper.MockReceipt(Ctx, multiTxBlockTx4.Hash(), &types.Receipt{ BlockNumber: MockHeight, TransactionIndex: 0, TxHashHex: multiTxBlockTx4.Hash().Hex(), @@ -710,7 +710,7 @@ func setupLogs() { Topics: []string{"0x0000000000000000000000000000000000000000000000000000000000000123", "0x0000000000000000000000000000000000000000000000000000000000000456"}, }}, }) - EVMKeeper.SetReceipt(Ctx, common.HexToHash(DebugTraceHashHex), &types.Receipt{ + EVMKeeper.MockReceipt(Ctx, common.HexToHash(DebugTraceHashHex), &types.Receipt{ BlockNumber: DebugTraceMockHeight, TransactionIndex: 0, TxHashHex: DebugTraceHashHex, diff --git a/evmrpc/tx_test.go b/evmrpc/tx_test.go index 002c31f87b..3e36046da1 100644 --- a/evmrpc/tx_test.go +++ b/evmrpc/tx_test.go @@ -24,7 +24,7 @@ func TestGetTxReceipt(t *testing.T) { receipt, err := EVMKeeper.GetReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e")) require.Nil(t, err) receipt.To = "" - EVMKeeper.SetReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e"), receipt) + EVMKeeper.MockReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e"), receipt) body := "{\"jsonrpc\": \"2.0\",\"method\": \"eth_getTransactionReceipt\",\"params\":[\"0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e\"],\"id\":\"test\"}" req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s:%d", TestAddr, TestPort), strings.NewReader(body)) @@ -68,7 +68,7 @@ func TestGetTxReceipt(t *testing.T) { require.Nil(t, err) receipt.ContractAddress = "" receipt.To = "0x1234567890123456789012345678901234567890" - EVMKeeper.SetReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e"), receipt) + EVMKeeper.MockReceipt(Ctx, common.HexToHash("0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e"), receipt) body = "{\"jsonrpc\": \"2.0\",\"method\": \"eth_getTransactionReceipt\",\"params\":[\"0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e\"],\"id\":\"test\"}" req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s:%d", TestAddr, TestPort), strings.NewReader(body)) require.Nil(t, err) @@ -215,7 +215,7 @@ func TestGetTransactionCount(t *testing.T) { func TestGetTransactionError(t *testing.T) { h := common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") - EVMKeeper.SetReceipt(Ctx, h, &types.Receipt{VmError: "test error"}) + EVMKeeper.MockReceipt(Ctx, h, &types.Receipt{VmError: "test error"}) resObj := sendRequestGood(t, "getTransactionErrorByHash", "0x1111111111111111111111111111111111111111111111111111111111111111") require.Equal(t, "test error", resObj["result"]) diff --git a/x/evm/genesis_test.go b/x/evm/genesis_test.go index 19a0a9f961..bcb78c0cb5 100644 --- a/x/evm/genesis_test.go +++ b/x/evm/genesis_test.go @@ -21,7 +21,7 @@ func TestExportImportGenesis(t *testing.T) { keeper.SetCode(ctx, codeAddr, []byte("abcde")) keeper.SetState(ctx, codeAddr, common.BytesToHash([]byte("123")), common.BytesToHash([]byte("456"))) keeper.SetNonce(ctx, evmAddr, 2) - keeper.SetReceipt(ctx, common.BytesToHash([]byte("789")), &types.Receipt{TxType: 2}) + keeper.MockReceipt(ctx, common.BytesToHash([]byte("789")), &types.Receipt{TxType: 2}) keeper.SetBlockBloom(ctx, 5, []ethtypes.Bloom{{1}}) keeper.SetTxHashesOnHeight(ctx, 5, []common.Hash{common.BytesToHash([]byte("123"))}) keeper.SetERC20CW20Pointer(ctx, "cw20addr", codeAddr) diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 9ba3ab4e12..d369ac58a2 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -26,11 +26,7 @@ func (k *Keeper) SetTransientReceipt(ctx sdk.Context, txHash common.Hash, receip // by EVM transaction hash (not Sei transaction hash) to function properly. func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt, error) { ctx.Logger().Info("[Debug] GetReceipt START", "tx", txHash.Hex()) - v, err := k.receiptStore.GetLatestVersion() - if err != nil { - return nil, err - } - bz, err := k.receiptStore.Get(types.ReceiptStoreKey, v, types.ReceiptKey(txHash)) + bz, err := k.receiptStore.Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) ctx.Logger().Info("[Debug] GetReceipt DONE", "tx", txHash.Hex()) if err != nil { return nil, err @@ -54,19 +50,14 @@ func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt return &r, nil } -// SetReceipt sets a data structure that stores EVM specific transaction metadata. +// MockReceipt sets a data structure that stores EVM specific transaction metadata. // -// Deprecated: in favor of SetTransientReceipt // this is currently used by a number of tests to set receipts at the moment -// TODO: remove this once we move off of SetReceipt (tests are using it) -func (k *Keeper) SetReceipt(ctx sdk.Context, txHash common.Hash, receipt *types.Receipt) error { - store := ctx.KVStore(k.storeKey) - bz, err := receipt.Marshal() - if err != nil { +func (k *Keeper) MockReceipt(ctx sdk.Context, txHash common.Hash, receipt *types.Receipt) error { + if err := k.SetTransientReceipt(ctx, txHash, receipt); err != nil { return err } - store.Set(types.ReceiptKey(txHash), bz) - return nil + return k.FlushTransientReceipts(ctx) } func (k *Keeper) FlushTransientReceipts(ctx sdk.Context) error { diff --git a/x/evm/keeper/receipt_test.go b/x/evm/keeper/receipt_test.go index fc1971d8f9..5111e4081a 100644 --- a/x/evm/keeper/receipt_test.go +++ b/x/evm/keeper/receipt_test.go @@ -14,7 +14,7 @@ func TestReceipt(t *testing.T) { txHash := common.HexToHash("0x0750333eac0be1203864220893d8080dd8a8fd7a2ed098dfd92a718c99d437f2") _, err := k.GetReceipt(ctx, txHash) require.NotNil(t, err) - k.SetReceipt(ctx, txHash, &types.Receipt{TxHashHex: txHash.Hex()}) + k.MockReceipt(ctx, txHash, &types.Receipt{TxHashHex: txHash.Hex()}) r, err := k.GetReceipt(ctx, txHash) require.Nil(t, err) require.Equal(t, txHash.Hex(), r.TxHashHex) From a13a453759526ecb57e8a42446915ff2b3ffed5f Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 14:06:32 -0400 Subject: [PATCH 19/26] flush after receipts exist --- x/evm/artifacts/native/artifacts_test.go | 1 + x/evm/client/wasm/query_test.go | 1 + x/evm/integration_test.go | 2 ++ x/evm/module_test.go | 2 ++ 4 files changed, 6 insertions(+) diff --git a/x/evm/artifacts/native/artifacts_test.go b/x/evm/artifacts/native/artifacts_test.go index e023def9b2..46aa6b7fd9 100644 --- a/x/evm/artifacts/native/artifacts_test.go +++ b/x/evm/artifacts/native/artifacts_test.go @@ -68,6 +68,7 @@ func TestSimple(t *testing.T) { require.Nil(t, err) require.Empty(t, res.VmError) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.NotNil(t, receipt) diff --git a/x/evm/client/wasm/query_test.go b/x/evm/client/wasm/query_test.go index 194aec2cc4..5b04471e91 100644 --- a/x/evm/client/wasm/query_test.go +++ b/x/evm/client/wasm/query_test.go @@ -345,6 +345,7 @@ func deployContract(t *testing.T, ctx sdk.Context, k *keeper.Keeper, path string res, err := msgServer.EVMTransaction(sdk.WrapSDKContext(ctx), req) require.Nil(t, err) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) if receipt.Status != 1 { diff --git a/x/evm/integration_test.go b/x/evm/integration_test.go index f28397768d..808de0fe7f 100644 --- a/x/evm/integration_test.go +++ b/x/evm/integration_test.go @@ -177,6 +177,8 @@ func TestCW2981PointerToERC2981(t *testing.T) { require.Nil(t, err) res := testkeeper.EVMTestApp.DeliverTx(ctx, abci.RequestDeliverTx{Tx: txbz}, cosmosTx, sha256.Sum256(txbz)) require.Equal(t, uint32(0), res.Code) + err = k.FlushTransientReceipts(ctx) + require.NoError(t, err) receipt, err := k.GetReceipt(ctx, tx.Hash()) require.Nil(t, err) require.NotEmpty(t, receipt.ContractAddress) diff --git a/x/evm/module_test.go b/x/evm/module_test.go index e48acce5ac..12d1b99036 100644 --- a/x/evm/module_test.go +++ b/x/evm/module_test.go @@ -110,6 +110,8 @@ func TestABCI(t *testing.T) { k.AppendErrorToEvmTxDeferredInfo(ctx.WithTxIndex(0), common.Hash{1}, "test error") k.SetTxResults([]*abci.ExecTxResult{{Code: 1}}) m.EndBlock(ctx, abci.RequestEndBlock{}) + err = k.FlushTransientReceipts(ctx) + require.NoError(t, err) receipt, err := k.GetReceipt(ctx, common.Hash{1}) require.Nil(t, err) require.Equal(t, receipt.BlockNumber, uint64(ctx.BlockHeight())) From dd2415eb31e80d9fc7f023305a8b330c3560ae47 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 14:19:41 -0400 Subject: [PATCH 20/26] add transient->pebble->legacy fallback --- x/evm/keeper/receipt.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index d369ac58a2..772a7bcd81 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -25,21 +25,25 @@ func (k *Keeper) SetTransientReceipt(ctx sdk.Context, txHash common.Hash, receip // Many EVM applications (e.g. MetaMask) relies on being on able to query receipt // by EVM transaction hash (not Sei transaction hash) to function properly. func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt, error) { - ctx.Logger().Info("[Debug] GetReceipt START", "tx", txHash.Hex()) - bz, err := k.receiptStore.Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) - ctx.Logger().Info("[Debug] GetReceipt DONE", "tx", txHash.Hex()) - if err != nil { - return nil, err - } + + // try transient store first (fastest) + tStore := ctx.TransientStore(k.transientStoreKey) + bz := tStore.Get(types.ReceiptKey(txHash)) if bz == nil { - ctx.Logger().Info("[Debug] GetReceipt NOT FOUND", "tx", txHash.Hex()) + // try persistent store + bz, err := k.receiptStore.Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) + if err != nil { + return nil, err + } - // fallback because these used to exist in application state - store := ctx.KVStore(k.storeKey) - bz = store.Get(types.ReceiptKey(txHash)) if bz == nil { - return nil, errors.New("not found") + // try legacy store for older receipts + store := ctx.KVStore(k.storeKey) + bz = store.Get(types.ReceiptKey(txHash)) + if bz == nil { + return nil, errors.New("not found") + } } } From 86d36f83cf4af83f9b51767de194c8e1db524191 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 14:23:44 -0400 Subject: [PATCH 21/26] make error name consistent --- app/test_state_store.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/test_state_store.go b/app/test_state_store.go index b380cd6907..48135e83b4 100644 --- a/app/test_state_store.go +++ b/app/test_state_store.go @@ -30,17 +30,17 @@ func (s *InMemoryStateStore) Get(storeKey string, version int64, key []byte) ([] store, ok := s.data[storeKey] if !ok { - return nil, errors.New("store not found") + return nil, errors.New("not found") } versionData, ok := store[version] if !ok { - return nil, errors.New("version not found") + return nil, errors.New("not found") } value, ok := versionData[string(key)] if !ok { - return nil, errors.New("key not found") + return nil, errors.New("not found") } return value, nil From b8f98a33ed295e1c87262634d2fc1a566e025c08 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 14:48:59 -0400 Subject: [PATCH 22/26] avoid reading from transient store --- evmrpc/filter_test.go | 1 + x/evm/keeper/receipt.go | 26 +++++++++----------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/evmrpc/filter_test.go b/evmrpc/filter_test.go index abab66aa16..77e211b74a 100644 --- a/evmrpc/filter_test.go +++ b/evmrpc/filter_test.go @@ -255,6 +255,7 @@ func TestFilterGetFilterChanges(t *testing.T) { Address: common.HexToAddress("0x1111111111111111111111111111111111111112"), Topics: []common.Hash{}, }}}}) + Ctx = Ctx.WithBlockHeight(9) EVMKeeper.MockReceipt(Ctx, common.HexToHash("0x123456789012345678902345678901234567890123456789012345678900005"), &types.Receipt{ BlockNumber: 9, LogsBloom: bloom[:], diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 772a7bcd81..6041b6d1de 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -2,7 +2,6 @@ package keeper import ( "errors" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/iavl" "github.com/ethereum/go-ethereum/common" @@ -25,25 +24,18 @@ func (k *Keeper) SetTransientReceipt(ctx sdk.Context, txHash common.Hash, receip // Many EVM applications (e.g. MetaMask) relies on being on able to query receipt // by EVM transaction hash (not Sei transaction hash) to function properly. func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt, error) { - - // try transient store first (fastest) - tStore := ctx.TransientStore(k.transientStoreKey) - bz := tStore.Get(types.ReceiptKey(txHash)) + // try persistent store + bz, err := k.receiptStore.Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) + if err != nil { + return nil, err + } if bz == nil { - // try persistent store - bz, err := k.receiptStore.Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) - if err != nil { - return nil, err - } - + // try legacy store for older receipts + store := ctx.KVStore(k.storeKey) + bz = store.Get(types.ReceiptKey(txHash)) if bz == nil { - // try legacy store for older receipts - store := ctx.KVStore(k.storeKey) - bz = store.Get(types.ReceiptKey(txHash)) - if bz == nil { - return nil, errors.New("not found") - } + return nil, errors.New("not found") } } From c72564e50a1cd1033238f3ed2a24f49323c8e77e Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 15:30:08 -0400 Subject: [PATCH 23/26] use latest version --- x/evm/keeper/msg_server_test.go | 10 ++++++++++ x/evm/keeper/receipt.go | 11 ++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/x/evm/keeper/msg_server_test.go b/x/evm/keeper/msg_server_test.go index bfccd537e0..7a96a68f59 100644 --- a/x/evm/keeper/msg_server_test.go +++ b/x/evm/keeper/msg_server_test.go @@ -94,6 +94,7 @@ func TestEVMTransaction(t *testing.T) { require.NotEmpty(t, res.Hash) require.Equal(t, uint64(1000000)-res.GasUsed, k.BankKeeper().GetBalance(ctx, sdk.AccAddress(evmAddr[:]), "usei").Amount.Uint64()) require.Equal(t, res.GasUsed, k.BankKeeper().GetBalance(ctx, state.GetCoinbaseAddress(ctx.TxIndex()), k.GetBaseDenom(ctx)).Amount.Uint64()) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.NotNil(t, receipt) @@ -128,6 +129,7 @@ func TestEVMTransaction(t *testing.T) { require.Nil(t, err) require.LessOrEqual(t, res.GasUsed, uint64(200000)) require.Empty(t, res.VmError) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err = k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.NotNil(t, receipt) @@ -179,6 +181,7 @@ func TestEVMTransactionError(t *testing.T) { require.NotEmpty(t, res.VmError) // gas should be charged and receipt should be created require.Equal(t, uint64(800000), k.BankKeeper().GetBalance(ctx, sdk.AccAddress(evmAddr[:]), "usei").Amount.Uint64()) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.Equal(t, uint32(ethtypes.ReceiptStatusFailed), receipt.Status) @@ -284,6 +287,7 @@ func TestEVMDynamicFeeTransaction(t *testing.T) { require.NotEmpty(t, res.ReturnData) require.NotEmpty(t, res.Hash) require.LessOrEqual(t, k.BankKeeper().GetBalance(ctx, sdk.AccAddress(evmAddr[:]), "usei").Amount.Uint64(), uint64(1000000)-res.GasUsed) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.NotNil(t, receipt) @@ -342,6 +346,7 @@ func TestEVMPrecompiles(t *testing.T) { require.NotEmpty(t, res.Hash) require.Equal(t, uint64(1000000)-res.GasUsed, k.BankKeeper().GetBalance(ctx, sdk.AccAddress(evmAddr[:]), "usei").Amount.Uint64()) require.Equal(t, res.GasUsed, k.BankKeeper().GetBalance(ctx, state.GetCoinbaseAddress(ctx.TxIndex()), k.GetBaseDenom(ctx)).Amount.Uint64()) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.NotNil(t, receipt) @@ -385,6 +390,7 @@ func TestEVMPrecompiles(t *testing.T) { require.Nil(t, err) require.LessOrEqual(t, res.GasUsed, uint64(200000)) require.Empty(t, res.VmError) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err = k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.NotNil(t, receipt) @@ -457,6 +463,7 @@ func TestEVMBlockEnv(t *testing.T) { require.NotEmpty(t, res.Hash) require.Equal(t, uint64(1000000)-res.GasUsed, k.BankKeeper().GetBalance(ctx, sdk.AccAddress(evmAddr[:]), "usei").Amount.Uint64()) require.Equal(t, res.GasUsed, k.BankKeeper().GetBalance(ctx, state.GetCoinbaseAddress(ctx.TxIndex()), k.GetBaseDenom(ctx)).Amount.Uint64()) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.NotNil(t, receipt) @@ -491,6 +498,7 @@ func TestEVMBlockEnv(t *testing.T) { require.Nil(t, err) require.LessOrEqual(t, res.GasUsed, uint64(200000)) require.Empty(t, res.VmError) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err = k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) require.NotNil(t, receipt) @@ -639,6 +647,7 @@ func TestEvmError(t *testing.T) { res := testkeeper.EVMTestApp.DeliverTx(ctx, abci.RequestDeliverTx{Tx: txbz}, sdktx, sha256.Sum256(txbz)) require.Equal(t, uint32(0), res.Code) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.EvmTxInfo.TxHash)) require.Nil(t, err) @@ -671,6 +680,7 @@ func TestEvmError(t *testing.T) { res = testkeeper.EVMTestApp.DeliverTx(ctx, abci.RequestDeliverTx{Tx: txbz}, sdktx, sha256.Sum256(txbz)) require.Equal(t, uint32(45), res.Code) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err = k.GetReceipt(ctx, common.HexToHash(res.EvmTxInfo.TxHash)) require.Nil(t, err) require.Equal(t, receipt.VmError, res.EvmTxInfo.VmError) diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 6041b6d1de..896ef80bfb 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -2,6 +2,7 @@ package keeper import ( "errors" + "fmt" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/iavl" "github.com/ethereum/go-ethereum/common" @@ -24,8 +25,15 @@ func (k *Keeper) SetTransientReceipt(ctx sdk.Context, txHash common.Hash, receip // Many EVM applications (e.g. MetaMask) relies on being on able to query receipt // by EVM transaction hash (not Sei transaction hash) to function properly. func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt, error) { + + // receipts are immutable, use latest version + lv, err := k.receiptStore.GetLatestVersion() + if err != nil { + return nil, err + } + // try persistent store - bz, err := k.receiptStore.Get(types.ReceiptStoreKey, ctx.BlockHeight(), types.ReceiptKey(txHash)) + bz, err := k.receiptStore.Get(types.ReceiptStoreKey, lv, types.ReceiptKey(txHash)) if err != nil { return nil, err } @@ -50,6 +58,7 @@ func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt // // this is currently used by a number of tests to set receipts at the moment func (k *Keeper) MockReceipt(ctx sdk.Context, txHash common.Hash, receipt *types.Receipt) error { + fmt.Printf("MOCK RECEIPT height=%d, tx=%s\n", ctx.BlockHeight(), txHash.Hex()) if err := k.SetTransientReceipt(ctx, txHash, receipt); err != nil { return err } From 2e2a3f6752f20d0dc15e0c24c5d63486f9651f4d Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 15:35:04 -0400 Subject: [PATCH 24/26] fix goimports --- x/evm/keeper/receipt.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x/evm/keeper/receipt.go b/x/evm/keeper/receipt.go index 896ef80bfb..5872ea6a74 100644 --- a/x/evm/keeper/receipt.go +++ b/x/evm/keeper/receipt.go @@ -3,11 +3,13 @@ package keeper import ( "errors" "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/iavl" "github.com/ethereum/go-ethereum/common" - "github.com/sei-protocol/sei-chain/x/evm/types" "github.com/sei-protocol/sei-db/proto" + + "github.com/sei-protocol/sei-chain/x/evm/types" ) // SetTransientReceipt sets a data structure that stores EVM specific transaction metadata. From f4780e807c52cf42282caa62e982ae7fabee812a Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Wed, 26 Jun 2024 15:52:46 -0400 Subject: [PATCH 25/26] add test coverage for test state store --- app/test_state_store.go | 52 +++++------ app/test_state_store_test.go | 166 +++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 30 deletions(-) create mode 100644 app/test_state_store_test.go diff --git a/app/test_state_store.go b/app/test_state_store.go index 48135e83b4..520c06c0f8 100644 --- a/app/test_state_store.go +++ b/app/test_state_store.go @@ -78,20 +78,7 @@ func (s *InMemoryStateStore) Iterator(storeKey string, version int64, start, end return nil, errors.New("version not found") } - keys := []string{} - for k := range versionData { - if (start == nil || k >= string(start)) && (end == nil || k < string(end)) { - keys = append(keys, k) - } - } - - return &InMemoryIterator{ - data: versionData, - keys: keys, - current: -1, - start: start, - end: end, - }, nil + return NewInMemoryIterator(versionData, start, end), nil } func (s *InMemoryStateStore) ReverseIterator(storeKey string, version int64, start, end []byte) (types.DBIterator, error) { @@ -108,25 +95,14 @@ func (s *InMemoryStateStore) ReverseIterator(storeKey string, version int64, sta return nil, errors.New("version not found") } - keys := []string{} - for k := range versionData { - if (start == nil || k >= string(start)) && (end == nil || k < string(end)) { - keys = append(keys, k) - } - } + iter := NewInMemoryIterator(versionData, start, end) // Reverse the keys for reverse iteration - for i, j := 0, len(keys)-1; i < j; i, j = i+1, j-1 { - keys[i], keys[j] = keys[j], keys[i] + for i, j := 0, len(iter.keys)-1; i < j; i, j = i+1, j-1 { + iter.keys[i], iter.keys[j] = iter.keys[j], iter.keys[i] } - return &InMemoryIterator{ - data: versionData, - keys: keys, - current: -1, - start: start, - end: end, - }, nil + return iter, nil } func (s *InMemoryStateStore) RawIterate(storeKey string, fn func([]byte, []byte, int64) bool) (bool, error) { @@ -266,7 +242,6 @@ func (s *InMemoryStateStore) Close() error { return nil } -// InMemoryIterator implements the DBIterator interface for an in-memory store. type InMemoryIterator struct { data map[string][]byte keys []string @@ -275,6 +250,23 @@ type InMemoryIterator struct { end []byte } +func NewInMemoryIterator(data map[string][]byte, start, end []byte) *InMemoryIterator { + keys := make([]string, 0, len(data)) + for k := range data { + if (start == nil || k >= string(start)) && (end == nil || k < string(end)) { + keys = append(keys, k) + } + } + + return &InMemoryIterator{ + data: data, + keys: keys, + current: 0, + start: start, + end: end, + } +} + func (it *InMemoryIterator) Domain() (start, end []byte) { return it.start, it.end } diff --git a/app/test_state_store_test.go b/app/test_state_store_test.go new file mode 100644 index 0000000000..141294b58c --- /dev/null +++ b/app/test_state_store_test.go @@ -0,0 +1,166 @@ +package app + +import ( + "testing" + + "github.com/cosmos/iavl" + seidbproto "github.com/sei-protocol/sei-db/proto" + "github.com/stretchr/testify/assert" +) + +func TestApplyChangesetAndGet(t *testing.T) { + store := NewInMemoryStateStore() + + err := store.ApplyChangeset(1, &seidbproto.NamedChangeSet{ + Changeset: iavl.ChangeSet{ + Pairs: []*iavl.KVPair{ + {Key: []byte("key1"), Value: []byte("value1")}, + }, + }, + Name: "exampleStore", + }) + assert.NoError(t, err) + + value, err := store.Get("exampleStore", 1, []byte("key1")) + assert.NoError(t, err) + assert.Equal(t, []byte("value1"), value) +} + +func TestHas(t *testing.T) { + store := NewInMemoryStateStore() + + err := store.ApplyChangeset(1, &seidbproto.NamedChangeSet{ + Changeset: iavl.ChangeSet{ + Pairs: []*iavl.KVPair{ + {Key: []byte("key1"), Value: []byte("value1")}, + }, + }, + Name: "exampleStore", + }) + assert.NoError(t, err) + + has, err := store.Has("exampleStore", 1, []byte("key1")) + assert.NoError(t, err) + assert.True(t, has) + + has, err = store.Has("exampleStore", 1, []byte("key2")) + assert.NoError(t, err) + assert.False(t, has) +} + +func TestIterator(t *testing.T) { + store := NewInMemoryStateStore() + + err := store.ApplyChangeset(1, &seidbproto.NamedChangeSet{ + Changeset: iavl.ChangeSet{ + Pairs: []*iavl.KVPair{ + {Key: []byte("key1"), Value: []byte("value1")}, + {Key: []byte("key2"), Value: []byte("value2")}, + }, + }, + Name: "exampleStore", + }) + assert.NoError(t, err) + + iter, err := store.Iterator("exampleStore", 1, nil, nil) + assert.NoError(t, err) + assert.NotNil(t, iter) + + assert.True(t, iter.Valid()) + assert.Equal(t, []byte("key1"), iter.Key()) + assert.Equal(t, []byte("value1"), iter.Value()) + + iter.Next() + assert.True(t, iter.Valid()) + assert.Equal(t, []byte("key2"), iter.Key()) + assert.Equal(t, []byte("value2"), iter.Value()) + + iter.Next() + assert.False(t, iter.Valid()) + iter.Close() +} + +func TestReverseIterator(t *testing.T) { + store := NewInMemoryStateStore() + + err := store.ApplyChangeset(1, &seidbproto.NamedChangeSet{ + Changeset: iavl.ChangeSet{ + Pairs: []*iavl.KVPair{ + {Key: []byte("key1"), Value: []byte("value1")}, + {Key: []byte("key2"), Value: []byte("value2")}, + }, + }, + Name: "exampleStore", + }) + assert.NoError(t, err) + + iter, err := store.ReverseIterator("exampleStore", 1, nil, nil) + assert.NoError(t, err) + assert.NotNil(t, iter) + + assert.True(t, iter.Valid()) + assert.Equal(t, []byte("key2"), iter.Key()) + assert.Equal(t, []byte("value2"), iter.Value()) + + iter.Next() + assert.True(t, iter.Valid()) + assert.Equal(t, []byte("key1"), iter.Key()) + assert.Equal(t, []byte("value1"), iter.Value()) + + iter.Next() + assert.False(t, iter.Valid()) + iter.Close() +} + +func TestGetLatestVersionAndSetLatestVersion(t *testing.T) { + store := NewInMemoryStateStore() + + err := store.SetLatestVersion(2) + assert.NoError(t, err) + + version, err := store.GetLatestVersion() + assert.NoError(t, err) + assert.Equal(t, int64(2), version) +} + +func TestGetEarliestVersionAndSetEarliestVersion(t *testing.T) { + store := NewInMemoryStateStore() + + err := store.SetEarliestVersion(1) + assert.NoError(t, err) + + version, err := store.GetEarliestVersion() + assert.NoError(t, err) + assert.Equal(t, int64(1), version) +} + +func TestPrune(t *testing.T) { + store := NewInMemoryStateStore() + + err := store.ApplyChangeset(1, &seidbproto.NamedChangeSet{ + Changeset: iavl.ChangeSet{ + Pairs: []*iavl.KVPair{ + {Key: []byte("key1"), Value: []byte("value1")}, + {Key: []byte("key2"), Value: []byte("value2")}, + }, + }, + Name: "exampleStore", + }) + assert.NoError(t, err) + + err = store.Prune(1) + assert.NoError(t, err) + + _, err = store.Get("exampleStore", 1, []byte("key1")) + assert.Error(t, err) + + _, err = store.Get("exampleStore", 1, []byte("key2")) + assert.Error(t, err) +} + +func TestClose(t *testing.T) { + store := NewInMemoryStateStore() + + err := store.Close() + assert.NoError(t, err) +} From 78766012451063e003c99da335c97174f602370b Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Thu, 27 Jun 2024 09:34:34 -0400 Subject: [PATCH 26/26] tick sei-cosmos --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3c9c61e433..06a52bd876 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.1.5 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.20-0.20240626152810-f14e25c3c39c + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.23 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.1 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-22 diff --git a/go.sum b/go.sum index 867636900b..60c7f93541 100644 --- a/go.sum +++ b/go.sum @@ -1347,8 +1347,8 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-22 h1:t/m1qXER+DEMrcpqgoYmUxifkA github.com/sei-protocol/go-ethereum v1.13.5-sei-22/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA= github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= -github.com/sei-protocol/sei-cosmos v0.3.20-0.20240626152810-f14e25c3c39c h1:0wM73r6+BIxfNvTr1B+SmLnfWpCyZEAexd2wbMnCoEE= -github.com/sei-protocol/sei-cosmos v0.3.20-0.20240626152810-f14e25c3c39c/go.mod h1:og/KbejR/zSQ8otapODEDU9zYNhFSUDbq9+tgeYePyU= +github.com/sei-protocol/sei-cosmos v0.3.23 h1:ObuJ1EWrQKvqpKye4WFXaGwttpXTNrVmzSSskisFNFw= +github.com/sei-protocol/sei-cosmos v0.3.23/go.mod h1:og/KbejR/zSQ8otapODEDU9zYNhFSUDbq9+tgeYePyU= github.com/sei-protocol/sei-db v0.0.39 h1:/XwwlObPhWnX8zH8GDbDvyn+a/K2911HZlmlBZzN+gQ= github.com/sei-protocol/sei-db v0.0.39/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.1.9 h1:y4mVYftxLNRs6533zl7N0/Ch+CzRQc04JDfHolIxgBE=