From 55ab7cf4de12ff2491c1e8b02f0f85ac119e2323 Mon Sep 17 00:00:00 2001 From: beer-1 <147697694+beer-1@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:14:01 +0900 Subject: [PATCH] feat: introduce evm indexer pruning (#129) * bump cometbft to update txindex prune strategy * implement evm indexer pruning * remove unnecessary range --- go.mod | 2 +- go.sum | 4 +- indexer/abci.go | 5 ++ indexer/indexer.go | 31 +++++--- indexer/prune.go | 152 +++++++++++++++++++++++++++++++++++++++ indexer/prune_test.go | 109 ++++++++++++++++++++++++++++ indexer/store.go | 54 ++++++++++++++ integration-tests/go.mod | 6 +- integration-tests/go.sum | 12 ++-- x/evm/config/config.go | 33 ++++++--- 10 files changed, 378 insertions(+), 30 deletions(-) create mode 100644 indexer/prune.go create mode 100644 indexer/prune_test.go diff --git a/go.mod b/go.mod index ee83b3d3..c4568383 100644 --- a/go.mod +++ b/go.mod @@ -288,7 +288,7 @@ replace ( // initia custom replace ( - github.com/cometbft/cometbft => github.com/initia-labs/cometbft v0.0.0-20241113064430-a371e2dc387f + github.com/cometbft/cometbft => github.com/initia-labs/cometbft v0.0.0-20241203094427-a9f2e56c0275 github.com/cosmos/ibc-go/v8 => github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d github.com/ethereum/go-ethereum => github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb diff --git a/go.sum b/go.sum index ef9ead82..dec22bc0 100644 --- a/go.sum +++ b/go.sum @@ -1437,8 +1437,8 @@ github.com/initia-labs/OPinit v0.6.1 h1:G9ebeYeqPlV9Z2s3JdSWfwQAUgIM+nhkcA8xSJUM github.com/initia-labs/OPinit v0.6.1/go.mod h1:gDpCh4Zx94mihwgzP/PLav8eVHLroZBu3dFyzCy8iIs= github.com/initia-labs/OPinit/api v0.6.0 h1:Q3hDHpTd9EqlDfY/OryCKIwuXYWJxGJdGfJicV1RjL4= github.com/initia-labs/OPinit/api v0.6.0/go.mod h1:gHK6DEWb3/DqQD5LjKirUx9jilAh2UioXanoQdgqVfU= -github.com/initia-labs/cometbft v0.0.0-20241113064430-a371e2dc387f h1:PpYBvJ0L58bAgH7KwS/7GBEUphLnhf4fnTLua9uOov8= -github.com/initia-labs/cometbft v0.0.0-20241113064430-a371e2dc387f/go.mod h1:y7+6kPknafzWlkSMCekzXC81wpRf1pcVAUnO0wRy9lQ= +github.com/initia-labs/cometbft v0.0.0-20241203094427-a9f2e56c0275 h1:kfOuFBZ09FVD7P75rXkpcm1nAh5mq5xNP6DXtPpOOiA= +github.com/initia-labs/cometbft v0.0.0-20241203094427-a9f2e56c0275/go.mod h1:y7+6kPknafzWlkSMCekzXC81wpRf1pcVAUnO0wRy9lQ= github.com/initia-labs/cometbft-client v0.0.0-20240924071428-ef115cefa07e h1:k+pg63SFozCAK4LZFSiZtof6z69Tlu0O/Zftj1aAwes= github.com/initia-labs/cometbft-client v0.0.0-20240924071428-ef115cefa07e/go.mod h1:aVposiPW9FOUeAeJ7JjJRdE3g+L6i8YDxFn6Cv6+Az4= github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb h1:oyH9gg/4f7uMCIJYnSpp7wa1NrGjSMsXTtypUfrsPLU= diff --git a/indexer/abci.go b/indexer/abci.go index 1aa68eb4..d24b9c0a 100644 --- a/indexer/abci.go +++ b/indexer/abci.go @@ -210,5 +210,10 @@ func (e *EVMIndexerImpl) ListenFinalizeBlock(ctx context.Context, req abci.Reque // return err // } + // execute pruning only if retain height is set + if e.retainHeight > 0 { + e.doPrune(ctx, uint64(blockHeight)) + } + return nil } diff --git a/indexer/indexer.go b/indexer/indexer.go index 0bc6d95b..20d8d89d 100644 --- a/indexer/indexer.go +++ b/indexer/indexer.go @@ -2,6 +2,7 @@ package indexer import ( "context" + "sync/atomic" "time" "github.com/jellydator/ttlcache/v3" @@ -14,6 +15,7 @@ import ( dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/mempool" "github.com/ethereum/go-ethereum/common" @@ -58,7 +60,9 @@ type EVMIndexer interface { // EVMIndexerImpl implements EVMIndexer. type EVMIndexerImpl struct { - enabled bool + enabled bool + retainHeight uint64 + pruningRunning *atomic.Bool db dbm.DB logger log.Logger @@ -68,14 +72,18 @@ type EVMIndexerImpl struct { store *CacheStore evmKeeper *evmkeeper.Keeper - schema collections.Schema - TxMap collections.Map[[]byte, rpctypes.RPCTransaction] - TxReceiptMap collections.Map[[]byte, coretypes.Receipt] + schema collections.Schema + + // blocks BlockHeaderMap collections.Map[uint64, coretypes.Header] BlockAndIndexToTxHashMap collections.Map[collections.Pair[uint64, uint64], []byte] BlockHashToNumberMap collections.Map[[]byte, uint64] - TxHashToCosmosTxHash collections.Map[[]byte, []byte] - CosmosTxHashToTxHash collections.Map[[]byte, []byte] + + // txs + TxMap collections.Map[[]byte, rpctypes.RPCTransaction] + TxReceiptMap collections.Map[[]byte, coretypes.Receipt] + TxHashToCosmosTxHash collections.Map[[]byte, []byte] + CosmosTxHashToTxHash collections.Map[[]byte, []byte] blockChans []chan *coretypes.Header logsChans []chan []*coretypes.Log @@ -100,13 +108,20 @@ func NewEVMIndexer( store := NewCacheStore(dbadapter.Store{DB: db}, cfg.IndexerCacheSize) sb := collections.NewSchemaBuilderFromAccessor( func(ctx context.Context) corestoretypes.KVStore { + // if there is prune store in context, use it + if pruneStore := sdk.UnwrapSDKContext(ctx).Value(pruneStoreKey); pruneStore != nil { + return pruneStore.(corestoretypes.KVStore) + } + return store }, ) - logger.Info("EVM Indexer", "enable", !cfg.DisableIndexer) + logger.Info("EVM Indexer", "enable", !cfg.IndexerDisable) indexer := &EVMIndexerImpl{ - enabled: !cfg.DisableIndexer, + enabled: !cfg.IndexerDisable, + retainHeight: cfg.IndexerRetainHeight, + pruningRunning: &atomic.Bool{}, db: db, store: store, diff --git a/indexer/prune.go b/indexer/prune.go new file mode 100644 index 00000000..402705f7 --- /dev/null +++ b/indexer/prune.go @@ -0,0 +1,152 @@ +package indexer + +import ( + "context" + + "cosmossdk.io/collections" + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "golang.org/x/sync/errgroup" + + "github.com/ethereum/go-ethereum/common" + coretypes "github.com/ethereum/go-ethereum/core/types" +) + +const ( + pruneStoreKey = iota +) + +// doPrune triggers pruning in a goroutine. If pruning is already running, +// it does nothing. +func (e *EVMIndexerImpl) doPrune(ctx context.Context, height uint64) { + if running := e.pruningRunning.Swap(true); running { + return + } + + go func(ctx context.Context, height uint64) { + defer e.pruningRunning.Store(false) + if err := e.prune(ctx, height); err != nil { + e.logger.Error("failed to prune", "err", err) + } + + e.logger.Debug("prune finished", "height", height) + }(ctx, height) +} + +// prune removes old blocks and transactions from the indexer. +func (e *EVMIndexerImpl) prune(ctx context.Context, curHeight uint64) error { + // use branch context to perform batch operations + batchStore := e.store.store.CacheWrap() + ctx = sdk.UnwrapSDKContext(ctx).WithValue(pruneStoreKey, newCoreKVStore(interface{}(batchStore).(storetypes.KVStore))) + + minHeight := curHeight - e.retainHeight + if minHeight <= 0 || minHeight >= curHeight { + return nil + } + + g, ctx := errgroup.WithContext(ctx) + g.Go(func() error { + return e.pruneBlocks(ctx, minHeight) + }) + g.Go(func() error { + return e.pruneTxs(ctx, minHeight) + }) + + if err := g.Wait(); err != nil { + return err + } + + // write batch + batchStore.Write() + + return nil +} + +// pruneBlocks removes old block headers from the indexer. +func (e *EVMIndexerImpl) pruneBlocks(ctx context.Context, minHeight uint64) error { + // record block hashes + var blockHashes []common.Hash + rn := new(collections.Range[uint64]).EndInclusive(minHeight) + err := e.BlockHeaderMap.Walk(ctx, rn, func(key uint64, value coretypes.Header) (stop bool, err error) { + blockHashes = append(blockHashes, value.Hash()) + return false, nil + }) + if err != nil { + return err + } + + // clear block headers within range + err = e.BlockHeaderMap.Clear(ctx, rn) + if err != nil { + return err + } + + // clear block hash to number map + for _, blockHash := range blockHashes { + if err := e.BlockHashToNumberMap.Remove(ctx, blockHash.Bytes()); err != nil { + return err + } + } + + return nil +} + +// pruneTxs removes old transactions from the indexer. +func (e *EVMIndexerImpl) pruneTxs(ctx context.Context, minHeight uint64) error { + // record tx hashes + var txHashes []common.Hash + rnPair := collections.NewPrefixUntilPairRange[uint64, uint64](minHeight) + err := e.BlockAndIndexToTxHashMap.Walk(ctx, rnPair, func(key collections.Pair[uint64, uint64], txHashBz []byte) (bool, error) { + txHash := common.BytesToHash(txHashBz) + txHashes = append(txHashes, txHash) + return false, nil + }) + if err != nil { + return err + } + + // clear block txs within range + err = e.BlockAndIndexToTxHashMap.Clear(ctx, rnPair) + if err != nil { + return err + } + + // clear txs and receipts and cosmos tx hash mappings + for _, txHash := range txHashes { + if err := e.TxMap.Remove(ctx, txHash.Bytes()); err != nil { + return err + } + if err := e.TxReceiptMap.Remove(ctx, txHash.Bytes()); err != nil { + return err + } + if cosmosTxHash, err := e.TxHashToCosmosTxHash.Get(ctx, txHash.Bytes()); err == nil { + if err := e.TxHashToCosmosTxHash.Remove(ctx, txHash.Bytes()); err != nil { + return err + } + if err := e.CosmosTxHashToTxHash.Remove(ctx, cosmosTxHash); err != nil { + return err + } + } else if err != collections.ErrNotFound { + return err + } + } + + return nil +} + +//////////////////////// TESTING INTERFACE //////////////////////// + +// Set custom retain height +func (e *EVMIndexerImpl) SetRetainHeight(height uint64) { + e.retainHeight = height +} + +// Check if pruning is running +func (e *EVMIndexerImpl) IsPruningRunning() bool { + return e.pruningRunning.Load() +} + +// Clear cache for testing +func (e *EVMIndexerImpl) ClearCache() error { + return e.store.cache.Reset() +} diff --git a/indexer/prune_test.go b/indexer/prune_test.go new file mode 100644 index 00000000..cbee5da9 --- /dev/null +++ b/indexer/prune_test.go @@ -0,0 +1,109 @@ +package indexer_test + +import ( + "math/big" + "testing" + "time" + + "cosmossdk.io/collections" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + + evmindexer "github.com/initia-labs/minievm/indexer" + "github.com/initia-labs/minievm/tests" + evmtypes "github.com/initia-labs/minievm/x/evm/types" +) + +func Test_PruneIndexer(t *testing.T) { + app, addrs, privKeys := tests.CreateApp(t) + indexer := app.EVMIndexer().(*evmindexer.EVMIndexerImpl) + defer app.Close() + + // set retain height to 1, only last block is indexed + indexer.SetRetainHeight(1) + + tx, evmTxHash := tests.GenerateCreateERC20Tx(t, app, privKeys[0]) + _, finalizeRes := tests.ExecuteTxs(t, app, tx) + tests.CheckTxResult(t, finalizeRes.TxResults[0], true) + + events := finalizeRes.TxResults[0].Events + createEvent := events[len(events)-3] + require.Equal(t, evmtypes.EventTypeContractCreated, createEvent.GetType()) + + contractAddr, err := hexutil.Decode(createEvent.Attributes[0].Value) + require.NoError(t, err) + + // listen finalize block + ctx, err := app.CreateQueryContext(0, false) + require.NoError(t, err) + + // check the tx is indexed + evmTx, err := indexer.TxByHash(ctx, evmTxHash) + require.NoError(t, err) + require.NotNil(t, evmTx) + + // mint 1_000_000 tokens to the first address + tx, evmTxHash2 := tests.GenerateMintERC20Tx(t, app, privKeys[0], common.BytesToAddress(contractAddr), addrs[0], new(big.Int).SetUint64(1_000_000_000_000)) + finalizeReq, finalizeRes := tests.ExecuteTxs(t, app, tx) + tests.CheckTxResult(t, finalizeRes.TxResults[0], true) + + // wait for pruning + for { + if indexer.IsPruningRunning() { + time.Sleep(100 * time.Millisecond) + } else { + break + } + } + + // clear cache + indexer.ClearCache() + + // listen finalize block + ctx, err = app.CreateQueryContext(0, false) + require.NoError(t, err) + + // check the block header is indexed + header, err := indexer.BlockHeaderByNumber(ctx, uint64(finalizeReq.Height)) + require.NoError(t, err) + require.NotNil(t, header) + require.Equal(t, finalizeReq.Height, header.Number.Int64()) + + // previous block should be pruned + header, err = indexer.BlockHeaderByNumber(ctx, uint64(finalizeReq.Height-1)) + require.ErrorIs(t, err, collections.ErrNotFound) + require.Nil(t, header) + + // check the tx is indexed + evmTx, err = indexer.TxByHash(ctx, evmTxHash2) + require.NoError(t, err) + require.NotNil(t, evmTx) + + // but the first tx should be pruned + evmTx, err = indexer.TxByHash(ctx, evmTxHash) + require.ErrorIs(t, err, collections.ErrNotFound) + require.Nil(t, evmTx) + + // check the receipt is indexed + receipt, err := indexer.TxReceiptByHash(ctx, evmTxHash2) + require.NoError(t, err) + require.NotNil(t, receipt) + + // check the receipt is pruned + _, err = indexer.TxReceiptByHash(ctx, evmTxHash) + require.ErrorIs(t, err, collections.ErrNotFound) + + // check cosmos tx hash is indexed + cosmosTxHash, err := indexer.CosmosTxHashByTxHash(ctx, evmTxHash2) + require.NoError(t, err) + require.NotNil(t, cosmosTxHash) + evmTxHash3, err := indexer.TxHashByCosmosTxHash(ctx, cosmosTxHash) + require.NoError(t, err) + require.Equal(t, evmTxHash2, evmTxHash3) + + // check cosmos tx hash is pruned + _, err = indexer.CosmosTxHashByTxHash(ctx, evmTxHash) + require.ErrorIs(t, err, collections.ErrNotFound) +} diff --git a/indexer/store.go b/indexer/store.go index 0e952f4a..e7f08a43 100644 --- a/indexer/store.go +++ b/indexer/store.go @@ -4,6 +4,7 @@ import ( "context" corestoretypes "cosmossdk.io/core/store" + "cosmossdk.io/store" cachekv "cosmossdk.io/store/cachekv" storetypes "cosmossdk.io/store/types" @@ -119,3 +120,56 @@ func (c CacheStore) ReverseIterator(start, end []byte) (storetypes.Iterator, err func (c CacheStore) Write() { c.store.Write() } + +// coreKVStore is a wrapper of Core/Store kvstore interface +// Remove after https://github.com/cosmos/cosmos-sdk/issues/14714 is closed +type coreKVStore struct { + kvStore storetypes.KVStore +} + +// newCoreKVStore returns a wrapper of Core/Store kvstore interface +// Remove once store migrates to core/store kvstore interface +func newCoreKVStore(store storetypes.KVStore) corestoretypes.KVStore { + return coreKVStore{kvStore: store} +} + +// Get returns nil iff key doesn't exist. Errors on nil key. +func (store coreKVStore) Get(key []byte) ([]byte, error) { + return store.kvStore.Get(key), nil +} + +// Has checks if a key exists. Errors on nil key. +func (store coreKVStore) Has(key []byte) (bool, error) { + return store.kvStore.Has(key), nil +} + +// Set sets the key. Errors on nil key or value. +func (store coreKVStore) Set(key, value []byte) error { + store.kvStore.Set(key, value) + return nil +} + +// Delete deletes the key. Errors on nil key. +func (store coreKVStore) Delete(key []byte) error { + store.kvStore.Delete(key) + return nil +} + +// Iterator iterates over a domain of keys in ascending order. End is exclusive. +// Start must be less than end, or the Iterator is invalid. +// Iterator must be closed by caller. +// To iterate over entire domain, use store.Iterator(nil, nil) +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +// Exceptionally allowed for cachekv.Store, safe to write in the modules. +func (store coreKVStore) Iterator(start, end []byte) (store.Iterator, error) { + return store.kvStore.Iterator(start, end), nil +} + +// ReverseIterator iterates over a domain of keys in descending order. End is exclusive. +// Start must be less than end, or the Iterator is invalid. +// Iterator must be closed by caller. +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +// Exceptionally allowed for cachekv.Store, safe to write in the modules. +func (store coreKVStore) ReverseIterator(start, end []byte) (store.Iterator, error) { + return store.kvStore.ReverseIterator(start, end), nil +} diff --git a/integration-tests/go.mod b/integration-tests/go.mod index c2214167..ba70ebd4 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -10,7 +10,7 @@ require ( github.com/cosmos/cosmos-sdk v0.50.10 github.com/cosmos/ibc-go/v8 v8.5.0 github.com/ethereum/go-ethereum v1.14.11 - github.com/initia-labs/initia v0.6.1 + github.com/initia-labs/initia v0.6.4 github.com/initia-labs/minievm v0.5.2 github.com/stretchr/testify v1.9.0 ) @@ -153,7 +153,7 @@ require ( github.com/initia-labs/kvindexer/submodules/evm-tx v0.1.2 // indirect github.com/initia-labs/kvindexer/submodules/pair v0.1.1 // indirect github.com/initia-labs/kvindexer/submodules/tx v0.1.0 // indirect - github.com/initia-labs/movevm v0.6.0 // indirect + github.com/initia-labs/movevm v0.6.1 // indirect github.com/jellydator/ttlcache/v3 v3.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -271,7 +271,7 @@ replace ( // initia custom replace ( - github.com/cometbft/cometbft => github.com/initia-labs/cometbft v0.0.0-20241113064430-a371e2dc387f + github.com/cometbft/cometbft => github.com/initia-labs/cometbft v0.0.0-20241203094427-a9f2e56c0275 github.com/cosmos/ibc-go/v8 => github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d github.com/ethereum/go-ethereum => github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 89153f35..e063ff23 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1397,14 +1397,14 @@ github.com/initia-labs/OPinit v0.6.1 h1:G9ebeYeqPlV9Z2s3JdSWfwQAUgIM+nhkcA8xSJUM github.com/initia-labs/OPinit v0.6.1/go.mod h1:gDpCh4Zx94mihwgzP/PLav8eVHLroZBu3dFyzCy8iIs= github.com/initia-labs/OPinit/api v0.6.0 h1:Q3hDHpTd9EqlDfY/OryCKIwuXYWJxGJdGfJicV1RjL4= github.com/initia-labs/OPinit/api v0.6.0/go.mod h1:gHK6DEWb3/DqQD5LjKirUx9jilAh2UioXanoQdgqVfU= -github.com/initia-labs/cometbft v0.0.0-20241113064430-a371e2dc387f h1:PpYBvJ0L58bAgH7KwS/7GBEUphLnhf4fnTLua9uOov8= -github.com/initia-labs/cometbft v0.0.0-20241113064430-a371e2dc387f/go.mod h1:y7+6kPknafzWlkSMCekzXC81wpRf1pcVAUnO0wRy9lQ= +github.com/initia-labs/cometbft v0.0.0-20241203094427-a9f2e56c0275 h1:kfOuFBZ09FVD7P75rXkpcm1nAh5mq5xNP6DXtPpOOiA= +github.com/initia-labs/cometbft v0.0.0-20241203094427-a9f2e56c0275/go.mod h1:y7+6kPknafzWlkSMCekzXC81wpRf1pcVAUnO0wRy9lQ= github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb h1:oyH9gg/4f7uMCIJYnSpp7wa1NrGjSMsXTtypUfrsPLU= github.com/initia-labs/evm v0.0.0-20241108055119-3d312736d7fb/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d h1:TLq8lB1PtQ0pjGf+bN8YgGVeLMuytZ26SBGMOs1seKY= github.com/initia-labs/ibc-go/v8 v8.0.0-20240802003717-19c0b4ad450d/go.mod h1:zh6x1osR0hNvEcFrC/lhGD08sMfQmr9wHVvZ/mRWMCs= -github.com/initia-labs/initia v0.6.1 h1:lJdaNp6UWwars+DCumF2L9vRmdcS+fRAMUG7f5SR6pA= -github.com/initia-labs/initia v0.6.1/go.mod h1:sQYysCP3GScSmPxNLFhnjBwVVzZFtP7EeECQQ1wzPOk= +github.com/initia-labs/initia v0.6.4 h1:61ERWEW888b0IEqI9LQUkD1ztmOtRY74nOPsuKVnJWM= +github.com/initia-labs/initia v0.6.4/go.mod h1:d8D+AbkOVktXTx9gnRL7iN0dA/+sG98uz52zRSEhh+0= github.com/initia-labs/kvindexer v0.1.9 h1:rv/zD8VMU0+P7f+rTtYefIG93f3vRy55JqNK+fohQr8= github.com/initia-labs/kvindexer v0.1.9/go.mod h1:OV85HaQ9KVrg+zGPUlxT9RF9nAaM3Yq4/3MoHqGqhWk= github.com/initia-labs/kvindexer/submodules/block v0.1.0 h1:y+EXnksd/I2F96mzIoQA64nZUZON2P+99YrSzeLCLoY= @@ -1415,8 +1415,8 @@ github.com/initia-labs/kvindexer/submodules/pair v0.1.1 h1:o151gA4jIbqEl+pWTOCiz github.com/initia-labs/kvindexer/submodules/pair v0.1.1/go.mod h1:8X1GE1ZLkH7z8TKb5MUh7UClTkcqVFIwXIIRdsqeUZY= github.com/initia-labs/kvindexer/submodules/tx v0.1.0 h1:6kbf6wmzXPN0XCQLasiFgq1AlZHkt5K3/ZG+IWw1nNs= github.com/initia-labs/kvindexer/submodules/tx v0.1.0/go.mod h1:i0XeLbLa6xdgTR01WF8kaAO50vMmwxbeq0fKexwpFHU= -github.com/initia-labs/movevm v0.6.0 h1:46JjDfOId6hfeoqYqKWTzPeb5ESQzzm8AhhGWYnFOmE= -github.com/initia-labs/movevm v0.6.0/go.mod h1:aUWdvFZPdULjJ2McQTE+mLnfnG3CLAz0TWJRFzFFUwg= +github.com/initia-labs/movevm v0.6.1 h1:g+nUX289tou8HaHkwvZIE7KzhVAi+fykpGORItw8j0E= +github.com/initia-labs/movevm v0.6.1/go.mod h1:sj/kXD7mUQASqogPTjqltIr4Uid3xxnlcbfiFvvqeXA= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc= diff --git a/x/evm/config/config.go b/x/evm/config/config.go index 1cde2a3f..2ce6e8ef 100644 --- a/x/evm/config/config.go +++ b/x/evm/config/config.go @@ -10,34 +10,41 @@ import ( const ( // DefaultContractSimulationGasLimit - default max simulation gas DefaultContractSimulationGasLimit = uint64(3_000_000) - // DefaultDisableIndexer is the default flag to disable indexer - DefaultDisableIndexer = false + // DefaultIndexerDisable is the default flag to disable indexer + DefaultIndexerDisable = false // DefaultIndexerCacheSize is the default maximum size (MiB) of the cache. DefaultIndexerCacheSize = 100 + // DefaultIndexerRetainHeight is the default height to retain indexer data. + DefaultIndexerRetainHeight = uint64(0) ) const ( flagContractSimulationGasLimit = "evm.contract-simulation-gas-limit" - flagDisableIndexer = "evm.disable-indexer" + flagIndexerDisable = "evm.indexer-disable" flagIndexerCacheSize = "evm.indexer-cache-size" + flagIndexerRetainHeight = "evm.indexer-retain-height" ) // EVMConfig is the extra config required for evm type EVMConfig struct { // ContractSimulationGasLimit is the maximum gas amount can be used in a tx simulation call. ContractSimulationGasLimit uint64 `mapstructure:"contract-simulation-gas-limit"` - // DisableIndexer is the flag to disable indexer - DisableIndexer bool `mapstructure:"disable-indexer"` + // IndexerDisable is the flag to disable indexer + IndexerDisable bool `mapstructure:"indexer-disable"` // IndexerCacheSize is the maximum size (MiB) of the cache. IndexerCacheSize int `mapstructure:"indexer-cache-size"` + // IndexerRetainHeight is the height to retain indexer data. + // If 0, it will retain all data. + IndexerRetainHeight uint64 `mapstructure:"indexer-retain-height"` } // DefaultEVMConfig returns the default settings for EVMConfig func DefaultEVMConfig() EVMConfig { return EVMConfig{ ContractSimulationGasLimit: DefaultContractSimulationGasLimit, - DisableIndexer: DefaultDisableIndexer, + IndexerDisable: DefaultIndexerDisable, IndexerCacheSize: DefaultIndexerCacheSize, + IndexerRetainHeight: DefaultIndexerRetainHeight, } } @@ -45,16 +52,18 @@ func DefaultEVMConfig() EVMConfig { func GetConfig(appOpts servertypes.AppOptions) EVMConfig { return EVMConfig{ ContractSimulationGasLimit: cast.ToUint64(appOpts.Get(flagContractSimulationGasLimit)), - DisableIndexer: cast.ToBool(appOpts.Get(flagDisableIndexer)), + IndexerDisable: cast.ToBool(appOpts.Get(flagIndexerDisable)), IndexerCacheSize: cast.ToInt(appOpts.Get(flagIndexerCacheSize)), + IndexerRetainHeight: cast.ToUint64(appOpts.Get(flagIndexerRetainHeight)), } } // AddConfigFlags implements servertypes.EVMConfigFlags interface. func AddConfigFlags(startCmd *cobra.Command) { startCmd.Flags().Uint64(flagContractSimulationGasLimit, DefaultContractSimulationGasLimit, "Maximum simulation gas amount for evm contract execution") - startCmd.Flags().Bool(flagDisableIndexer, DefaultDisableIndexer, "Disable evm indexer") + startCmd.Flags().Bool(flagIndexerDisable, DefaultIndexerDisable, "Disable evm indexer") startCmd.Flags().Int(flagIndexerCacheSize, DefaultIndexerCacheSize, "Maximum size (MiB) of the indexer cache") + startCmd.Flags().Uint64(flagIndexerRetainHeight, DefaultIndexerRetainHeight, "Height to retain indexer data") } // DefaultConfigTemplate default config template for evm @@ -68,10 +77,14 @@ const DefaultConfigTemplate = ` # The maximum gas amount can be used in a tx simulation call. contract-simulation-gas-limit = "{{ .EVMConfig.ContractSimulationGasLimit }}" -# DisableIndexer is the flag to disable indexer. If true, evm jsonrpc queries will return +# IndexerDisable is the flag to disable indexer. If true, evm jsonrpc queries will return # empty results for block, tx, and receipt queries. -disable-indexer = {{ .EVMConfig.DisableIndexer }} +indexer-disable = {{ .EVMConfig.IndexerDisable }} # IndexerCacheSize is the maximum size (MiB) of the cache for evm indexer. indexer-cache-size = {{ .EVMConfig.IndexerCacheSize }} + +# IndexerRetainHeight is the height to retain indexer data. +# If 0, it will retain all data. +indexer-retain-height = {{ .EVMConfig.IndexerRetainHeight }} `