From 3fadf56828c2836ed888d981354ea75261f3e26e Mon Sep 17 00:00:00 2001 From: codchen Date: Tue, 13 Feb 2024 11:09:30 +0800 Subject: [PATCH] Use in-memory map for deferred info (#1345) wip --- app/app.go | 1 + contracts/lib/openzeppelin-contracts | 2 +- x/evm/keeper/keeper.go | 78 ++++++++-------------------- x/evm/keeper/keeper_test.go | 8 ++- x/evm/module.go | 6 ++- x/evm/module_test.go | 6 +-- 6 files changed, 36 insertions(+), 65 deletions(-) diff --git a/app/app.go b/app/app.go index e3663a6e3d..fcf255ab8e 100644 --- a/app/app.go +++ b/app/app.go @@ -1505,6 +1505,7 @@ func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequ for relativeOtherIndex, originalIndex := range otherIndices { txResults[originalIndex] = otherResults[relativeOtherIndex] } + app.EvmKeeper.SetTxResults(txResults) // Finalize all Bank Module Transfers here so that events are included lazyWriteEvents := app.BankKeeper.WriteDeferredBalances(ctx) diff --git a/contracts/lib/openzeppelin-contracts b/contracts/lib/openzeppelin-contracts index 01ef448981..932fddf69a 160000 --- a/contracts/lib/openzeppelin-contracts +++ b/contracts/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 01ef448981be9d20ca85f2faf6ebdf591ce409f3 +Subproject commit 932fddf69a699a9a80fd2396fd1a2ab91cdda123 diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 0409f6f6ae..121b2118dc 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -1,7 +1,6 @@ package keeper import ( - "encoding/binary" "fmt" "math" "math/big" @@ -19,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" "github.com/sei-protocol/sei-chain/x/evm/types" @@ -29,6 +29,9 @@ type Keeper struct { memStoreKey sdk.StoreKey Paramstore paramtypes.Subspace + deferredInfo *sync.Map + txResults []*abci.ExecTxResult + bankKeeper bankkeeper.Keeper accountKeeper *authkeeper.AccountKeeper stakingKeeper *stakingkeeper.Keeper @@ -68,6 +71,7 @@ func NewKeeper( nonceMx: &sync.RWMutex{}, cachedFeeCollectorAddressMtx: &sync.RWMutex{}, keyToNonce: make(map[tmtypes.TxKey]*addressNoncePair), + deferredInfo: &sync.Map{}, } return k } @@ -142,69 +146,27 @@ func (k *Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { } func (k *Keeper) GetEVMTxDeferredInfo(ctx sdk.Context) (res []EvmTxDeferredInfo) { - hashMap, bloomMap := map[int]common.Hash{}, map[int]ethtypes.Bloom{} - hashIter := prefix.NewStore(ctx.KVStore(k.memStoreKey), types.TxHashPrefix).Iterator(nil, nil) - for ; hashIter.Valid(); hashIter.Next() { - h := common.Hash{} - h.SetBytes(hashIter.Value()) - hashMap[int(binary.BigEndian.Uint32(hashIter.Key()))] = h - } - hashIter.Close() - bloomIter := prefix.NewStore(ctx.KVStore(k.memStoreKey), types.TxBloomPrefix).Iterator(nil, nil) - for ; bloomIter.Valid(); bloomIter.Next() { - b := ethtypes.Bloom{} - b.SetBytes(bloomIter.Value()) - bloomMap[int(binary.BigEndian.Uint32(bloomIter.Key()))] = b - } - bloomIter.Close() - for idx, h := range hashMap { - i := EvmTxDeferredInfo{TxIndx: idx, TxHash: h} - if b, ok := bloomMap[idx]; ok { - i.TxBloom = b - delete(bloomMap, idx) + k.deferredInfo.Range(func(key, value any) bool { + txIdx := key.(int) + if txIdx >= 0 && txIdx < len(k.txResults) && k.txResults[txIdx].Code == 0 { + res = append(res, *(value.(*EvmTxDeferredInfo))) } - res = append(res, i) - } - for idx, b := range bloomMap { - res = append(res, EvmTxDeferredInfo{TxIndx: idx, TxBloom: b}) - } + return true + }) sort.SliceStable(res, func(i, j int) bool { return res[i].TxIndx < res[j].TxIndx }) return } func (k *Keeper) AppendToEvmTxDeferredInfo(ctx sdk.Context, bloom ethtypes.Bloom, txHash common.Hash) { - key := make([]byte, 8) - binary.BigEndian.PutUint32(key, uint32(ctx.TxIndex())) - prefix.NewStore(ctx.KVStore(k.memStoreKey), types.TxHashPrefix).Set(key, txHash[:]) - prefix.NewStore(ctx.KVStore(k.memStoreKey), types.TxBloomPrefix).Set(key, bloom[:]) + k.deferredInfo.Store(ctx.TxIndex(), &EvmTxDeferredInfo{ + TxIndx: ctx.TxIndex(), + TxBloom: bloom, + TxHash: txHash, + }) } -func (k *Keeper) ClearEVMTxDeferredInfo(ctx sdk.Context) { - hashStore := prefix.NewStore(ctx.KVStore(k.memStoreKey), types.TxHashPrefix) - hashIterator := hashStore.Iterator(nil, nil) - defer hashIterator.Close() - hashKeysToDelete := [][]byte{} - for ; hashIterator.Valid(); hashIterator.Next() { - hashKeysToDelete = append(hashKeysToDelete, hashIterator.Key()) - } - // close the first iterator for safety - hashIterator.Close() - for _, key := range hashKeysToDelete { - hashStore.Delete(key) - } - - bloomStore := prefix.NewStore(ctx.KVStore(k.memStoreKey), types.TxBloomPrefix) - bloomIterator := bloomStore.Iterator(nil, nil) - bloomKeysToDelete := [][]byte{} - defer bloomIterator.Close() - for ; bloomIterator.Valid(); bloomIterator.Next() { - bloomKeysToDelete = append(bloomKeysToDelete, bloomIterator.Key()) - } - // close the second iterator for safety - bloomIterator.Close() - for _, key := range bloomKeysToDelete { - bloomStore.Delete(key) - } +func (k *Keeper) ClearEVMTxDeferredInfo() { + k.deferredInfo = &sync.Map{} } func (k *Keeper) getHistoricalHash(ctx sdk.Context, h int64) common.Hash { @@ -295,6 +257,10 @@ func (k *Keeper) RemovePendingNonce(key tmtypes.TxKey) { } } +func (k *Keeper) SetTxResults(txResults []*abci.ExecTxResult) { + k.txResults = txResults +} + func uint64Cmp(a, b uint64) int { if a < b { return -1 diff --git a/x/evm/keeper/keeper_test.go b/x/evm/keeper/keeper_test.go index b3997e3a0f..9735282c32 100644 --- a/x/evm/keeper/keeper_test.go +++ b/x/evm/keeper/keeper_test.go @@ -13,6 +13,7 @@ import ( evmkeeper "github.com/sei-protocol/sei-chain/x/evm/keeper" "github.com/sei-protocol/sei-chain/x/evm/types" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/rand" tmtypes "github.com/tendermint/tendermint/types" ) @@ -191,7 +192,10 @@ func TestDeferredInfo(t *testing.T) { ctx = ctx.WithTxIndex(1) k.AppendToEvmTxDeferredInfo(ctx, ethtypes.Bloom{1, 2, 3}, common.Hash{4, 5, 6}) ctx = ctx.WithTxIndex(2) - k.AppendToEvmTxDeferredInfo(ctx, ethtypes.Bloom{7, 8}, common.Hash{9.0}) + k.AppendToEvmTxDeferredInfo(ctx, ethtypes.Bloom{7, 8}, common.Hash{9, 0}) + ctx = ctx.WithTxIndex(3) // should be ignored because txResult has non-zero code + k.AppendToEvmTxDeferredInfo(ctx, ethtypes.Bloom{11, 12}, common.Hash{13, 14}) + k.SetTxResults([]*abci.ExecTxResult{{Code: 0}, {Code: 0}, {Code: 0}, {Code: 1}}) infoList := k.GetEVMTxDeferredInfo(ctx) require.Equal(t, 2, len(infoList)) require.Equal(t, 1, infoList[0].TxIndx) @@ -201,7 +205,7 @@ func TestDeferredInfo(t *testing.T) { require.Equal(t, ethtypes.Bloom{7, 8}, infoList[1].TxBloom) require.Equal(t, common.Hash{9, 0}, infoList[1].TxHash) // test clear tx deferred info - k.ClearEVMTxDeferredInfo(ctx) + k.ClearEVMTxDeferredInfo() infoList = k.GetEVMTxDeferredInfo(ctx) require.Empty(t, len(infoList)) } diff --git a/x/evm/module.go b/x/evm/module.go index 7c7ca4393d..c759bc3306 100644 --- a/x/evm/module.go +++ b/x/evm/module.go @@ -161,6 +161,10 @@ func (AppModule) ConsensusVersion() uint64 { return 3 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(sdk.Context, abci.RequestBeginBlock) { + // clear tx responses from last block + am.keeper.SetTxResults([]*abci.ExecTxResult{}) + // clear the TxDeferredInfo + am.keeper.ClearEVMTxDeferredInfo() } // EndBlock executes all ABCI EndBlock logic respective to the capability module. It @@ -189,7 +193,5 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val } am.keeper.SetTxHashesOnHeight(ctx, ctx.BlockHeight(), utils.Map(evmTxDeferredInfoList, func(i keeper.EvmTxDeferredInfo) common.Hash { return i.TxHash })) am.keeper.SetBlockBloom(ctx, ctx.BlockHeight(), utils.Map(evmTxDeferredInfoList, func(i keeper.EvmTxDeferredInfo) ethtypes.Bloom { return i.TxBloom })) - // clear the TxDeferredInfo - am.keeper.ClearEVMTxDeferredInfo(ctx) return []abci.ValidatorUpdate{} } diff --git a/x/evm/module_test.go b/x/evm/module_test.go index 144020fcc8..f595369531 100644 --- a/x/evm/module_test.go +++ b/x/evm/module_test.go @@ -41,9 +41,8 @@ func TestABCI(t *testing.T) { s.AddBalance(evmAddr1, big.NewInt(5000000000000)) require.Nil(t, s.Finalize()) k.AppendToEvmTxDeferredInfo(ctx.WithTxIndex(3), ethtypes.Bloom{}, common.Hash{}) + k.SetTxResults([]*abci.ExecTxResult{{Code: 0}, {Code: 0}, {Code: 0}, {Code: 0}}) m.EndBlock(ctx, abci.RequestEndBlock{}) - deferredInfo := k.GetEVMTxDeferredInfo(ctx) - require.Empty(t, deferredInfo) require.Equal(t, uint64(0), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(types.ModuleName), "usei").Amount.Uint64()) require.Equal(t, uint64(2), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(authtypes.FeeCollectorName), "usei").Amount.Uint64()) @@ -55,9 +54,8 @@ func TestABCI(t *testing.T) { s.AddBalance(evmAddr1, big.NewInt(2000000000000)) require.Nil(t, s.Finalize()) k.AppendToEvmTxDeferredInfo(ctx.WithTxIndex(2), ethtypes.Bloom{}, common.Hash{}) + k.SetTxResults([]*abci.ExecTxResult{{Code: 0}, {Code: 0}, {Code: 0}}) m.EndBlock(ctx, abci.RequestEndBlock{}) require.Equal(t, uint64(1), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(types.ModuleName), "usei").Amount.Uint64()) require.Equal(t, uint64(2), k.BankKeeper().GetBalance(ctx, k.AccountKeeper().GetModuleAddress(authtypes.FeeCollectorName), "usei").Amount.Uint64()) - deferredInfo = k.GetEVMTxDeferredInfo(ctx) - require.Empty(t, deferredInfo) }