From e58f02a8342b2ae8864e8bf195034e66b9578632 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 18 Sep 2024 06:53:58 -0400 Subject: [PATCH 01/28] Archive Node Online Migration --- app/test_state_store.go | 20 +++++++++ go.mod | 2 +- tools/migration/ss/migrator.go | 82 ++++++++++++++++++++++------------ 3 files changed, 74 insertions(+), 30 deletions(-) diff --git a/app/test_state_store.go b/app/test_state_store.go index 15b4d63e1..a5b071145 100644 --- a/app/test_state_store.go +++ b/app/test_state_store.go @@ -244,6 +244,26 @@ func (s *InMemoryStateStore) RawImport(ch <-chan types.RawSnapshotNode) error { return nil } +func (s *InMemoryStateStore) SetLatestMigratedModule(module string) error { + // TODO: Add set call here + return nil +} + +func (s *InMemoryStateStore) GetLatestMigratedModule() (string, error) { + // TODO: Add get call here + return "", nil +} + +func (s *InMemoryStateStore) SetLatestMigratedKey(key []byte) error { + // TODO: Add set call here + return nil +} + +func (s *InMemoryStateStore) GetLatestMigratedKey() ([]byte, error) { + // TODO: Add get call here + return nil, nil +} + func (s *InMemoryStateStore) Prune(version int64) error { s.mu.Lock() defer s.mu.Unlock() diff --git a/go.mod b/go.mod index 5d794e01b..068e018ec 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.2 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b 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.44 + github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.45-0.20240918104613-6c0900823891 // 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.8 diff --git a/tools/migration/ss/migrator.go b/tools/migration/ss/migrator.go index cb4e42bfc..2e08a0900 100644 --- a/tools/migration/ss/migrator.go +++ b/tools/migration/ss/migrator.go @@ -3,6 +3,7 @@ package ss import ( "bytes" "fmt" + "time" "github.com/cosmos/iavl" "github.com/sei-protocol/sei-db/config" @@ -43,36 +44,42 @@ func NewMigrator(homeDir string, db dbm.DB) *Migrator { } func (m *Migrator) Migrate(version int64, homeDir string) error { - // TODO: Read in capacity of this buffered channel as param ch := make(chan types.RawSnapshotNode, 1000) errCh := make(chan error, 2) - fmt.Println("Beginning Migration...") + // Get the latest key, if any, to resume from + latestKey, err := m.stateStore.GetLatestMigratedKey() + if err != nil { + return fmt.Errorf("failed to get latest key: %w", err) + } + + latestModule, err := m.stateStore.GetLatestMigratedModule() + if err != nil { + return fmt.Errorf("failed to get latest module: %w", err) + } - // Goroutine to iterate through iavl and export leaf nodes + fmt.Println("Starting migration...") + + // Goroutine to iterate through IAVL and export leaf nodes go func() { defer close(ch) - errCh <- ExportLeafNodes(m.iavlDB, ch) + errCh <- ExportLeafNodesFromKey(m.iavlDB, ch, latestKey, latestModule) }() + // Import nodes into PebbleDB go func() { errCh <- m.stateStore.RawImport(ch) }() - // Block on completion of both goroutines + // Block until both processes complete for i := 0; i < 2; i++ { if err := <-errCh; err != nil { return err } } - // Set latest version - err := m.stateStore.SetLatestVersion(version) - if err != nil { - return err - } - - return nil + // Set latest version in the database + return m.stateStore.SetLatestVersion(version) } func (m *Migrator) Verify(version int64) error { @@ -113,40 +120,52 @@ func (m *Migrator) Verify(version int64) error { return verifyErr } -// Export leaf nodes of iavl -func ExportLeafNodes(db dbm.DB, ch chan<- types.RawSnapshotNode) error { - // Module by module, TODO: Potentially parallelize +func ExportLeafNodesFromKey(db dbm.DB, ch chan<- types.RawSnapshotNode, startKey []byte, startModule string) error { count := 0 leafNodeCount := 0 - fmt.Println("Scanning database and exporting leaf nodes...") + fmt.Println("ExportLeafNodesFromKey - Scanning database and exporting leaf nodes...") + + startTimeTotal := time.Now() // Start measuring total time for _, module := range modules { - fmt.Printf("Iterating through %s module...\n", module) + if module != startModule && startModule != "" { + continue + } + startTimeModule := time.Now() // Measure time for each module + fmt.Printf("ExportLeafNodesFromKey - Iterating through %s module...\n", module) - // Can't use the previous, have to create an inner prefixDB := dbm.NewPrefixDB(db, []byte(buildRawPrefix(module))) - itr, err := prefixDB.Iterator(nil, nil) + var itr dbm.Iterator + var err error + + // If there is a starting key, seek to it, otherwise start from the beginning + if startKey != nil && bytes.HasPrefix(startKey, []byte(buildRawPrefix(module))) { + itr, err = prefixDB.Iterator(startKey, nil) // Start from the latest key + } else { + itr, err = prefixDB.Iterator(nil, nil) // Start from the beginning + } + if err != nil { - fmt.Printf("error Export Leaf Nodes %+v\n", err) + fmt.Printf("ExportLeafNodesFromKey - Error creating iterator: %+v\n", err) return fmt.Errorf("failed to create iterator: %w", err) } defer itr.Close() + startTimeBatch := time.Now() // Measure time for every 10,000 iterations + for ; itr.Valid(); itr.Next() { value := bytes.Clone(itr.Value()) node, err := iavl.MakeNode(value) - if err != nil { - fmt.Printf("failed to make node err: %+v\n", err) + fmt.Printf("ExportLeafNodesFromKey - Failed to make node: %+v\n", err) return fmt.Errorf("failed to make node: %w", err) } - // leaf node + // Only export leaf nodes if node.GetHeight() == 0 { leafNodeCount++ ch <- types.RawSnapshotNode{ - // TODO: Likely need to clone StoreKey: module, Key: node.GetNodeKey(), Value: node.GetValue(), @@ -156,20 +175,25 @@ func ExportLeafNodes(db dbm.DB, ch chan<- types.RawSnapshotNode) error { count++ if count%10000 == 0 { - fmt.Printf("Total scanned: %d, leaf nodes exported: %d\n", count, leafNodeCount) + batchDuration := time.Since(startTimeBatch) + fmt.Printf("ExportLeafNodesFromKey - Last 10,000 iterations took: %v. Total scanned: %d, leaf nodes exported: %d\n", batchDuration, count, leafNodeCount) + + startTimeBatch = time.Now() // Reset the start time for the next batch } } - fmt.Printf("Finished scanning module %s Total scanned: %d, leaf nodes exported: %d\n", module, count, leafNodeCount) - if err := itr.Error(); err != nil { - fmt.Printf("iterator error: %+v\n", err) + fmt.Printf("Iterator error: %+v\n", err) return fmt.Errorf("iterator error: %w", err) } + moduleDuration := time.Since(startTimeModule) + fmt.Printf("ExportLeafNodesFromKey - Finished scanning module %s. Time taken: %v. Total scanned: %d, leaf nodes exported: %d\n", module, moduleDuration, count, leafNodeCount) } - fmt.Printf("DB contains %d entries, exported %d leaf nodes\n", count, leafNodeCount) + totalDuration := time.Since(startTimeTotal) + fmt.Printf("ExportLeafNodesFromKey - DB scanning completed. Total time taken: %v. Total entries scanned: %d, leaf nodes exported: %d\n", totalDuration, count, leafNodeCount) + return nil } From 27a16763f704e053c6cf73a620acc8f561002cda Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 23 Sep 2024 10:25:27 -0400 Subject: [PATCH 02/28] Add migrate-iavl flag for online migration --- app/app.go | 7 ++++++- app/seidb.go | 7 ++++--- cmd/seid/cmd/root.go | 20 +++++++++++++++++++- tools/migration/cmd/cmd.go | 31 +++++++++++++++++++++++++------ tools/migration/ss/migrator.go | 14 +------------- 5 files changed, 55 insertions(+), 24 deletions(-) diff --git a/app/app.go b/app/app.go index 580aef2d4..cb2e6136d 100644 --- a/app/app.go +++ b/app/app.go @@ -368,6 +368,7 @@ type App struct { genesisImportConfig genesistypes.GenesisImportConfig + stateStore seidb.StateStore receiptStore seidb.StateStore } @@ -396,7 +397,7 @@ func New( cdc := encodingConfig.Amino interfaceRegistry := encodingConfig.InterfaceRegistry - bAppOptions := SetupSeiDB(logger, homePath, appOpts, baseAppOptions) + bAppOptions, stateStore := SetupSeiDB(logger, homePath, appOpts, baseAppOptions) bApp := baseapp.NewBaseApp(AppName, logger, db, encodingConfig.TxConfig.TxDecoder(), tmConfig, appOpts, bAppOptions...) bApp.SetCommitMultiStoreTracer(traceStore) @@ -429,6 +430,7 @@ func New( versionInfo: version.NewInfo(), metricCounter: &map[string]float32{}, encodingConfig: encodingConfig, + stateStore: stateStore, } for _, option := range appOptions { @@ -1064,6 +1066,9 @@ func (app *App) Name() string { return app.BaseApp.Name() } // GetBaseApp returns the base app of the application func (app App) GetBaseApp() *baseapp.BaseApp { return app.BaseApp } +// GetStateStore returns the state store of the application +func (app App) GetStateStore() seidb.StateStore { return app.stateStore } + // BeginBlocker application updates every begin block func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { metrics.GaugeSeidVersionAndCommit(app.versionInfo.Version, app.versionInfo.GitCommit) diff --git a/app/seidb.go b/app/seidb.go index a50614639..5c25b5a34 100644 --- a/app/seidb.go +++ b/app/seidb.go @@ -7,6 +7,7 @@ import ( servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/storev2/rootmulti" "github.com/sei-protocol/sei-db/config" + seidb "github.com/sei-protocol/sei-db/ss/types" "github.com/spf13/cast" "github.com/tendermint/tendermint/libs/log" ) @@ -40,11 +41,11 @@ func SetupSeiDB( homePath string, appOpts servertypes.AppOptions, baseAppOptions []func(*baseapp.BaseApp), -) []func(*baseapp.BaseApp) { +) ([]func(*baseapp.BaseApp), seidb.StateStore) { scEnabled := cast.ToBool(appOpts.Get(FlagSCEnable)) if !scEnabled { logger.Info("SeiDB is disabled, falling back to IAVL") - return baseAppOptions + return baseAppOptions, nil } logger.Info("SeiDB SC is enabled, running node with StoreV2 commit store") scConfig := parseSCConfigs(appOpts) @@ -63,7 +64,7 @@ func SetupSeiDB( }, }, baseAppOptions...) - return baseAppOptions + return baseAppOptions, cms.GetStateStore() } func parseSCConfigs(appOpts servertypes.AppOptions) config.StateCommitConfig { diff --git a/cmd/seid/cmd/root.go b/cmd/seid/cmd/root.go index df8ed1fe1..5e0b927c5 100644 --- a/cmd/seid/cmd/root.go +++ b/cmd/seid/cmd/root.go @@ -26,6 +26,7 @@ import ( servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/snapshots" "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/rootmulti" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/utils/tracing" aclkeeper "github.com/cosmos/cosmos-sdk/x/accesscontrol/keeper" @@ -38,6 +39,7 @@ import ( "github.com/sei-protocol/sei-chain/app/params" "github.com/sei-protocol/sei-chain/evmrpc" "github.com/sei-protocol/sei-chain/tools" + "github.com/sei-protocol/sei-chain/tools/migration/ss" "github.com/sei-protocol/sei-chain/x/evm/blocktest" "github.com/sei-protocol/sei-chain/x/evm/querier" "github.com/sei-protocol/sei-chain/x/evm/replay" @@ -220,6 +222,7 @@ func txCommand() *cobra.Command { func addModuleInitFlags(startCmd *cobra.Command) { crisis.AddModuleInitFlags(startCmd) + startCmd.Flags().Bool("migrate-iavl", false, "Run migration of IAVL data store to SeiDB State Store") } // newApp creates a new Cosmos SDK app @@ -266,7 +269,7 @@ func newApp( // This makes it such that the wasm VM gas converts to sdk gas at a 6.66x rate vs that of the previous multiplier wasmGasRegisterConfig.GasMultiplier = 21_000_000 - return app.New( + app := app.New( logger, db, traceStore, @@ -302,6 +305,21 @@ func newApp( baseapp.SetSnapshotDirectory(cast.ToString(appOpts.Get(server.FlagStateSyncSnapshotDir))), baseapp.SetOccEnabled(cast.ToBool(appOpts.Get(baseapp.FlagOccEnabled))), ) + + // Start migration if --migrate flag is set + if cast.ToBool(appOpts.Get("migrate-iavl")) { + go func() { + homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) + stateStore := app.GetStateStore() + latestVersion := rootmulti.GetLatestVersion(db) + migrator := ss.NewMigrator(homeDir, db, stateStore) + if err := migrator.Migrate(latestVersion, homeDir); err != nil { + panic(err) + } + }() + } + + return app } // appExport creates a new simapp (optionally at a given height) diff --git a/tools/migration/cmd/cmd.go b/tools/migration/cmd/cmd.go index d1ff27a28..578265ffd 100644 --- a/tools/migration/cmd/cmd.go +++ b/tools/migration/cmd/cmd.go @@ -7,7 +7,10 @@ import ( "github.com/cosmos/cosmos-sdk/store/rootmulti" "github.com/sei-protocol/sei-chain/tools/migration/sc" "github.com/sei-protocol/sei-chain/tools/migration/ss" + "github.com/sei-protocol/sei-db/config" + sstypes "github.com/sei-protocol/sei-db/ss" "github.com/spf13/cobra" + "github.com/tendermint/tendermint/libs/log" dbm "github.com/tendermint/tm-db" ) @@ -51,13 +54,16 @@ func migrateSC(version int64, homeDir string, db dbm.DB) error { } func migrateSS(version int64, homeDir string, db dbm.DB) error { - migrator := ss.NewMigrator(homeDir, db) - return migrator.Migrate(version, homeDir) -} + ssConfig := config.DefaultStateStoreConfig() + ssConfig.Enable = true -func verifySS(version int64, homeDir string, db dbm.DB) error { - migrator := ss.NewMigrator(homeDir, db) - return migrator.Verify(version) + stateStore, err := sstypes.NewStateStore(log.NewNopLogger(), homeDir, ssConfig) + if err != nil { + return err + } + + migrator := ss.NewMigrator(homeDir, db, stateStore) + return migrator.Migrate(version, homeDir) } func VerifyMigrationCmd() *cobra.Command { @@ -97,3 +103,16 @@ func verify(cmd *cobra.Command, _ []string) { fmt.Println("Verification Succeeded") } + +func verifySS(version int64, homeDir string, db dbm.DB) error { + ssConfig := config.DefaultStateStoreConfig() + ssConfig.Enable = true + + stateStore, err := sstypes.NewStateStore(log.NewNopLogger(), homeDir, ssConfig) + if err != nil { + return err + } + + migrator := ss.NewMigrator(homeDir, db, stateStore) + return migrator.Verify(version) +} diff --git a/tools/migration/ss/migrator.go b/tools/migration/ss/migrator.go index 2e08a0900..4fde4aa41 100644 --- a/tools/migration/ss/migrator.go +++ b/tools/migration/ss/migrator.go @@ -6,10 +6,7 @@ import ( "time" "github.com/cosmos/iavl" - "github.com/sei-protocol/sei-db/config" - "github.com/sei-protocol/sei-db/ss" "github.com/sei-protocol/sei-db/ss/types" - "github.com/tendermint/tendermint/libs/log" dbm "github.com/tendermint/tm-db" ) @@ -27,16 +24,7 @@ var modules = []string{ "wasm", "aclaccesscontrol", "oracle", "epoch", "mint", "acc", "bank", "feegrant", "staking", "distribution", "slashing", "gov", "params", "ibc", "upgrade", "evidence", "transfer", "tokenfactory", } -func NewMigrator(homeDir string, db dbm.DB) *Migrator { - // TODO: Pass in more configs outside default, in particular ImportNumWorkers - ssConfig := config.DefaultStateStoreConfig() - ssConfig.Enable = true - - stateStore, err := ss.NewStateStore(log.NewNopLogger(), homeDir, ssConfig) - if err != nil { - panic(err) - } - +func NewMigrator(homeDir string, db dbm.DB, stateStore types.StateStore) *Migrator { return &Migrator{ iavlDB: db, stateStore: stateStore, From c28c7830e7a2526b01e96a735d3abe5c64dd7ae1 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Tue, 24 Sep 2024 23:35:33 -0400 Subject: [PATCH 03/28] Update sei cosmos --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 068e018ec..6686daadb 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.2.4 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.37-0.20240923023912-aa7a702d42cc + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.37-0.20240925031313-e61849179955 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.2.0 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.2 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b diff --git a/go.sum b/go.sum index 38d948197..69fcb61fe 100644 --- a/go.sum +++ b/go.sum @@ -1347,10 +1347,10 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b/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.37-0.20240923023912-aa7a702d42cc h1:srWLbsoS0NYBIl8OjZOFuPmIeqf+fJTkfsK39MmG3+k= -github.com/sei-protocol/sei-cosmos v0.3.37-0.20240923023912-aa7a702d42cc/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= -github.com/sei-protocol/sei-db v0.0.44 h1:HMgcyDTQlmXdJysHJxmIo66EKeXn1CSQT9qXDnxjJgI= -github.com/sei-protocol/sei-db v0.0.44/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= +github.com/sei-protocol/sei-cosmos v0.3.37-0.20240925031313-e61849179955 h1:FXeQsPJSb+EOKTBcWdrShJ1FwyxlR7Yum2uXBURzXLk= +github.com/sei-protocol/sei-cosmos v0.3.37-0.20240925031313-e61849179955/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= +github.com/sei-protocol/sei-db v0.0.45-0.20240918104613-6c0900823891 h1:gf23XvhKmCRyMvzEe2puRp3ZuXvw3noqF1cL1XxMQHQ= +github.com/sei-protocol/sei-db v0.0.45-0.20240918104613-6c0900823891/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.2.0 h1:OisPjXiDT+oe+aeckzDEFgkZCYuUjHgs/PP8DPicN+I= github.com/sei-protocol/sei-iavl v0.2.0/go.mod h1:qRf8QYUPfrAO7K6VDB2B2l/N7K5L76OorioGBcJBIbw= github.com/sei-protocol/sei-ibc-go/v3 v3.3.2 h1:BaMZ6gjwqe3R/5dLmcJ1TkSZ3omcWy2TjaAZAeOJH44= From 3ac501fec8fe7026669be58f2a2d318a1fcb36bc Mon Sep 17 00:00:00 2001 From: Yiming Zang <50607998+yzang2019@users.noreply.github.com> Date: Tue, 24 Sep 2024 20:38:47 -0700 Subject: [PATCH 04/28] Add QMS for online migration (#1870) * Add QMS for online migration * Fix lint --------- Co-authored-by: kbhat1 --- app/seidb.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/seidb.go b/app/seidb.go index 5c25b5a34..5c7e2a38c 100644 --- a/app/seidb.go +++ b/app/seidb.go @@ -34,6 +34,8 @@ const ( // Other configs FlagSnapshotInterval = "state-sync.snapshot-interval" + FlagMigrateIAVL = "migrate-iavl" + FlagMigrateHeight = "migrate-height" ) func SetupSeiDB( @@ -58,8 +60,15 @@ func SetupSeiDB( // cms must be overridden before the other options, because they may use the cms, // make sure the cms aren't be overridden by the other options later on. cms := rootmulti.NewStore(homePath, logger, scConfig, ssConfig) + migrationEnabled := cast.ToBool(appOpts.Get(FlagMigrateIAVL)) + migrationHeight := cast.ToInt64(appOpts.Get(FlagMigrateHeight)) baseAppOptions = append([]func(*baseapp.BaseApp){ func(baseApp *baseapp.BaseApp) { + if migrationEnabled { + originalCMS := baseApp.CommitMultiStore() + baseApp.SetQueryMultiStore(originalCMS) + baseApp.SetMigrationHeight(migrationHeight) + } baseApp.SetCMS(cms) }, }, baseAppOptions...) From 30a83118c8b17a5ea2aec59b0ab2fdaa168edea5 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 25 Sep 2024 17:09:20 -0400 Subject: [PATCH 05/28] Add migrate-height flag to start cmd --- cmd/seid/cmd/root.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/seid/cmd/root.go b/cmd/seid/cmd/root.go index 5e0b927c5..81c7f8203 100644 --- a/cmd/seid/cmd/root.go +++ b/cmd/seid/cmd/root.go @@ -26,7 +26,6 @@ import ( servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/snapshots" "github.com/cosmos/cosmos-sdk/store" - "github.com/cosmos/cosmos-sdk/store/rootmulti" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/utils/tracing" aclkeeper "github.com/cosmos/cosmos-sdk/x/accesscontrol/keeper" @@ -223,6 +222,7 @@ func txCommand() *cobra.Command { func addModuleInitFlags(startCmd *cobra.Command) { crisis.AddModuleInitFlags(startCmd) startCmd.Flags().Bool("migrate-iavl", false, "Run migration of IAVL data store to SeiDB State Store") + startCmd.Flags().Int64("migrate-height", 0, "Height at which to start the migration") } // newApp creates a new Cosmos SDK app @@ -311,9 +311,9 @@ func newApp( go func() { homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) stateStore := app.GetStateStore() - latestVersion := rootmulti.GetLatestVersion(db) + migrationHeight := cast.ToInt64(appOpts.Get("migrate-height")) migrator := ss.NewMigrator(homeDir, db, stateStore) - if err := migrator.Migrate(latestVersion, homeDir); err != nil { + if err := migrator.Migrate(migrationHeight, homeDir); err != nil { panic(err) } }() From e75b2224e7b85abc83736a409caf510c32998966 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 7 Oct 2024 08:30:29 -0600 Subject: [PATCH 06/28] Bump seidb --- app/seidb.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- tools/migration/sc/migrator.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/seidb.go b/app/seidb.go index 5c7e2a38c..175d5c1a4 100644 --- a/app/seidb.go +++ b/app/seidb.go @@ -59,7 +59,7 @@ func SetupSeiDB( // cms must be overridden before the other options, because they may use the cms, // make sure the cms aren't be overridden by the other options later on. - cms := rootmulti.NewStore(homePath, logger, scConfig, ssConfig) + cms := rootmulti.NewStore(homePath, logger, scConfig, ssConfig, cast.ToBool(appOpts.Get("migrate-iavl"))) migrationEnabled := cast.ToBool(appOpts.Get(FlagMigrateIAVL)) migrationHeight := cast.ToInt64(appOpts.Get(FlagMigrateHeight)) baseAppOptions = append([]func(*baseapp.BaseApp){ diff --git a/go.mod b/go.mod index 6686daadb..9b7ba9b62 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.2.4 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.37-0.20240925031313-e61849179955 + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.37-0.20241007142359-ca29513f17aa github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.2.0 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.2 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b diff --git a/go.sum b/go.sum index 69fcb61fe..730ac96a9 100644 --- a/go.sum +++ b/go.sum @@ -1347,8 +1347,8 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b/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.37-0.20240925031313-e61849179955 h1:FXeQsPJSb+EOKTBcWdrShJ1FwyxlR7Yum2uXBURzXLk= -github.com/sei-protocol/sei-cosmos v0.3.37-0.20240925031313-e61849179955/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= +github.com/sei-protocol/sei-cosmos v0.3.37-0.20241007142359-ca29513f17aa h1:F27bny97cLUl1PAUX67qnFEAwH2OtLXH/b3r5S3mfVA= +github.com/sei-protocol/sei-cosmos v0.3.37-0.20241007142359-ca29513f17aa/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= github.com/sei-protocol/sei-db v0.0.45-0.20240918104613-6c0900823891 h1:gf23XvhKmCRyMvzEe2puRp3ZuXvw3noqF1cL1XxMQHQ= github.com/sei-protocol/sei-db v0.0.45-0.20240918104613-6c0900823891/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.2.0 h1:OisPjXiDT+oe+aeckzDEFgkZCYuUjHgs/PP8DPicN+I= diff --git a/tools/migration/sc/migrator.go b/tools/migration/sc/migrator.go index 5eec43a62..d3fe2a949 100644 --- a/tools/migration/sc/migrator.go +++ b/tools/migration/sc/migrator.go @@ -77,7 +77,7 @@ func NewMigrator(homeDir string, db dbm.DB) *Migrator { scConfig.Enable = true ssConfig := config.DefaultStateStoreConfig() ssConfig.Enable = false - cmsV2 := rootmulti2.NewStore(homeDir, logger, scConfig, ssConfig) + cmsV2 := rootmulti2.NewStore(homeDir, logger, scConfig, ssConfig, true) for _, key := range Keys { cmsV2.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) } From fa3c6b69c5aa52b8bf8bfa73a69b7f2212cda456 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 9 Oct 2024 13:19:07 -0400 Subject: [PATCH 07/28] Reduce logging --- go.mod | 2 +- go.sum | 4 ++-- tools/migration/ss/migrator.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 9b7ba9b62..83a01a321 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.2 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b 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.45-0.20240918104613-6c0900823891 + github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.45-0.20241009171123-c9b6c253819b // 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.8 diff --git a/go.sum b/go.sum index 730ac96a9..0fc966151 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.37-0.20241007142359-ca29513f17aa h1:F27bny97cLUl1PAUX67qnFEAwH2OtLXH/b3r5S3mfVA= github.com/sei-protocol/sei-cosmos v0.3.37-0.20241007142359-ca29513f17aa/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= -github.com/sei-protocol/sei-db v0.0.45-0.20240918104613-6c0900823891 h1:gf23XvhKmCRyMvzEe2puRp3ZuXvw3noqF1cL1XxMQHQ= -github.com/sei-protocol/sei-db v0.0.45-0.20240918104613-6c0900823891/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= +github.com/sei-protocol/sei-db v0.0.45-0.20241009171123-c9b6c253819b h1:q25KpfxNwTrS8UZgkjdTvQkNI1Wo84KkavDpPA3aHwI= +github.com/sei-protocol/sei-db v0.0.45-0.20241009171123-c9b6c253819b/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.2.0 h1:OisPjXiDT+oe+aeckzDEFgkZCYuUjHgs/PP8DPicN+I= github.com/sei-protocol/sei-iavl v0.2.0/go.mod h1:qRf8QYUPfrAO7K6VDB2B2l/N7K5L76OorioGBcJBIbw= github.com/sei-protocol/sei-ibc-go/v3 v3.3.2 h1:BaMZ6gjwqe3R/5dLmcJ1TkSZ3omcWy2TjaAZAeOJH44= diff --git a/tools/migration/ss/migrator.go b/tools/migration/ss/migrator.go index 4fde4aa41..758b79428 100644 --- a/tools/migration/ss/migrator.go +++ b/tools/migration/ss/migrator.go @@ -162,9 +162,9 @@ func ExportLeafNodesFromKey(db dbm.DB, ch chan<- types.RawSnapshotNode, startKey } count++ - if count%10000 == 0 { + if count%1000000 == 0 { batchDuration := time.Since(startTimeBatch) - fmt.Printf("ExportLeafNodesFromKey - Last 10,000 iterations took: %v. Total scanned: %d, leaf nodes exported: %d\n", batchDuration, count, leafNodeCount) + fmt.Printf("ExportLeafNodesFromKey - Last 1,000,000 iterations took: %v. Total scanned: %d, leaf nodes exported: %d\n", batchDuration, count, leafNodeCount) startTimeBatch = time.Now() // Reset the start time for the next batch } From f5defc1158f2c749ddac67d5e72fb55d67e43338 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 16 Oct 2024 13:35:52 -0400 Subject: [PATCH 08/28] Archive Migration doc --- docs/migration/seidb_archive_migration.md | 149 ++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 docs/migration/seidb_archive_migration.md diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md new file mode 100644 index 000000000..a18b65bad --- /dev/null +++ b/docs/migration/seidb_archive_migration.md @@ -0,0 +1,149 @@ +# SeiDB Archive Migration Guide + +## Overview +SeiDB is the next generation of chain storage in SeiV2. +One issue for archive nodes is that we need to keep the full state of the chain, so we can't +state sync a node and clear out previous data. + +In order to run an archive node with SeiDB, we need to run a migration from iavl to sei-db. + +The overall process will work as follows: +(1) Stop archive node and note down its height, call it MIGRATION_HEIGHT +(2) Update config to enable SeiDB (state committment + state store) +(3) Run sc migration at the MIGRATION_HEIGHT +(4) Re start seid with `--migrate-iavl` enabled (migrating state store in background) +(5) Verify migration at various sampled heights once state store is complete +(6) Stop seid, clear out iavl and restart seid normally, now only using SeiDB fully + +You may need to ensure you have sufficient disk space available, as during the migration process, both IAVL and SeiDB state stores will need to be maintained simultaneously. This could potentially double your storage requirements temporarily. + + +## Migration Steps + +### Step 1: Stop Node and note down latest height +Stop the seid process and note down the latest height. Save it as an env var $MIGRATION_HEIGHT. +```bash +systemctl stop seid +MIGRATION_HEIGHT=<> +``` + +### Step 2: Add SeiDB Configurations +We can enable SeiDB by adding the following configs to app.toml file. +Usually you can find this file under ~/.sei/config/app.toml. +```bash +############################################################################# +### SeiDB Configuration ### +############################################################################# + +[state-commit] +# Enable defines if the SeiDB should be enabled to override existing IAVL db backend. +sc-enable = true + +# AsyncCommitBuffer defines the size of asynchronous commit queue, this greatly improve block catching-up +# performance, <=0 means synchronous commit. +sc-async-commit-buffer = 100 + +# SnapshotKeepRecent defines how many memiavl snapshots (beyond the latest one) to keep +# Recommend to set to 1 to make sure IBC relayers work. +sc-keep-recent = 1 + +# SnapshotInterval defines the number of blocks interval the memiavl snapshot is taken, default to 10000 blocks. +# Adjust based on your needs: +# Setting this too low could lead to lot of extra heavy disk IO +# Setting this too high could lead to slow restart +sc-snapshot-interval = 10000 + +# SnapshotWriterLimit defines the max concurrency for taking memiavl snapshot +sc-snapshot-writer-limit = 1 + +# CacheSize defines the size of the LRU cache for each store on top of the tree, default to 100000. +sc-cache-size = 100000 + +[state-store] +# Enable defines if the state-store should be enabled for historical queries. +# In order to use state-store, you need to make sure to enable state-commit at the same time. +# Validator nodes should turn this off. +# State sync node or full nodes should turn this on. +ss-enable = true + +# DBBackend defines the backend database used for state-store. +# Supported backends: pebbledb, rocksdb +# defaults to pebbledb (recommended) +ss-backend = "pebbledb" + +# AsyncWriteBuffer defines the async queue length for commits to be applied to State Store +# Set <= 0 for synchronous writes, which means commits also need to wait for data to be persisted in State Store. +# defaults to 100 +ss-async-write-buffer = 100 + +# KeepRecent defines the number of versions to keep in state store +# Setting it to 0 means keep everything, default to 100000 +ss-keep-recent = 0 + +# PruneIntervalSeconds defines the minimum interval in seconds + some random delay to trigger pruning. +# It is more efficient to trigger pruning less frequently with large interval. +# default to 600 seconds +ss-prune-interval = 600 + +# ImportNumWorkers defines the concurrency for state sync import +# defaults to 1 +ss-import-num-workers = 1 +``` + + +### Step 3: Run SC Migration + +```bash +seid tools migrate-iavl --target-db SC --home-dir /root/.sei +``` + +This may take a couple hours to run. You will see logs of form +`Start restoring SC store for height` + + +### Step 4: Restart seid with background SS migration +```bash +seid start --migrate-iavl --migrate-height $MIGRATION_HEIGHT --chain-id pacific-1 +``` + +Seid will run normally and the migration will run in the background. Data from iavl +will be written to SS and new writes will be directed at SS not iavl. + +You will see logs of form +`SeiDB Archive Migration: Iterating through %s module...` and +`SeiDB Archive Migration: Last 1,000,000 iterations took:...` + + +NOTE: While this is running, any historical queries will be routed to iavl if +they are for a height BEFORE the migrate-height. Any queries on heights +AFTER the migrate-height will be routed to state store (pebbbledb). + + +### Step 5: Verify State Store Migration after completion +Once State Store Migration is complete, you will see logs of form +`SeiDB Archive Migration: DB scanning completed. Total time taken:...` + +You DO NOT immediately need to do anything. Your node will continue to run +and will operate normally. However we added a verification tool that will iterate through +all keys in iavl at a specific height and verify they exist in State Store. + +You should run the following command for a selection of different heights +```bash +seid tools verify-migration --version $VERIFICATION_HEIGHT +``` + +This will output `Verification Succeeded` if the verification was successful. + + +### Step 6: Clear out Iavl and restart seid +Once the verification is complete, we can proceed to clear out the iavl and +restart seid normally. + +```bash +systemctl stop seid +rm -rf ~/.sei/data/application.db +seid start --chain-id pacific-1 +``` + + +## FAQ From 0cc3b817feb7362a366ada1be19962ebcffe19d7 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 16 Oct 2024 13:37:14 -0400 Subject: [PATCH 09/28] Update form --- docs/migration/seidb_archive_migration.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index a18b65bad..13bb3fee8 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -8,12 +8,13 @@ state sync a node and clear out previous data. In order to run an archive node with SeiDB, we need to run a migration from iavl to sei-db. The overall process will work as follows: -(1) Stop archive node and note down its height, call it MIGRATION_HEIGHT -(2) Update config to enable SeiDB (state committment + state store) -(3) Run sc migration at the MIGRATION_HEIGHT -(4) Re start seid with `--migrate-iavl` enabled (migrating state store in background) -(5) Verify migration at various sampled heights once state store is complete -(6) Stop seid, clear out iavl and restart seid normally, now only using SeiDB fully + +1. Stop archive node and note down its height, call it MIGRATION_HEIGHT +2. Update config to enable SeiDB (state committment + state store) +3. Run sc migration at the MIGRATION_HEIGHT +4. Re start seid with `--migrate-iavl` enabled (migrating state store in background) +5. Verify migration at various sampled heights once state store is complete +6. Stop seid, clear out iavl and restart seid normally, now only using SeiDB fully You may need to ensure you have sufficient disk space available, as during the migration process, both IAVL and SeiDB state stores will need to be maintained simultaneously. This could potentially double your storage requirements temporarily. From 241632b2c73d92559b4d8ba9419ac50212ddaddd Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 16 Oct 2024 13:39:02 -0400 Subject: [PATCH 10/28] Update --- docs/migration/seidb_archive_migration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index 13bb3fee8..a9b6d8a74 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -2,8 +2,8 @@ ## Overview SeiDB is the next generation of chain storage in SeiV2. -One issue for archive nodes is that we need to keep the full state of the chain, so we can't -state sync a node and clear out previous data. +One issue for running SeiDB on archive nodes is that we need to keep the full state of the chain, so we can't +state sync it and clear out previous iavl data. In order to run an archive node with SeiDB, we need to run a migration from iavl to sei-db. From 387c96d1a34bb8212d82ad6a1745f56b239bcb90 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 16 Oct 2024 14:48:43 -0400 Subject: [PATCH 11/28] Export metric --- tools/migration/ss/migrator.go | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/tools/migration/ss/migrator.go b/tools/migration/ss/migrator.go index 758b79428..a0a3dcabe 100644 --- a/tools/migration/ss/migrator.go +++ b/tools/migration/ss/migrator.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/armon/go-metrics" "github.com/cosmos/iavl" "github.com/sei-protocol/sei-db/ss/types" dbm "github.com/tendermint/tm-db" @@ -95,15 +96,15 @@ func (m *Migrator) Verify(version int64) error { } count++ if count%10000 == 0 { - fmt.Printf("Verified %d keys in for module %s\n", count, module) + fmt.Printf("SeiDB Archive Migration:: Verified %d keys in for module %s\n", count, module) } return false }) if err != nil { - fmt.Printf("Failed to iterate the tree %s: %s\n", module, err.Error()) + fmt.Printf("SeiDB Archive Migration: Failed to iterate the tree %s: %s\n", module, err.Error()) return err } - fmt.Printf("Finished verifying module %s, total scanned: %d keys\n", module, count) + fmt.Printf("SeiDB Archive Migration:: Finished verifying module %s, total scanned: %d keys\n", module, count) } return verifyErr } @@ -111,16 +112,18 @@ func (m *Migrator) Verify(version int64) error { func ExportLeafNodesFromKey(db dbm.DB, ch chan<- types.RawSnapshotNode, startKey []byte, startModule string) error { count := 0 leafNodeCount := 0 - fmt.Println("ExportLeafNodesFromKey - Scanning database and exporting leaf nodes...") + fmt.Println("SeiDB Archive Migration: Scanning database and exporting leaf nodes...") startTimeTotal := time.Now() // Start measuring total time + var batchLeafNodeCount int + for _, module := range modules { if module != startModule && startModule != "" { continue } startTimeModule := time.Now() // Measure time for each module - fmt.Printf("ExportLeafNodesFromKey - Iterating through %s module...\n", module) + fmt.Printf("SeiDB Archive Migration: Iterating through %s module...\n", module) prefixDB := dbm.NewPrefixDB(db, []byte(buildRawPrefix(module))) var itr dbm.Iterator @@ -134,7 +137,7 @@ func ExportLeafNodesFromKey(db dbm.DB, ch chan<- types.RawSnapshotNode, startKey } if err != nil { - fmt.Printf("ExportLeafNodesFromKey - Error creating iterator: %+v\n", err) + fmt.Printf("SeiDB Archive Migration: Error creating iterator: %+v\n", err) return fmt.Errorf("failed to create iterator: %w", err) } defer itr.Close() @@ -146,13 +149,14 @@ func ExportLeafNodesFromKey(db dbm.DB, ch chan<- types.RawSnapshotNode, startKey node, err := iavl.MakeNode(value) if err != nil { - fmt.Printf("ExportLeafNodesFromKey - Failed to make node: %+v\n", err) + fmt.Printf("SeiDB Archive Migration: Failed to make node: %+v\n", err) return fmt.Errorf("failed to make node: %w", err) } // Only export leaf nodes if node.GetHeight() == 0 { leafNodeCount++ + batchLeafNodeCount++ ch <- types.RawSnapshotNode{ StoreKey: module, Key: node.GetNodeKey(), @@ -164,9 +168,13 @@ func ExportLeafNodesFromKey(db dbm.DB, ch chan<- types.RawSnapshotNode, startKey count++ if count%1000000 == 0 { batchDuration := time.Since(startTimeBatch) - fmt.Printf("ExportLeafNodesFromKey - Last 1,000,000 iterations took: %v. Total scanned: %d, leaf nodes exported: %d\n", batchDuration, count, leafNodeCount) + fmt.Printf("SeiDB Archive Migration: Last 1,000,000 iterations took: %v. Total scanned: %d, leaf nodes exported: %d\n", batchDuration, count, leafNodeCount) + metrics.IncrCounterWithLabels([]string{"sei", "migration", "leaf_nodes_exported"}, float32(batchLeafNodeCount), []metrics.Label{ + {Name: "module", Value: module}, + }) - startTimeBatch = time.Now() // Reset the start time for the next batch + batchLeafNodeCount = 0 + startTimeBatch = time.Now() } } @@ -176,11 +184,11 @@ func ExportLeafNodesFromKey(db dbm.DB, ch chan<- types.RawSnapshotNode, startKey } moduleDuration := time.Since(startTimeModule) - fmt.Printf("ExportLeafNodesFromKey - Finished scanning module %s. Time taken: %v. Total scanned: %d, leaf nodes exported: %d\n", module, moduleDuration, count, leafNodeCount) + fmt.Printf("SeiDB Archive Migration: Finished scanning module %s. Time taken: %v. Total scanned: %d, leaf nodes exported: %d\n", module, moduleDuration, count, leafNodeCount) } totalDuration := time.Since(startTimeTotal) - fmt.Printf("ExportLeafNodesFromKey - DB scanning completed. Total time taken: %v. Total entries scanned: %d, leaf nodes exported: %d\n", totalDuration, count, leafNodeCount) + fmt.Printf("SeiDB Archive Migration: DB scanning completed. Total time taken: %v. Total entries scanned: %d, leaf nodes exported: %d\n", totalDuration, count, leafNodeCount) return nil } From a586dbc45c4b5ba71e11d797bd9fb689c817cf01 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 16 Oct 2024 15:14:30 -0400 Subject: [PATCH 12/28] latest height --- docs/migration/seidb_archive_migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index a9b6d8a74..6adbefb37 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -24,8 +24,8 @@ You may need to ensure you have sufficient disk space available, as during the m ### Step 1: Stop Node and note down latest height Stop the seid process and note down the latest height. Save it as an env var $MIGRATION_HEIGHT. ```bash +MIGRATION_HEIGHT=$(seid q block | jq ".block.last_commit.height" | tr -d '"') systemctl stop seid -MIGRATION_HEIGHT=<> ``` ### Step 2: Add SeiDB Configurations From 0b9647b48a9cca17f35082598d5d8ec4060f5dd7 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Sun, 27 Oct 2024 21:37:22 +0100 Subject: [PATCH 13/28] Update start module logic --- tools/migration/ss/migrator.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/migration/ss/migrator.go b/tools/migration/ss/migrator.go index a0a3dcabe..1b4fe5b4d 100644 --- a/tools/migration/ss/migrator.go +++ b/tools/migration/ss/migrator.go @@ -117,10 +117,15 @@ func ExportLeafNodesFromKey(db dbm.DB, ch chan<- types.RawSnapshotNode, startKey startTimeTotal := time.Now() // Start measuring total time var batchLeafNodeCount int + startModuleFound := startModule == "" // true if no start module specified for _, module := range modules { - if module != startModule && startModule != "" { - continue + if !startModuleFound { + if module == startModule { + startModuleFound = true + } else { + continue + } } startTimeModule := time.Now() // Measure time for each module fmt.Printf("SeiDB Archive Migration: Iterating through %s module...\n", module) From 8dc5c9d1b6c172e7f3fb23e6eb6f3667586b6321 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 28 Oct 2024 11:33:46 +0100 Subject: [PATCH 14/28] Remove migrate SS command --- tools/migration/cmd/cmd.go | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/tools/migration/cmd/cmd.go b/tools/migration/cmd/cmd.go index 578265ffd..a29b6386d 100644 --- a/tools/migration/cmd/cmd.go +++ b/tools/migration/cmd/cmd.go @@ -21,13 +21,11 @@ func MigrateCmd() *cobra.Command { Run: execute, } cmd.PersistentFlags().String("home-dir", "/root/.sei", "Sei home directory") - cmd.PersistentFlags().String("target-db", "", "Available options: [SS, SC]") return cmd } func execute(cmd *cobra.Command, _ []string) { homeDir, _ := cmd.Flags().GetString("home-dir") - target, _ := cmd.Flags().GetString("target-db") dataDir := filepath.Join(homeDir, "data") db, err := dbm.NewGoLevelDB("application", dataDir) if err != nil { @@ -35,16 +33,9 @@ func execute(cmd *cobra.Command, _ []string) { } latestVersion := rootmulti.GetLatestVersion(db) fmt.Printf("latest version: %d\n", latestVersion) - if target == "SS" { - if err = migrateSS(latestVersion, homeDir, db); err != nil { - panic(err) - } - } else if target == "SC" { - if err = migrateSC(latestVersion, homeDir, db); err != nil { - panic(err) - } - } else { - panic("Invalid target-db, either SS or SC should be provided") + + if err = migrateSC(latestVersion, homeDir, db); err != nil { + panic(err) } } @@ -53,19 +44,6 @@ func migrateSC(version int64, homeDir string, db dbm.DB) error { return migrator.Migrate(version) } -func migrateSS(version int64, homeDir string, db dbm.DB) error { - ssConfig := config.DefaultStateStoreConfig() - ssConfig.Enable = true - - stateStore, err := sstypes.NewStateStore(log.NewNopLogger(), homeDir, ssConfig) - if err != nil { - return err - } - - migrator := ss.NewMigrator(homeDir, db, stateStore) - return migrator.Migrate(version, homeDir) -} - func VerifyMigrationCmd() *cobra.Command { cmd := &cobra.Command{ Use: "verify-migration", From df491b963d2f925ad2863f939cb1beee7cbf8f53 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 28 Oct 2024 12:41:36 +0100 Subject: [PATCH 15/28] Enable ss store --- tools/migration/sc/migrator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/migration/sc/migrator.go b/tools/migration/sc/migrator.go index d3fe2a949..6ee951f11 100644 --- a/tools/migration/sc/migrator.go +++ b/tools/migration/sc/migrator.go @@ -76,7 +76,7 @@ func NewMigrator(homeDir string, db dbm.DB) *Migrator { scConfig := config.DefaultStateCommitConfig() scConfig.Enable = true ssConfig := config.DefaultStateStoreConfig() - ssConfig.Enable = false + ssConfig.Enable = true cmsV2 := rootmulti2.NewStore(homeDir, logger, scConfig, ssConfig, true) for _, key := range Keys { cmsV2.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) From 1f5ec164d7d29c392af30080103a5e57444315a1 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 28 Oct 2024 17:51:15 +0100 Subject: [PATCH 16/28] Update archive node migration docs --- docs/migration/seidb_archive_migration.md | 26 ++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index 6adbefb37..0daba7015 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -9,9 +9,9 @@ In order to run an archive node with SeiDB, we need to run a migration from iavl The overall process will work as follows: -1. Stop archive node and note down its height, call it MIGRATION_HEIGHT -2. Update config to enable SeiDB (state committment + state store) -3. Run sc migration at the MIGRATION_HEIGHT +1. Update config to enable SeiDB (state committment + state store) +2. Stop the node and Run SC Migration +3. Note down MIGRATION_HEIGHT 4. Re start seid with `--migrate-iavl` enabled (migrating state store in background) 5. Verify migration at various sampled heights once state store is complete 6. Stop seid, clear out iavl and restart seid normally, now only using SeiDB fully @@ -21,14 +21,7 @@ You may need to ensure you have sufficient disk space available, as during the m ## Migration Steps -### Step 1: Stop Node and note down latest height -Stop the seid process and note down the latest height. Save it as an env var $MIGRATION_HEIGHT. -```bash -MIGRATION_HEIGHT=$(seid q block | jq ".block.last_commit.height" | tr -d '"') -systemctl stop seid -``` - -### Step 2: Add SeiDB Configurations +### Step 1: Add SeiDB Configurations We can enable SeiDB by adding the following configs to app.toml file. Usually you can find this file under ~/.sei/config/app.toml. ```bash @@ -92,9 +85,10 @@ ss-import-num-workers = 1 ``` -### Step 3: Run SC Migration +### Step 2: Stop the node and Run SC Migration ```bash +systemctl stop seid seid tools migrate-iavl --target-db SC --home-dir /root/.sei ``` @@ -102,6 +96,14 @@ This may take a couple hours to run. You will see logs of form `Start restoring SC store for height` +### Step 3: Note down MIGRATION_HEIGHT +Note down the latest height as outputted from the sc migration. +Save it as an env var $MIGRATION_HEIGHT. +```bash +MIGRATION_HEIGHT=<> +``` + + ### Step 4: Restart seid with background SS migration ```bash seid start --migrate-iavl --migrate-height $MIGRATION_HEIGHT --chain-id pacific-1 From e304dc0895f25abfc1d8d1c546131d5f3d1eb1a4 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 28 Oct 2024 18:36:30 +0100 Subject: [PATCH 17/28] More migration doc updates --- docs/migration/seidb_archive_migration.md | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index 0daba7015..b9414d799 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -14,7 +14,8 @@ The overall process will work as follows: 3. Note down MIGRATION_HEIGHT 4. Re start seid with `--migrate-iavl` enabled (migrating state store in background) 5. Verify migration at various sampled heights once state store is complete -6. Stop seid, clear out iavl and restart seid normally, now only using SeiDB fully +6. Restart seid normally and verify node runs properly +7. Clear out iavl and restart seid normally, now only using SeiDB fully You may need to ensure you have sufficient disk space available, as during the migration process, both IAVL and SeiDB state stores will need to be maintained simultaneously. This could potentially double your storage requirements temporarily. @@ -138,9 +139,21 @@ seid tools verify-migration --version $VERIFICATION_HEIGHT This will output `Verification Succeeded` if the verification was successful. -### Step 6: Clear out Iavl and restart seid -Once the verification is complete, we can proceed to clear out the iavl and -restart seid normally. +### Step 6: Restart seid normally and verify node runs properly +Once the verification has completed, we can restart seid normally and verify +that the node operates. + +```bash +seid start --chain-id pacific-1 +``` + +Note how we are not using the `--migrate-iavl` and `--migration-height` flags. +We can let this run for a couple hours and verify node oeprates normally. + + +### Step 7: Clear out Iavl and restart seid +Once it has been confirmed that the node has been running normally, +we can proceed to clear out the iavl and restart seid normally. ```bash systemctl stop seid From 8f928f74b52aad9281c9d835b5b5bb804fe7f965 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 28 Oct 2024 18:55:15 +0100 Subject: [PATCH 18/28] Update metrics in readme --- docs/migration/seidb_archive_migration.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index b9414d799..16fd1bef3 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -162,4 +162,16 @@ seid start --chain-id pacific-1 ``` +## Metrics + +During the State Store Migration, there are exported metrics that are helpful to keep track of +the progress. + +`sei_migration_leaf_nodes_exported` keeps track of how many nodes have been exported from iavl. + +`sei_migration_nodes_imported` keeps track of how many nodes have been imported into SeiDB (pebbledb). + +Both of these metrics have a `module` label which indicates what module is currently being exported / imported. + + ## FAQ From 1acc2dff508d752d0fea21ce5c8089c4bd635c2f Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 28 Oct 2024 21:06:43 +0100 Subject: [PATCH 19/28] Merge main --- CHANGELOG.md | 12 ++ aclmapping/evm/mappings_test.go | 1 + app/app.go | 9 +- app/eth_replay.go | 1 + app/receipt.go | 8 +- app/upgrades.go | 1 + contracts/test/ERC20toCW20PointerTest.js | 68 +++--- contracts/test/ERC721toCW721PointerTest.js | 55 +++-- contracts/test/EVMCompatabilityTest.js | 38 ++-- contracts/test/lib.js | 4 +- evmrpc/block.go | 34 +-- evmrpc/block_test.go | 13 +- evmrpc/filter.go | 18 +- evmrpc/filter_test.go | 4 +- evmrpc/info.go | 14 +- evmrpc/info_test.go | 22 +- evmrpc/setup_test.go | 2 +- evmrpc/simulate.go | 14 +- evmrpc/simulate_test.go | 46 +++- evmrpc/tx_test.go | 2 +- go.mod | 8 +- go.sum | 16 +- .../contracts/evm/bindings/erc20/erc20.go | 1 - .../bindings/univ2_swapper/univ2_swapper.go | 1 - loadtest/evm.go | 9 +- occ_tests/messages/test_msgs.go | 4 +- precompiles/bank/bank_test.go | 4 +- precompiles/pointer/pointer_test.go | 2 +- proto/evm/params.proto | 57 ++++- run_blocktests.sh | 8 + testutil/keeper/epoch.go | 2 +- utils/metrics/metrics_util.go | 11 + x/epoch/types/codec.go | 9 +- x/evm/ante/fee.go | 9 +- x/evm/ante/fee_test.go | 37 ++++ x/evm/ante/sig.go | 4 +- x/evm/genesis_test.go | 2 + x/evm/keeper/evm_test.go | 4 + x/evm/keeper/fee.go | 77 +++++++ x/evm/keeper/fee_test.go | 155 +++++++++++++ x/evm/keeper/keeper.go | 6 +- x/evm/keeper/msg_server_test.go | 14 +- x/evm/keeper/params.go | 12 ++ x/evm/keeper/params_test.go | 4 +- x/evm/keeper/replay.go | 17 +- x/evm/migrations/migrate_eip_1559_params.go | 17 ++ .../migrate_eip_1559_params_test.go | 31 +++ x/evm/module.go | 19 +- x/evm/module_test.go | 7 +- x/evm/types/codec.go | 12 +- x/evm/types/keys.go | 1 + x/evm/types/params.go | 45 +++- x/evm/types/params.pb.go | 204 +++++++++++++++--- x/evm/types/params_test.go | 32 ++- x/mint/types/codec.go | 8 +- x/oracle/keeper/test_utils.go | 2 +- x/oracle/module.go | 2 +- x/oracle/types/codec.go | 12 +- x/tokenfactory/keeper/migrations_test.go | 2 +- x/tokenfactory/types/codec.go | 27 ++- 60 files changed, 1032 insertions(+), 228 deletions(-) create mode 100644 x/evm/keeper/fee.go create mode 100644 x/evm/keeper/fee_test.go create mode 100644 x/evm/migrations/migrate_eip_1559_params.go create mode 100644 x/evm/migrations/migrate_eip_1559_params_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c5ab66af..d93eae4d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,18 @@ Ref: https://keepachangelog.com/en/1.0.0/ --> # Changelog +## v5.9.0 +sei-chain +* [#1867](https://github.com/sei-protocol/sei-chain/pull/1867) Add synthetic events in separate sei endpoints +* [#1861](https://github.com/sei-protocol/sei-chain/pull/1861) Revert showing wasm txs in EVM RPCs +* [#1857](https://github.com/sei-protocol/sei-chain/pull/1857) Fix events in 2-hop scenarios +* [#1856](https://github.com/sei-protocol/sei-chain/pull/1856) Add delegatecall flag to properly detect delegatecalls +* [#1850](https://github.com/sei-protocol/sei-chain/pull/1853) Fix websocket from_height +* [#1849](https://github.com/sei-protocol/sei-chain/pull/1849) Reduce block bloom storage +* [#1844](https://github.com/sei-protocol/sei-chain/pull/1844) Allowlist for token extensions + +sei-iavl +*[#41](https://github.com/sei-protocol/sei-iavl/pull/41) Fix tree versions causing slow restart and OOM ## v5.8.0 sei-chain * [#1840](https://github.com/sei-protocol/sei-chain/pull/1840) Add migration for new params diff --git a/aclmapping/evm/mappings_test.go b/aclmapping/evm/mappings_test.go index fb56460aa..397431206 100644 --- a/aclmapping/evm/mappings_test.go +++ b/aclmapping/evm/mappings_test.go @@ -126,6 +126,7 @@ func (suite *KeeperTestSuite) TestMsgEVMTransaction() { ctx, err := suite.preprocessor.AnteHandle(handlerCtx, tx.GetTx(), false, func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { return ctx, nil }) suite.Require().Nil(err) cms.ResetEvents() + suite.App.EvmKeeper.SetDynamicBaseFeePerGas(ctx, sdk.ZeroDec()) _, err = suite.msgServer.EVMTransaction(sdk.WrapSDKContext(ctx), tc.msg) suite.Require().Nil(err) diff --git a/app/app.go b/app/app.go index cb2e6136d..00aa5fe32 100644 --- a/app/app.go +++ b/app/app.go @@ -1604,8 +1604,15 @@ func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequ lazyWriteEvents := app.BankKeeper.WriteDeferredBalances(ctx) events = append(events, lazyWriteEvents...) + // Sum up total used per block + blockTotalGasUsed := int64(0) + for _, txResult := range txResults { + blockTotalGasUsed += txResult.GasUsed + } + endBlockResp := app.EndBlock(ctx, abci.RequestEndBlock{ - Height: req.GetHeight(), + Height: req.GetHeight(), + BlockGasUsed: blockTotalGasUsed, }) events = append(events, endBlockResp.Events...) diff --git a/app/eth_replay.go b/app/eth_replay.go index d63a3f1dd..780267b9d 100644 --- a/app/eth_replay.go +++ b/app/eth_replay.go @@ -141,6 +141,7 @@ func BlockTest(a *App, bt *ethtests.BlockTest) { } params := a.EvmKeeper.GetParams(a.GetContextForDeliverTx([]byte{})) params.MinimumFeePerGas = sdk.NewDecFromInt(sdk.NewInt(0)) + // params.BaseFeePerGas = sdk.NewDecFromInt(sdk.NewInt(0)) a.EvmKeeper.SetParams(a.GetContextForDeliverTx([]byte{}), params) } diff --git a/app/receipt.go b/app/receipt.go index 9ad3b5301..6ba273d21 100644 --- a/app/receipt.go +++ b/app/receipt.go @@ -32,10 +32,8 @@ type AllowanceResponse struct { Expires json.RawMessage `json:"expires"` } -func (app *App) AddCosmosEventsToEVMReceiptIfApplicable(ctx sdk.Context, tx sdk.Tx, checksum [32]byte, response abci.ResponseDeliverTx) { - if response.Code > 0 { - return - } +func (app *App) AddCosmosEventsToEVMReceiptIfApplicable(ctx sdk.Context, tx sdk.Tx, checksum [32]byte, response sdk.DeliverTxHookInput) { + // hooks will only be called if DeliverTx is successful wasmEvents := GetEventsOfType(response, wasmtypes.WasmModuleEventType) if len(wasmEvents) == 0 { return @@ -283,7 +281,7 @@ func (app *App) GetEvmAddressAttribute(ctx sdk.Context, event abci.Event, attrib return EmptyHash } -func GetEventsOfType(rdtx abci.ResponseDeliverTx, ty string) (res []abci.Event) { +func GetEventsOfType(rdtx sdk.DeliverTxHookInput, ty string) (res []abci.Event) { for _, event := range rdtx.Events { if event.Type == ty { res = append(res, event) diff --git a/app/upgrades.go b/app/upgrades.go index ffd33662a..4ec052825 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -110,6 +110,7 @@ var upgradesList = []string{ "v5.7.4", "v5.7.5", "v5.8.0", + "v5.9.0", } // if there is an override list, use that instead, for integration tests diff --git a/contracts/test/ERC20toCW20PointerTest.js b/contracts/test/ERC20toCW20PointerTest.js index 06d81fc4c..aca3b48dd 100644 --- a/contracts/test/ERC20toCW20PointerTest.js +++ b/contracts/test/ERC20toCW20PointerTest.js @@ -86,16 +86,16 @@ describe("ERC20 to CW20 Pointer", function () { }); describe("transfer()", function () { - it("should transfer", async function () { + it.only("should transfer", async function () { let sender = accounts[0]; let recipient = accounts[1]; expect(await pointer.balanceOf(sender.evmAddress)).to.equal(balances.account0); expect(await pointer.balanceOf(recipient.evmAddress)).to.equal(balances.account1); - const blockNumber = await ethers.provider.getBlockNumber(); const tx = await pointer.transfer(recipient.evmAddress, 1); - await tx.wait(); + const receipt = await tx.wait(); + const blockNumber = receipt.blockNumber; expect(await pointer.balanceOf(sender.evmAddress)).to.equal(balances.account0-1); expect(await pointer.balanceOf(recipient.evmAddress)).to.equal(balances.account1+1); @@ -107,18 +107,38 @@ describe("ERC20 to CW20 Pointer", function () { address: await pointer.getAddress(), topics: [ethers.id("Transfer(address,address,uint256)")] }; - // send via eth_ endpoint - synthetic event doesn't show up + // send via eth_ endpoint - synthetic event should show up because we are using the + // synthetic event in place of a real EVM event const ethlogs = await ethers.provider.send('eth_getLogs', [filter]); - expect(ethlogs.length).to.equal(0); + expect(ethlogs.length).to.equal(1); // send via sei_ endpoint - synthetic event shows up const seilogs = await ethers.provider.send('sei_getLogs', [filter]); expect(seilogs.length).to.equal(1); - expect(seilogs.length).to.equal(1); - expect(seilogs[0]["address"].toLowerCase()).to.equal((await pointer.getAddress()).toLowerCase()); - expect(seilogs[0]["topics"][0]).to.equal(ethers.id("Transfer(address,address,uint256)")); - expect(seilogs[0]["topics"][1].substring(26)).to.equal(sender.evmAddress.substring(2).toLowerCase()); - expect(seilogs[0]["topics"][2].substring(26)).to.equal(recipient.evmAddress.substring(2).toLowerCase()); + + const logs = [...ethlogs, ...seilogs]; + logs.forEach(async (log) => { + expect(log["address"].toLowerCase()).to.equal((await pointer.getAddress()).toLowerCase()); + expect(log["topics"][0]).to.equal(ethers.id("Transfer(address,address,uint256)")); + expect(log["topics"][1].substring(26)).to.equal(sender.evmAddress.substring(2).toLowerCase()); + expect(log["topics"][2].substring(26)).to.equal(recipient.evmAddress.substring(2).toLowerCase()); + }); + + const ethBlock = await ethers.provider.send('eth_getBlockByNumber', ['0x' + blockNumber.toString(16), false]); + const seiBlock = await ethers.provider.send('sei_getBlockByNumber', ['0x' + blockNumber.toString(16), false]); + expect(ethBlock.transactions.length).to.equal(1); + expect(seiBlock.transactions.length).to.equal(1); + + const ethReceipts = await ethers.provider.send('eth_getBlockReceipts', ['0x' + blockNumber.toString(16)]); + const seiReceipts = await ethers.provider.send('sei_getBlockReceipts', ['0x' + blockNumber.toString(16)]); + expect(ethReceipts.length).to.equal(1); + expect(seiReceipts.length).to.equal(1); + expect(ethReceipts[0].transactionHash).to.equal(seiReceipts[0].transactionHash); + + const ethTx = await ethers.provider.send('eth_getTransactionReceipt', [receipt.hash]); + expect(ethTx.logs.length).to.equal(1); // check for transfer event + const ethTxByHash = await ethers.provider.send('eth_getTransactionByHash', [tx.hash]); + expect(ethTxByHash).to.not.be.null; const cleanupTx = await pointer.connect(recipient.signer).transfer(sender.evmAddress, 1); await cleanupTx.wait(); @@ -147,7 +167,7 @@ describe("ERC20 to CW20 Pointer", function () { const spender = accounts[1].evmAddress; const blockNumber = await ethers.provider.getBlockNumber(); const tx = await pointer.approve(spender, 1000000); - await tx.wait(); + const receipt = await tx.wait(); const allowance = await pointer.allowance(owner, spender); expect(Number(allowance)).to.equal(1000000); @@ -160,21 +180,21 @@ describe("ERC20 to CW20 Pointer", function () { }; // send via eth_ endpoint - synthetic event doesn't show up const ethlogs = await ethers.provider.send('eth_getLogs', [filter]); - expect(ethlogs.length).to.equal(0); + expect(ethlogs.length).to.equal(1); + expect(ethlogs[0]["address"].toLowerCase()).to.equal((await pointer.getAddress()).toLowerCase()); + expect(ethlogs[0]["topics"][0]).to.equal(ethers.id("Approval(address,address,uint256)")); + expect(ethlogs[0]["topics"][1].substring(26)).to.equal(owner.substring(2).toLowerCase()); + expect(ethlogs[0]["topics"][2].substring(26)).to.equal(spender.substring(2).toLowerCase()); // send via sei_ endpoint - synthetic event shows up const seilogs = await ethers.provider.send('sei_getLogs', [filter]); expect(seilogs.length).to.equal(1); - expect(seilogs[0]["address"].toLowerCase()).to.equal((await pointer.getAddress()).toLowerCase()); - expect(seilogs[0]["topics"][0]).to.equal(ethers.id("Approval(address,address,uint256)")); - expect(seilogs[0]["topics"][1].substring(26)).to.equal(owner.substring(2).toLowerCase()); - expect(seilogs[0]["topics"][2].substring(26)).to.equal(spender.substring(2).toLowerCase()); }); it("should lower approval", async function () { const owner = accounts[0].evmAddress; const spender = accounts[1].evmAddress; - const tx = await pointer.approve(spender, 0); + const tx = await pointer.approve(spender, 0, { gasPrice: ethers.parseUnits('100', 'gwei') }); await tx.wait(); const allowance = await pointer.allowance(owner, spender); expect(Number(allowance)).to.equal(0); @@ -184,21 +204,21 @@ describe("ERC20 to CW20 Pointer", function () { const owner = accounts[0].evmAddress; const spender = accounts[1].evmAddress; const maxUint128 = new BigNumber("0xffffffffffffffffffffffffffffffff", 16); - const tx = await pointer.approve(spender, maxUint128.toFixed()); + const tx = await pointer.approve(spender, maxUint128.toFixed(), { gasPrice: ethers.parseUnits('100', 'gwei') }); await tx.wait(); const allowance = await pointer.allowance(owner, spender); expect(allowance).to.equal(maxUint128.toFixed()); // approving uint128 max int + 1 should work but only approve uint128 const maxUint128Plus1 = maxUint128.plus(1); - const tx128plus1 = await pointer.approve(spender, maxUint128Plus1.toFixed()); + const tx128plus1 = await pointer.approve(spender, maxUint128Plus1.toFixed(), { gasPrice: ethers.parseUnits('100', 'gwei') }); await tx128plus1.wait(); const allowance128plus1 = await pointer.allowance(owner, spender); expect(allowance128plus1).to.equal(maxUint128.toFixed()); // approving uint256 should also work but only approve uint128 const maxUint256 = new BigNumber("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16); - const tx256 = await pointer.approve(spender, maxUint256.toFixed()); + const tx256 = await pointer.approve(spender, maxUint256.toFixed(), { gasPrice: ethers.parseUnits('100', 'gwei') }); await tx256.wait(); const allowance256 = await pointer.allowance(owner, spender); expect(allowance256).to.equal(maxUint128.toFixed()); @@ -224,7 +244,7 @@ describe("ERC20 to CW20 Pointer", function () { expect(Number(allowanceBefore)).to.be.greaterThanOrEqual(amountToTransfer); // transfer - const tfTx = await pointer.connect(spender.signer).transferFrom(owner.evmAddress, recipient.evmAddress, amountToTransfer); + const tfTx = await pointer.connect(spender.signer).transferFrom(owner.evmAddress, recipient.evmAddress, amountToTransfer, { gasPrice: ethers.parseUnits('100', 'gwei') }); const receipt = await tfTx.wait(); // capture balances after @@ -260,12 +280,12 @@ describe("ERC20 to CW20 Pointer", function () { const owner = accounts[0]; const spender = accounts[1]; - const tx = await pointer.approve(spender.evmAddress, 10); + const tx = await pointer.approve(spender.evmAddress, 10, { gasPrice: ethers.parseUnits('100', 'gwei') }); await tx.wait(); - await expect(pointer.connect(spender.signer).transferFrom(owner.evmAddress, recipient.evmAddress, 20)).to.be.revertedWith("CosmWasm execute failed"); + await expect(pointer.connect(spender.signer).transferFrom(owner.evmAddress, recipient.evmAddress, 20, { gasPrice: ethers.parseUnits('100', 'gwei') })).to.be.revertedWith("CosmWasm execute failed"); // put it back - await (await pointer.approve(spender.evmAddress, 0)).wait() + await (await pointer.approve(spender.evmAddress, 0, { gasPrice: ethers.parseUnits('100', 'gwei') })).wait() }); }); }); diff --git a/contracts/test/ERC721toCW721PointerTest.js b/contracts/test/ERC721toCW721PointerTest.js index 2048c69f0..b871af9d9 100644 --- a/contracts/test/ERC721toCW721PointerTest.js +++ b/contracts/test/ERC721toCW721PointerTest.js @@ -83,7 +83,7 @@ describe("ERC721 to CW721 Pointer", function () { describe("write", function(){ it("approve", async function () { const blockNumber = await ethers.provider.getBlockNumber(); - const approvedTxResp = await pointerAcc0.approve(accounts[1].evmAddress, 2) + const approvedTxResp = await pointerAcc0.approve(accounts[1].evmAddress, 2, { gasPrice: ethers.parseUnits('100', 'gwei') }) await approvedTxResp.wait() const approved = await pointerAcc0.getApproved(2); expect(approved).to.equal(accounts[1].evmAddress); @@ -94,29 +94,34 @@ describe("ERC721 to CW721 Pointer", function () { address: await pointerAcc1.getAddress(), topics: [ethers.id("Approval(address,address,uint256)")] }; - // send via eth_ endpoint - synthetic event doesn't show up + // send via eth_ endpoint - synthetic event should show up because we are using the + // synthetic event in place of a real EVM event const ethlogs = await ethers.provider.send('eth_getLogs', [filter]); - expect(ethlogs.length).to.equal(0); + expect(ethlogs.length).to.equal(1); // send via sei_ endpoint - synthetic event shows up const seilogs = await ethers.provider.send('sei_getLogs', [filter]); expect(seilogs.length).to.equal(1); - expect(seilogs[0]["address"].toLowerCase()).to.equal((await pointerAcc1.getAddress()).toLowerCase()); - expect(seilogs[0]["topics"][0]).to.equal(ethers.id("Approval(address,address,uint256)")); - expect(seilogs[0]["topics"][1].substring(26)).to.equal(accounts[0].evmAddress.substring(2).toLowerCase()); - expect(seilogs[0]["topics"][2].substring(26)).to.equal(accounts[1].evmAddress.substring(2).toLowerCase()); + + const logs = [...ethlogs, ...seilogs]; + logs.forEach(async (log) => { + expect(log["address"].toLowerCase()).to.equal((await pointer.getAddress()).toLowerCase()); + expect(log["topics"][0]).to.equal(ethers.id("Transfer(address,address,uint256)")); + expect(log["topics"][1].substring(26)).to.equal(accounts[0].evmAddress.substring(2).toLowerCase()); + expect(log["topics"][2].substring(26)).to.equal(accounts[1].evmAddress.substring(2).toLowerCase()); + }); }); it("cannot approve token you don't own", async function () { - await expect(pointerAcc0.approve(accounts[1].evmAddress, 1)).to.be.reverted; + await expect(pointerAcc0.approve(accounts[1].evmAddress, 1, { gasPrice: ethers.parseUnits('100', 'gwei') })).to.be.reverted; }); it("transfer from", async function () { // accounts[0] should transfer token id 2 to accounts[1] await mine(pointerAcc0.approve(accounts[1].evmAddress, 2)); const blockNumber = await ethers.provider.getBlockNumber(); - transferTxResp = await pointerAcc1.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 2); - await transferTxResp.wait(); + transferTxResp = await pointerAcc1.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 2, { gasPrice: ethers.parseUnits('100', 'gwei') }); + const receipt = await transferTxResp.wait(); const filter = { fromBlock: '0x' + blockNumber.toString(16), toBlock: 'latest', @@ -125,19 +130,33 @@ describe("ERC721 to CW721 Pointer", function () { }; // send via eth_ endpoint - synthetic event doesn't show up const ethlogs = await ethers.provider.send('eth_getLogs', [filter]); - expect(ethlogs.length).to.equal(0); - + expect(ethlogs.length).to.equal(1); const seilogs = await ethers.provider.send('sei_getLogs', [filter]); expect(seilogs.length).to.equal(1); - expect(seilogs[0]["address"].toLowerCase()).to.equal((await pointerAcc1.getAddress()).toLowerCase()); - expect(seilogs[0]["topics"][0]).to.equal(ethers.id("Transfer(address,address,uint256)")); - expect(seilogs[0]["topics"][1].substring(26)).to.equal(accounts[1].evmAddress.substring(2).toLowerCase()); - expect(seilogs[0]["topics"][2].substring(26)).to.equal(accounts[1].evmAddress.substring(2).toLowerCase()); + const logs = [...ethlogs, ...seilogs]; + logs.forEach(async (log) => { + expect(log["address"].toLowerCase()).to.equal((await pointerAcc1.getAddress()).toLowerCase()); + expect(log["topics"][0]).to.equal(ethers.id("Transfer(address,address,uint256)")); + expect(log["topics"][1].substring(26)).to.equal(accounts[1].evmAddress.substring(2).toLowerCase()); + expect(log["topics"][2].substring(26)).to.equal(accounts[1].evmAddress.substring(2).toLowerCase()); + }); + const balance0 = await pointerAcc0.balanceOf(accounts[0].evmAddress); expect(balance0).to.equal(0); const balance1 = await pointerAcc0.balanceOf(accounts[1].evmAddress); expect(balance1).to.equal(2); + // do same for eth_getBlockReceipts and sei_getBlockReceipts + const ethBlockReceipts = await ethers.provider.send('eth_getBlockReceipts', ['0x' + receipt.blockNumber.toString(16)]); + expect(ethBlockReceipts.length).to.equal(1); + const seiBlockReceipts = await ethers.provider.send('sei_getBlockReceipts', ['0x' + receipt.blockNumber.toString(16)]); + expect(seiBlockReceipts.length).to.equal(1); + + const ethTx = await ethers.provider.send('eth_getTransactionReceipt', [receipt.hash]); + expect(ethTx.logs.length).to.equal(1); + const ethTxByHash = await ethers.provider.send('eth_getTransactionByHash', [receipt.hash]); + expect(ethTxByHash).to.not.be.null; + // return token id 2 back to accounts[0] using safe transfer from await mine(pointerAcc1.approve(accounts[0].evmAddress, 2)); await mine(pointerAcc1.safeTransferFrom(accounts[1].evmAddress, accounts[0].evmAddress, 2)); @@ -146,11 +165,11 @@ describe("ERC721 to CW721 Pointer", function () { }); it("cannot transfer token you don't own", async function () { - await expect(pointerAcc0.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 3)).to.be.reverted; + await expect(pointerAcc0.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 3, { gasPrice: ethers.parseUnits('100', 'gwei') })).to.be.reverted; }); it("set approval for all", async function () { - const setApprovalForAllTxResp = await pointerAcc0.setApprovalForAll(accounts[1].evmAddress, true); + const setApprovalForAllTxResp = await pointerAcc0.setApprovalForAll(accounts[1].evmAddress, true, { gasPrice: ethers.parseUnits('100', 'gwei') }); await setApprovalForAllTxResp.wait(); await expect(setApprovalForAllTxResp) .to.emit(pointerAcc0, 'ApprovalForAll') diff --git a/contracts/test/EVMCompatabilityTest.js b/contracts/test/EVMCompatabilityTest.js index 30703a6f2..070eadaff 100644 --- a/contracts/test/EVMCompatabilityTest.js +++ b/contracts/test/EVMCompatabilityTest.js @@ -93,7 +93,7 @@ describe("EVM Test", function () { testToken = await TestToken.deploy("TestToken", "TTK"); const EVMCompatibilityTester = await ethers.getContractFactory("EVMCompatibilityTester"); - evmTester = await EVMCompatibilityTester.deploy(); + evmTester = await EVMCompatibilityTester.deploy({ gasPrice: ethers.parseUnits('100', 'gwei') }); await Promise.all([evmTester.waitForDeployment(), testToken.waitForDeployment()]) @@ -130,7 +130,7 @@ describe("EVM Test", function () { describe("Contract Factory", function() { it("should deploy a second contract from createToken", async function () { - const txResponse = await evmTester.createToken("TestToken", "TTK"); + const txResponse = await evmTester.createToken("TestToken", "TTK", { gasPrice: ethers.parseUnits('100', 'gwei') }); const testerAddress = await evmTester.getAddress(); const receipt = await txResponse.wait(); const newTokenAddress = receipt.logs[0].address; @@ -148,7 +148,7 @@ describe("EVM Test", function () { await delay() // Set balance - await testToken.setBalance(owner.address, setAmount); + await testToken.setBalance(owner.address, setAmount, { gasPrice: ethers.parseUnits('100', 'gwei') }); // Prepare call data for balanceOf function of MyToken const balanceOfData = testToken.interface.encodeFunctionData("balanceOf", [owner.address]); @@ -169,7 +169,7 @@ describe("EVM Test", function () { describe("Msg Properties", function() { it("Should store and retrieve msg properties correctly", async function() { // Store msg properties - const txResponse = await evmTester.storeMsgProperties({ value: 1 }); + const txResponse = await evmTester.storeMsgProperties({ value: 1, gasPrice: ethers.parseUnits('100', 'gwei') }); await txResponse.wait(); // Retrieve stored msg properties @@ -215,7 +215,7 @@ describe("EVM Test", function () { it("Should set the address correctly and emit an event", async function () { // Call setAddress await delay() - const txResponse = await evmTester.setAddressVar(); + const txResponse = await evmTester.setAddressVar({ gasPrice: ethers.parseUnits('100', 'gwei') }); await txResponse.wait(); // Wait for the transaction to be mined await expect(txResponse) .to.emit(evmTester, 'AddressSet') @@ -225,7 +225,7 @@ describe("EVM Test", function () { it("Should set the bool correctly and emit an event", async function () { // Call setBoolVar await delay() - const txResponse = await evmTester.setBoolVar(true); + const txResponse = await evmTester.setBoolVar(true, { gasPrice: ethers.parseUnits('100', 'gwei') }); await txResponse.wait(); // Wait for the transaction to be mined debug(JSON.stringify(txResponse)) @@ -241,7 +241,7 @@ describe("EVM Test", function () { it("Should set the uint256 correctly and emit an event", async function () { // Call setBoolVar await delay() - const txResponse = await evmTester.setUint256Var(12345); + const txResponse = await evmTester.setUint256Var(12345, { gasPrice: ethers.parseUnits('100', 'gwei') }); await txResponse.wait(); // Wait for the transaction to be mined debug(JSON.stringify(txResponse)) @@ -279,7 +279,7 @@ describe("EVM Test", function () { it("Should trace a call with timestamp", async function () { await delay() - const txResponse = await evmTester.setTimestamp(); + const txResponse = await evmTester.setTimestamp({ gasPrice: ethers.parseUnits('100', 'gwei') }); const receipt = await txResponse.wait(); // Wait for the transaction to be mined // get the timestamp that was saved off during setTimestamp() @@ -315,7 +315,7 @@ describe("EVM Test", function () { it("Should set the string correctly and emit an event", async function () { await delay() - const txResponse = await evmTester.setStringVar("test"); + const txResponse = await evmTester.setStringVar("test", { gasPrice: ethers.parseUnits('100', 'gwei') }); const receipt = await txResponse.wait(); // Wait for the transaction to be mined const cosmosTx = await getCosmosTx(ethers.provider, receipt.hash) @@ -332,7 +332,7 @@ describe("EVM Test", function () { it("Should set the bytes correctly and emit an event", async function () { await delay() - const txResponse = await evmTester.setBytesVar(ethers.toUtf8Bytes("test")); + const txResponse = await evmTester.setBytesVar(ethers.toUtf8Bytes("test"), { gasPrice: ethers.parseUnits('100', 'gwei') }); await txResponse.wait(); await expect(txResponse) @@ -347,7 +347,7 @@ describe("EVM Test", function () { await delay() // Send the transaction and wait for it to be confirmed - const txResponse = await evmTester.setBalance(owner.address, testAmount); + const txResponse = await evmTester.setBalance(owner.address, testAmount, { gasPrice: ethers.parseUnits('100', 'gwei') }); await txResponse.wait(); await delay() // Now check the balance @@ -358,7 +358,7 @@ describe("EVM Test", function () { it("Should store and retrieve a private var correctly", async function () { const testAmount = 12345; await delay() - const txResponse = await evmTester.storeData(testAmount); + const txResponse = await evmTester.storeData(testAmount, { gasPrice: ethers.parseUnits('100', 'gwei') }); await txResponse.wait(); // Wait for the transaction to be mined await delay() const retrievedAmount = await evmTester.retrieveData(); @@ -379,7 +379,7 @@ describe("EVM Test", function () { describe("Assembly", function(){ it("Should add numbers correctly", async function () { - expect(await evmTester.addNumbers(10, 20)).to.equal(30); + expect(await evmTester.addNumbers(10, 20, { gasPrice: ethers.parseUnits('100', 'gwei') })).to.equal(30); }); it("Should return the current balance of the contract", async function () { @@ -392,7 +392,7 @@ describe("EVM Test", function () { it("Should return correct value from readFromStorage(index)", async function () { const testAmount = 12345; await delay() - const txResponse = await evmTester.storeData(testAmount); + const txResponse = await evmTester.storeData(testAmount, { gasPrice: ethers.parseUnits('100', 'gwei') }); await delay() await txResponse.wait(); // Wait for the transaction to be mined @@ -697,7 +697,7 @@ describe("EVM Test", function () { const numberOfEvents = 5; // check receipt - const txResponse = await evmTester.emitMultipleLogs(numberOfEvents); + const txResponse = await evmTester.emitMultipleLogs(numberOfEvents, { gasPrice: ethers.parseUnits('100', 'gwei') }); const receipt = await txResponse.wait(); expect(receipt.logs.length).to.equal(numberOfEvents) for(let i=0; i 0 && receipt.Logs[0].Synthetic { + // If the receipt has synthetic logs, we actually want to include them in the response. + if !a.includeShellReceipts && receipt.TxType == ShellEVMTxType { return } encodedReceipt, err := encodeReceipt(receipt, a.txConfig.TxDecoder(), block, func(h common.Hash) bool { @@ -215,7 +220,7 @@ func EncodeTmBlock( txHash := common.HexToHash(block.Block.DataHash.String()) resultHash := common.HexToHash(block.Block.LastResultsHash.String()) miner := common.HexToAddress(block.Block.ProposerAddress.String()) - baseFeePerGas := k.GetBaseFeePerGas(ctx).TruncateInt().BigInt() + baseFeePerGas := k.GetDynamicBaseFeePerGas(ctx).TruncateInt().BigInt() var blockGasUsed int64 chainConfig := types.DefaultChainConfig().EthereumConfig(k.ChainID(ctx)) transactions := []interface{}{} @@ -241,6 +246,9 @@ func EncodeTmBlock( if err != nil { continue } + if !includeSyntheticTxs && receipt.TxType == ShellEVMTxType { + continue + } newTx := ethapi.NewRPCTransaction(ethtx, blockhash, number.Uint64(), uint64(blockTime.Second()), uint64(receipt.TransactionIndex), baseFeePerGas, chainConfig) transactions = append(transactions, newTx) } @@ -254,7 +262,7 @@ func EncodeTmBlock( continue } if !fullTx { - transactions = append(transactions, th) + transactions = append(transactions, "0x"+hex.EncodeToString(th[:])) } else { ti := uint64(receipt.TransactionIndex) to := k.GetEVMAddressOrDefault(ctx, sdk.MustAccAddressFromBech32(m.Contract)) diff --git a/evmrpc/block_test.go b/evmrpc/block_test.go index 1a4c76d0f..4c394ead3 100644 --- a/evmrpc/block_test.go +++ b/evmrpc/block_test.go @@ -114,11 +114,18 @@ func TestGetBlockReceipts(t *testing.T) { // Query by tag latest => retrieves block 8 resObj3 := sendRequestGood(t, "getBlockReceipts", "latest") result = resObj3["result"].([]interface{}) - require.Equal(t, 1, len(result)) + require.Equal(t, 2, len(result)) receipt1 = result[0].(map[string]interface{}) require.Equal(t, "0x8", receipt1["blockNumber"]) require.Equal(t, "0x0", receipt1["transactionIndex"]) require.Equal(t, multiTxBlockTx4.Hash().Hex(), receipt1["transactionHash"]) + receiptWithSyntheticLog := result[1].(map[string]interface{}) + require.Equal(t, "0x8", receiptWithSyntheticLog["blockNumber"]) + logs := receiptWithSyntheticLog["logs"].([]interface{}) + firstLog := logs[0].(map[string]interface{}) + topics := firstLog["topics"].([]interface{}) + syntheticLogFirstTopic := "0x0000000000000000000000000000000000000000000000000000000000000234" + require.Equal(t, syntheticLogFirstTopic, topics[0].(string)) } func verifyGenesisBlockResult(t *testing.T, resObj map[string]interface{}) { @@ -167,7 +174,7 @@ func verifyBlockResult(t *testing.T, resObj map[string]interface{}) { require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000001", tx["blockHash"]) require.Equal(t, "0x5b4eba929f3811980f5ae0c5d04fa200f837df4e", tx["from"]) require.Equal(t, "0x3e8", tx["gas"]) - require.Equal(t, "0x0", tx["gasPrice"]) + require.Equal(t, "0xa", tx["gasPrice"]) require.Equal(t, "0xa", tx["maxFeePerGas"]) require.Equal(t, "0x0", tx["maxPriorityFeePerGas"]) require.Equal(t, "0xf02362077ac075a397344172496b28e913ce5294879d811bb0269b3be20a872e", tx["hash"]) @@ -185,7 +192,7 @@ func verifyBlockResult(t *testing.T, resObj map[string]interface{}) { require.Equal(t, "0x0", tx["yParity"]) require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000002", resObj["transactionsRoot"]) require.Equal(t, []interface{}{}, resObj["uncles"]) - require.Equal(t, "0x0", resObj["baseFeePerGas"]) + require.Equal(t, "0x3b9aca00", resObj["baseFeePerGas"]) require.Equal(t, "0x0", resObj["totalDifficulty"]) } diff --git a/evmrpc/filter.go b/evmrpc/filter.go index 29be263ed..167118ede 100644 --- a/evmrpc/filter.go +++ b/evmrpc/filter.go @@ -64,7 +64,7 @@ type EventItemDataWrapper struct { } func NewFilterAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, filterConfig *FilterConfig, connectionType ConnectionType, namespace string) *FilterAPI { - logFetcher := &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider, filterConfig: filterConfig, includeSynthetic: shouldIncludeSynthetic(namespace)} + logFetcher := &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider, filterConfig: filterConfig, includeSyntheticReceipts: shouldIncludeSynthetic(namespace)} filters := make(map[ethrpc.ID]filter) api := &FilterAPI{ namespace: namespace, @@ -211,7 +211,6 @@ func (a *FilterAPI) GetFilterLogs( return logs, nil } -// JEREMYFLAG func (a *FilterAPI) GetLogs( ctx context.Context, crit filters.FilterCriteria, @@ -275,11 +274,11 @@ func (a *FilterAPI) UninstallFilter( } type LogFetcher struct { - tmClient rpcclient.Client - k *keeper.Keeper - ctxProvider func(int64) sdk.Context - filterConfig *FilterConfig - includeSynthetic bool + tmClient rpcclient.Client + k *keeper.Keeper + ctxProvider func(int64) sdk.Context + filterConfig *FilterConfig + includeSyntheticReceipts bool } func (f *LogFetcher) GetLogsByFilters(ctx context.Context, crit filters.FilterCriteria, lastToHeight int64) ([]*ethtypes.Log, int64, error) { @@ -366,10 +365,11 @@ func (f *LogFetcher) FindLogsByBloom(height int64, filters [][]bloomIndexes) (re ctx.Logger().Error(fmt.Sprintf("FindLogsByBloom: unable to find receipt for hash %s", hash.Hex())) continue } - if !f.includeSynthetic && len(receipt.Logs) > 0 && receipt.Logs[0].Synthetic { + // if includeShellReceipts is false, include receipts with synthetic logs but exclude shell tx receipts + if !f.includeSyntheticReceipts && receipt.TxType == ShellEVMTxType { continue } - if !f.includeSynthetic && receipt.EffectiveGasPrice == 0 { + if !f.includeSyntheticReceipts && receipt.EffectiveGasPrice == 0 { return } if len(receipt.LogsBloom) > 0 && MatchFilters(ethtypes.Bloom(receipt.LogsBloom), filters) { diff --git a/evmrpc/filter_test.go b/evmrpc/filter_test.go index 4f589d95d..fa0a4f145 100644 --- a/evmrpc/filter_test.go +++ b/evmrpc/filter_test.go @@ -221,7 +221,7 @@ func TestSeiFilterGetLogs(t *testing.T) { }) } -func TestEthEndpointShouldNotReturnSyntheticLogs(t *testing.T) { +func TestEthEndpointCanReturnSyntheticLogs(t *testing.T) { testFilterGetLogs(t, "eth", []GetFilterLogTests{ { name: "filter by single topic with default range, exclude synethetic logs", @@ -230,7 +230,7 @@ func TestEthEndpointShouldNotReturnSyntheticLogs(t *testing.T) { check: func(t *testing.T, log map[string]interface{}) { require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000234", log["topics"].([]interface{})[0].(string)) }, - wantLen: 0, + wantLen: 1, }, }) } diff --git a/evmrpc/info.go b/evmrpc/info.go index d79526103..5b7badb8f 100644 --- a/evmrpc/info.go +++ b/evmrpc/info.go @@ -80,12 +80,15 @@ func (i *InfoAPI) GasPrice(ctx context.Context) (result *hexutil.Big, returnErr } if len(feeHist.Reward) == 0 || len(feeHist.Reward[0]) == 0 { // if there is no EVM tx in the most recent block, return the minimum fee param - return (*hexutil.Big)(i.keeper.GetMinimumFeePerGas(i.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt()), nil + baseFee := i.keeper.GetMinimumFeePerGas(i.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt() + return (*hexutil.Big)(baseFee), nil } - return (*hexutil.Big)(new(big.Int).Add( + baseFee := i.keeper.GetDynamicBaseFeePerGas(i.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt() + sum := new(big.Int).Add( feeHist.Reward[0][0].ToInt(), - i.keeper.GetBaseFeePerGas(i.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt(), - )), nil + baseFee, + ) + return (*hexutil.Big)(sum), nil } // lastBlock is inclusive @@ -195,7 +198,8 @@ func (i *InfoAPI) safeGetBaseFee(targetHeight int64) (res *big.Int) { res = nil } }() - res = i.keeper.GetBaseFeePerGas(i.ctxProvider(targetHeight)).BigInt() + baseFee := i.keeper.GetDynamicBaseFeePerGas(i.ctxProvider(targetHeight)) + res = baseFee.TruncateInt().BigInt() return } diff --git a/evmrpc/info_test.go b/evmrpc/info_test.go index b56f9e2c6..016bda147 100644 --- a/evmrpc/info_test.go +++ b/evmrpc/info_test.go @@ -2,6 +2,7 @@ package evmrpc_test import ( "errors" + "fmt" "math/big" "testing" @@ -58,11 +59,11 @@ func TestCoinbase(t *testing.T) { } func TestGasPrice(t *testing.T) { - Ctx = Ctx.WithBlockHeight(1) resObj := sendRequestGood(t, "gasPrice") Ctx = Ctx.WithBlockHeight(8) result := resObj["result"].(string) - require.Equal(t, "0xa", result) + oneGwei := "0x3b9aca00" + require.Equal(t, oneGwei, result) } func TestFeeHistory(t *testing.T) { @@ -81,12 +82,12 @@ func TestFeeHistory(t *testing.T) { Ctx = Ctx.WithBlockHeight(1) // Simulate context with a specific block height testCases := []feeHistoryTestCase{ - {name: "Valid request by number", blockCount: 1, lastBlock: "0x8", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0xa", expectedBaseFee: "0x0", expectedGasUsed: 0.5}, - {name: "Valid request by latest", blockCount: 1, lastBlock: "latest", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0xa", expectedBaseFee: "0x0", expectedGasUsed: 0.5}, - {name: "Valid request by earliest", blockCount: 1, lastBlock: "earliest", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0xa", expectedBaseFee: "0x0", expectedGasUsed: 0.5}, - {name: "Request on the same block", blockCount: 1, lastBlock: "0x1", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0xa", expectedBaseFee: "0x0", expectedGasUsed: 0.5}, - {name: "Request on future block", blockCount: 1, lastBlock: "0x9", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0xa", expectedBaseFee: "0x0", expectedGasUsed: 0.5}, - {name: "Block count truncates", blockCount: 1025, lastBlock: "latest", rewardPercentiles: []interface{}{25}, expectedOldest: "0x1", expectedReward: "0xa", expectedBaseFee: "0x0", expectedGasUsed: 0.5}, + {name: "Valid request by number", blockCount: 1, lastBlock: "0x8", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0x170cdc1e00", expectedBaseFee: "0x3b9aca00", expectedGasUsed: 0.5}, + {name: "Valid request by latest", blockCount: 1, lastBlock: "latest", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0x170cdc1e00", expectedBaseFee: "0x3b9aca00", expectedGasUsed: 0.5}, + {name: "Valid request by earliest", blockCount: 1, lastBlock: "earliest", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0x170cdc1e00", expectedBaseFee: "0x3b9aca00", expectedGasUsed: 0.5}, + {name: "Request on the same block", blockCount: 1, lastBlock: "0x1", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0x170cdc1e00", expectedBaseFee: "0x3b9aca00", expectedGasUsed: 0.5}, + {name: "Request on future block", blockCount: 1, lastBlock: "0x9", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1", expectedReward: "0x170cdc1e00", expectedBaseFee: "0x3b9aca00", expectedGasUsed: 0.5}, + {name: "Block count truncates", blockCount: 1025, lastBlock: "latest", rewardPercentiles: []interface{}{25}, expectedOldest: "0x1", expectedReward: "0x170cdc1e00", expectedBaseFee: "0x3b9aca00", expectedGasUsed: 0.5}, {name: "Too many percentiles", blockCount: 10, lastBlock: "latest", rewardPercentiles: make([]interface{}, 101), expectedError: errors.New("rewardPercentiles length must be less than or equal to 100")}, {name: "Invalid percentiles order", blockCount: 10, lastBlock: "latest", rewardPercentiles: []interface{}{99, 1}, expectedError: errors.New("invalid reward percentiles: must be ascending and between 0 and 100")}, } @@ -103,6 +104,7 @@ func TestFeeHistory(t *testing.T) { require.False(t, errorExists) resObj = resObj["result"].(map[string]interface{}) + require.Equal(t, tc.expectedOldest, resObj["oldestBlock"].(string)) rewards, ok := resObj["reward"].([]interface{}) @@ -111,6 +113,8 @@ func TestFeeHistory(t *testing.T) { reward, ok := rewards[0].([]interface{}) require.True(t, ok, "Expected reward to be a slice of interfaces") require.Equal(t, 1, len(reward), "Expected exactly one sub-item in reward") + fmt.Println("resObj", resObj) + require.Equal(t, tc.expectedReward, reward[0].(string), "Reward does not match expected value") require.Equal(t, tc.expectedBaseFee, resObj["baseFeePerGas"].([]interface{})[0].(string)) @@ -164,5 +168,5 @@ func TestMaxPriorityFeePerGas(t *testing.T) { Ctx = Ctx.WithBlockHeight(1) // Mimic request sending and handle the response resObj := sendRequestGood(t, "maxPriorityFeePerGas") - assert.Equal(t, "0xa", resObj["result"]) + assert.Equal(t, "0x170cdc1e00", resObj["result"]) } diff --git a/evmrpc/setup_test.go b/evmrpc/setup_test.go index 3449bb640..d252f3167 100644 --- a/evmrpc/setup_test.go +++ b/evmrpc/setup_test.go @@ -575,7 +575,7 @@ func generateTxData() { TxHashHex: tx1.Hash().Hex(), GasUsed: 55, Status: 0, - EffectiveGasPrice: 10, + EffectiveGasPrice: 100000000000, Logs: []*types.Log{{ Address: "0x1111111111111111111111111111111111111111", Topics: []string{"0x1111111111111111111111111111111111111111111111111111111111111111", "0x1111111111111111111111111111111111111111111111111111111111111112"}, diff --git a/evmrpc/simulate.go b/evmrpc/simulate.go index e78c500f3..7805dca65 100644 --- a/evmrpc/simulate.go +++ b/evmrpc/simulate.go @@ -95,6 +95,18 @@ func (s *SimulationAPI) EstimateGas(ctx context.Context, args ethapi.Transaction return estimate, err } +func (s *SimulationAPI) EstimateGasAfterCalls(ctx context.Context, args ethapi.TransactionArgs, calls []ethapi.TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *ethapi.StateOverride) (result hexutil.Uint64, returnErr error) { + startTime := time.Now() + defer recordMetricsWithError("eth_estimateGasAfterCalls", s.connectionType, startTime, returnErr) + bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + if blockNrOrHash != nil { + bNrOrHash = *blockNrOrHash + } + ctx = context.WithValue(ctx, CtxIsWasmdPrecompileCallKey, wasmd.IsWasmdCall(args.To)) + estimate, err := ethapi.DoEstimateGasAfterCalls(ctx, s.backend, args, calls, bNrOrHash, overrides, s.backend.RPCEVMTimeout(), s.backend.RPCGasCap()) + return estimate, err +} + func (s *SimulationAPI) Call(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *ethapi.StateOverride, blockOverrides *ethapi.BlockOverrides) (result hexutil.Bytes, returnErr error) { startTime := time.Now() defer recordMetrics("eth_call", s.connectionType, startTime, returnErr == nil) @@ -424,7 +436,7 @@ func (b *Backend) getHeader(blockNumber *big.Int) *ethtypes.Header { header := ðtypes.Header{ Difficulty: common.Big0, Number: blockNumber, - BaseFee: b.keeper.GetBaseFeePerGas(b.ctxProvider(LatestCtxHeight)).BigInt(), + BaseFee: b.keeper.GetDynamicBaseFeePerGas(b.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt(), GasLimit: b.config.GasCap, Time: uint64(time.Now().Unix()), ExcessBlobGas: &zeroExcessBlobGas, diff --git a/evmrpc/simulate_test.go b/evmrpc/simulate_test.go index 5375722f6..542fac433 100644 --- a/evmrpc/simulate_test.go +++ b/evmrpc/simulate_test.go @@ -67,6 +67,48 @@ func TestEstimateGas(t *testing.T) { Ctx = Ctx.WithBlockHeight(8) } +func TestEstimateGasAfterCalls(t *testing.T) { + Ctx = Ctx.WithBlockHeight(1) + // estimate get after set + _, from := testkeeper.MockAddressPair() + amts := sdk.NewCoins(sdk.NewCoin(EVMKeeper.GetBaseDenom(Ctx), sdk.NewInt(20))) + EVMKeeper.BankKeeper().MintCoins(Ctx, types.ModuleName, amts) + EVMKeeper.BankKeeper().SendCoinsFromModuleToAccount(Ctx, types.ModuleName, sdk.AccAddress(from[:]), amts) + _, contractAddr := testkeeper.MockAddressPair() + code, err := os.ReadFile("../example/contracts/simplestorage/SimpleStorage.bin") + require.Nil(t, err) + bz, err := hex.DecodeString(string(code)) + require.Nil(t, err) + abi, err := simplestorage.SimplestorageMetaData.GetAbi() + require.Nil(t, err) + call, err := abi.Pack("set", big.NewInt(20)) + require.Nil(t, err) + input, err := abi.Pack("get") + require.Nil(t, err) + EVMKeeper.SetCode(Ctx, contractAddr, bz) + txArgs := map[string]interface{}{ + "from": from.Hex(), + "to": contractAddr.Hex(), + "value": "0x0", + "nonce": "0x2", + "chainId": fmt.Sprintf("%#x", EVMKeeper.ChainID(Ctx)), + "input": fmt.Sprintf("%#x", input), + } + callArgs := map[string]interface{}{ + "from": from.Hex(), + "to": contractAddr.Hex(), + "value": "0x0", + "nonce": "0x2", + "chainId": fmt.Sprintf("%#x", EVMKeeper.ChainID(Ctx)), + "input": fmt.Sprintf("%#x", call), + } + resObj := sendRequestGood(t, "estimateGasAfterCalls", txArgs, []interface{}{callArgs}, nil, map[string]interface{}{}) + result := resObj["result"].(string) + require.Equal(t, "0x536d", result) // 21357 for get + + Ctx = Ctx.WithBlockHeight(8) +} + func TestCreateAccessList(t *testing.T) { Ctx = Ctx.WithBlockHeight(1) @@ -89,7 +131,7 @@ func TestCreateAccessList(t *testing.T) { "chainId": fmt.Sprintf("%#x", EVMKeeper.ChainID(Ctx)), "input": fmt.Sprintf("%#x", input), } - amts := sdk.NewCoins(sdk.NewCoin(EVMKeeper.GetBaseDenom(Ctx), sdk.NewInt(20))) + amts := sdk.NewCoins(sdk.NewCoin(EVMKeeper.GetBaseDenom(Ctx), sdk.NewInt(2000000))) EVMKeeper.BankKeeper().MintCoins(Ctx, types.ModuleName, amts) EVMKeeper.BankKeeper().SendCoinsFromModuleToAccount(Ctx, types.ModuleName, sdk.AccAddress(from[:]), amts) resObj := sendRequestGood(t, "createAccessList", txArgs, "latest") @@ -148,10 +190,8 @@ func TestEthCallHighAmount(t *testing.T) { from.Hex(): {"balance": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, } resObj := sendRequestGood(t, "call", txArgs, "latest", overrides) - fmt.Println("resObj = ", resObj) errMap := resObj["error"].(map[string]interface{}) result := errMap["message"] - fmt.Println("res = ", result) require.Equal(t, result, "error: balance override overflow") Ctx = Ctx.WithBlockHeight(8) diff --git a/evmrpc/tx_test.go b/evmrpc/tx_test.go index b6695d05d..b41c07f2c 100644 --- a/evmrpc/tx_test.go +++ b/evmrpc/tx_test.go @@ -44,7 +44,7 @@ func testGetTxReceipt(t *testing.T, namespace string) { require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000001", resObj["blockHash"].(string)) require.Equal(t, "0x8", resObj["blockNumber"].(string)) require.Equal(t, "0x7b", resObj["cumulativeGasUsed"].(string)) - require.Equal(t, "0xa", resObj["effectiveGasPrice"].(string)) + require.Equal(t, "0x174876e800", resObj["effectiveGasPrice"].(string)) require.Equal(t, "0x1234567890123456789012345678901234567890", resObj["from"].(string)) require.Equal(t, "0x37", resObj["gasUsed"].(string)) logs := resObj["logs"].([]interface{}) diff --git a/go.mod b/go.mod index 83a01a321..d1d55a32f 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/BurntSushi/toml v1.3.2 github.com/CosmWasm/wasmd v0.27.0 - github.com/CosmWasm/wasmvm v1.5.4 + github.com/CosmWasm/wasmvm v1.5.5 github.com/armon/go-metrics v0.4.1 github.com/btcsuite/btcd v0.22.1 github.com/cosmos/cosmos-sdk v0.45.10 @@ -346,15 +346,15 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.2.4 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.37-0.20241007142359-ca29513f17aa + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.39-0.20241028105359-4193e4f26917 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.2.0 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.2 - github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b + github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-23 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.45-0.20241009171123-c9b6c253819b // 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.8 + github.com/tendermint/tendermint => github.com/sei-protocol/sei-tendermint v0.3.9-0.20240926181940-e9348a908b27 github.com/tendermint/tm-db => github.com/sei-protocol/tm-db v0.0.4 google.golang.org/grpc => google.golang.org/grpc v1.33.2 ) diff --git a/go.sum b/go.sum index 0fc966151..c9c096b68 100644 --- a/go.sum +++ b/go.sum @@ -96,8 +96,8 @@ github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= -github.com/CosmWasm/wasmvm v1.5.4 h1:Opqy65ubJ8bMsT08dn85VjRdsLJVPIAgIXif92qOMGc= -github.com/CosmWasm/wasmvm v1.5.4/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= +github.com/CosmWasm/wasmvm v1.5.5 h1:XlZI3xO5iUhiBqMiyzsrWEfUtk5gcBMNYIdHnsTB+NI= +github.com/CosmWasm/wasmvm v1.5.5/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= @@ -1343,20 +1343,20 @@ github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod github.com/securego/gosec/v2 v2.11.0 h1:+PDkpzR41OI2jrw1q6AdXZCbsNGNGT7pQjal0H0cArI= github.com/securego/gosec/v2 v2.11.0/go.mod h1:SX8bptShuG8reGC0XS09+a4H2BoWSJi+fscA+Pulbpo= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b h1:mVNX02TN7XlxkZliA752umeOB5MegtMroeIzdFGbgBk= -github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240923025222-815b87dde97b/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= +github.com/sei-protocol/go-ethereum v1.13.5-sei-23 h1:rkgeOHC56QTco4mIyGd6cZHtlonulLsaPLZCaMY6TAw= +github.com/sei-protocol/go-ethereum v1.13.5-sei-23/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.37-0.20241007142359-ca29513f17aa h1:F27bny97cLUl1PAUX67qnFEAwH2OtLXH/b3r5S3mfVA= -github.com/sei-protocol/sei-cosmos v0.3.37-0.20241007142359-ca29513f17aa/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= +github.com/sei-protocol/sei-cosmos v0.3.39-0.20241028105359-4193e4f26917 h1:h4QV0suNrGyK7u8fn3xpI+/864DVN8f9Qat2J2KAjvA= +github.com/sei-protocol/sei-cosmos v0.3.39-0.20241028105359-4193e4f26917/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= github.com/sei-protocol/sei-db v0.0.45-0.20241009171123-c9b6c253819b h1:q25KpfxNwTrS8UZgkjdTvQkNI1Wo84KkavDpPA3aHwI= github.com/sei-protocol/sei-db v0.0.45-0.20241009171123-c9b6c253819b/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.2.0 h1:OisPjXiDT+oe+aeckzDEFgkZCYuUjHgs/PP8DPicN+I= github.com/sei-protocol/sei-iavl v0.2.0/go.mod h1:qRf8QYUPfrAO7K6VDB2B2l/N7K5L76OorioGBcJBIbw= github.com/sei-protocol/sei-ibc-go/v3 v3.3.2 h1:BaMZ6gjwqe3R/5dLmcJ1TkSZ3omcWy2TjaAZAeOJH44= github.com/sei-protocol/sei-ibc-go/v3 v3.3.2/go.mod h1:VwB/vWu4ysT5DN2aF78d17LYmx3omSAdq6gpKvM7XRA= -github.com/sei-protocol/sei-tendermint v0.3.8 h1:9o+A3tL6q1ki++dLng/J8MHHiT6y3l7D4Ir2UIQSkAQ= -github.com/sei-protocol/sei-tendermint v0.3.8/go.mod h1:4LSlJdhl3nf3OmohliwRNUFLOB1XWlrmSodrIP7fLh4= +github.com/sei-protocol/sei-tendermint v0.3.9-0.20240926181940-e9348a908b27 h1:IREoTJ2mrjmGGHVtuVLzzPjh7U7sqjqJLHAIN1BSIW4= +github.com/sei-protocol/sei-tendermint v0.3.9-0.20240926181940-e9348a908b27/go.mod h1:4LSlJdhl3nf3OmohliwRNUFLOB1XWlrmSodrIP7fLh4= github.com/sei-protocol/sei-tm-db v0.0.5 h1:3WONKdSXEqdZZeLuWYfK5hP37TJpfaUa13vAyAlvaQY= github.com/sei-protocol/sei-tm-db v0.0.5/go.mod h1:Cpa6rGyczgthq7/0pI31jys2Fw0Nfrc+/jKdP1prVqY= github.com/sei-protocol/sei-wasmd v0.2.4 h1:W++xiJ1P57BhBW8TGk8vfPRJlWXr1vp2kQCvSc8Qpaw= diff --git a/loadtest/contracts/evm/bindings/erc20/erc20.go b/loadtest/contracts/evm/bindings/erc20/erc20.go index 5f225c93f..41e41bd72 100644 --- a/loadtest/contracts/evm/bindings/erc20/erc20.go +++ b/loadtest/contracts/evm/bindings/erc20/erc20.go @@ -757,4 +757,3 @@ func (_Erc20 *Erc20Filterer) ParseTransfer(log types.Log) (*Erc20Transfer, error event.Raw = log return event, nil } - diff --git a/loadtest/contracts/evm/bindings/univ2_swapper/univ2_swapper.go b/loadtest/contracts/evm/bindings/univ2_swapper/univ2_swapper.go index abd7c47f5..abebc6abf 100644 --- a/loadtest/contracts/evm/bindings/univ2_swapper/univ2_swapper.go +++ b/loadtest/contracts/evm/bindings/univ2_swapper/univ2_swapper.go @@ -324,4 +324,3 @@ func (_Univ2Swapper *Univ2SwapperSession) Swap() (*types.Transaction, error) { func (_Univ2Swapper *Univ2SwapperTransactorSession) Swap() (*types.Transaction, error) { return _Univ2Swapper.Contract.Swap(&_Univ2Swapper.TransactOpts) } - diff --git a/loadtest/evm.go b/loadtest/evm.go index 05c9fdeb4..ecf22cf16 100644 --- a/loadtest/evm.go +++ b/loadtest/evm.go @@ -25,8 +25,8 @@ import ( ) var ( - DefaultPriorityFee = big.NewInt(1000000000) // 1gwei - DefaultMaxFee = big.NewInt(1000000000) // 1gwei + DefaultPriorityFee = big.NewInt(1000000000) // 1gwei + DefaultMaxFee = big.NewInt(1000000000000) // 1000gwei ) type EvmTxClient struct { @@ -112,7 +112,7 @@ func (txClient *EvmTxClient) GenerateSendFundsTx() *ethtypes.Transaction { if !txClient.useEip1559 { tx = ethtypes.NewTx(ðtypes.LegacyTx{ Nonce: txClient.nextNonce(), - GasPrice: txClient.gasPrice, + GasPrice: DefaultMaxFee, Gas: uint64(21000), To: &txClient.accountAddress, Value: randomValue(), @@ -186,7 +186,7 @@ func (txClient *EvmTxClient) getTransactOpts() *bind.TransactOpts { panic(fmt.Sprintf("Failed to create transactor: %v \n", err)) } if !txClient.useEip1559 { - auth.GasPrice = txClient.gasPrice + auth.GasPrice = DefaultMaxFee } else { auth.GasFeeCap = DefaultMaxFee auth.GasTipCap = DefaultPriorityFee @@ -221,7 +221,6 @@ func (txClient *EvmTxClient) SendEvmTx(signedTx *ethtypes.Transaction, onSuccess if err != nil { fmt.Printf("Failed to send evm transaction: %v \n", err) } else { - // We choose not to GetTxReceipt because we assume the EVM RPC would be running with broadcast mode = block onSuccess() } } diff --git a/occ_tests/messages/test_msgs.go b/occ_tests/messages/test_msgs.go index 6ea0d5c65..d7df19532 100644 --- a/occ_tests/messages/test_msgs.go +++ b/occ_tests/messages/test_msgs.go @@ -82,8 +82,8 @@ func EVMTransferConflicting(tCtx *utils.TestContext, count int) []*utils.TestMes // each message will have a brand new address func evmTransfer(testAcct utils.TestAcct, to common.Address, scenario string) *utils.TestMessage { signedTx, err := ethtypes.SignTx(ethtypes.NewTx(ðtypes.DynamicFeeTx{ - GasFeeCap: new(big.Int).SetUint64(1000000000000), - GasTipCap: new(big.Int).SetUint64(1000000000000), + GasFeeCap: new(big.Int).SetUint64(100000000000), + GasTipCap: new(big.Int).SetUint64(100000000000), Gas: 21000, ChainID: big.NewInt(config.DefaultChainID), To: &to, diff --git a/precompiles/bank/bank_test.go b/precompiles/bank/bank_test.go index 3ad24ed56..41ffee15f 100644 --- a/precompiles/bank/bank_test.go +++ b/precompiles/bank/bank_test.go @@ -179,7 +179,7 @@ func TestRun(t *testing.T) { sdk.NewAttribute(banktypes.AttributeKeySender, senderAddr.String()), ), // gas refund to the sender - banktypes.NewCoinReceivedEvent(senderAddr, sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(172056)))), + banktypes.NewCoinReceivedEvent(senderAddr, sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(41916)))), // tip is paid to the validator banktypes.NewCoinReceivedEvent(sdk.MustAccAddressFromBech32("sei1v4mx6hmrda5kucnpwdjsqqqqqqqqqqqqlve8dv"), sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(27944)))), } @@ -231,7 +231,7 @@ func TestRun(t *testing.T) { Denom: "ufoo", }, bank.CoinBalance(parsedBalances[0])) require.Equal(t, bank.CoinBalance{ - Amount: big.NewInt(9972045), + Amount: big.NewInt(9841905), Denom: "usei", }, bank.CoinBalance(parsedBalances[1])) diff --git a/precompiles/pointer/pointer_test.go b/precompiles/pointer/pointer_test.go index d3fe14b00..d49fa2731 100644 --- a/precompiles/pointer/pointer_test.go +++ b/precompiles/pointer/pointer_test.go @@ -57,7 +57,7 @@ func TestAddNative(t *testing.T) { evm = vm.NewEVM(*blockCtx, vm.TxContext{}, statedb, cfg, vm.Config{}) ret, g, err := p.RunAndCalculateGas(evm, caller, caller, append(p.GetExecutor().(*pointer.PrecompileExecutor).AddNativePointerID, args...), suppliedGas, nil, nil, false, false) require.Nil(t, err) - require.Equal(t, uint64(8888494), g) + require.Equal(t, uint64(8881534), g) outputs, err := m.Outputs.Unpack(ret) require.Nil(t, err) addr := outputs[0].(common.Address) diff --git a/proto/evm/params.proto b/proto/evm/params.proto index d945c7c9c..54d5ba3ff 100644 --- a/proto/evm/params.proto +++ b/proto/evm/params.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package seiprotocol.seichain.evm; import "gogoproto/gogo.proto"; -import "evm/config.proto"; option go_package = "github.com/sei-protocol/sei-chain/x/evm/types"; @@ -49,4 +48,60 @@ string minimum_fee_per_gas = 4 [ ]; uint64 deliver_tx_hook_wasm_gas_limit = 9; + + string max_dynamic_base_fee_upward_adjustment = 10 [ + (gogoproto.moretags) = "yaml:\"max_dynamic_base_fee_upward_adjustment\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "max_dynamic_base_fee_upward_adjustment" + ]; + string max_dynamic_base_fee_downward_adjustment = 11 [ + (gogoproto.moretags) = "yaml:\"max_dynamic_base_fee_downward_adjustment\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "max_dynamic_base_fee_downward_adjustment" + ]; + uint64 target_gas_used_per_block = 12; +} + +message ParamsPreV580 { + option (gogoproto.goproto_stringer) = false; + + // string base_denom = 1 [ + // (gogoproto.moretags) = "yaml:\"base_denom\"", + // (gogoproto.jsontag) = "base_denom" + // ]; + string priority_normalizer = 2 [ + (gogoproto.moretags) = "yaml:\"priority_normalizer\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "priority_normalizer" + ]; + string base_fee_per_gas = 3 [ + (gogoproto.moretags) = "yaml:\"base_fee_per_gas\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "base_fee_per_gas" +]; +string minimum_fee_per_gas = 4 [ + (gogoproto.moretags) = "yaml:\"minimum_fee_per_gas\"", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "minimum_fee_per_gas" +]; + // ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false]; +// string chain_id = 6 [ +// (gogoproto.moretags) = "yaml:\"chain_id\"", +// (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", +// (gogoproto.nullable) = false, +// (gogoproto.jsontag) = "chain_id" +// ]; +// repeated string whitelisted_codehashes_bank_send = 7 [ +// (gogoproto.moretags) = "yaml:\"whitelisted_codehashes_bank_send\"", +// (gogoproto.jsontag) = "whitelisted_codehashes_bank_send" +// ]; +repeated bytes whitelisted_cw_code_hashes_for_delegate_call = 8 [ + (gogoproto.moretags) = "yaml:\"whitelisted_cw_code_hashes_for_delegate_call\"", + (gogoproto.jsontag) = "whitelisted_cw_code_hashes_for_delegate_call" +]; } \ No newline at end of file diff --git a/run_blocktests.sh b/run_blocktests.sh index 05367f6d5..0620f9bbf 100755 --- a/run_blocktests.sh +++ b/run_blocktests.sh @@ -34,6 +34,14 @@ declare -a test_name_skip_list=( "BLOCKHASH_Bounds" # failing "logRevert" # uses an invalid opcode (0xBA) "blockWithAllTransactionTypes" # recently started failing + "tipInsideBlock" # failing after turning on eip-1559 and not burning base fee + "multimpleBalanceInstruction" # failing after turning on eip-1559 and not burning base fee + "tips" # failing after turning on eip-1559 and not burning base fee + "burnVerify" # failing after turning on eip-1559 and not burning base fee + "emptyPostTransfer" # failing after turning on eip-1559 and not burning base fee + "multimpleBalanceInstruction" # failing from 150% max gas refund change + "burnVerify" # failing from 150% max gas refund change + "refundReset" # failing from 150% max gas refund change # invalid block tests - state tests "gasLimitTooHigh" # block header gas limit doesn't apply to us diff --git a/testutil/keeper/epoch.go b/testutil/keeper/epoch.go index 57f91de84..9b952670b 100644 --- a/testutil/keeper/epoch.go +++ b/testutil/keeper/epoch.go @@ -36,7 +36,7 @@ func EpochKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { cdc := codec.NewProtoCodec(registry) paramsSubspace := typesparams.NewSubspace(cdc, - types.Amino, + codec.NewLegacyAmino(), storeKey, memStoreKey, "EpochParams", diff --git a/utils/metrics/metrics_util.go b/utils/metrics/metrics_util.go index 4252e4b96..0eca18118 100644 --- a/utils/metrics/metrics_util.go +++ b/utils/metrics/metrics_util.go @@ -357,3 +357,14 @@ func HistogramEvmEffectiveGasPrice(gasPrice *big.Int) { float32(gasPrice.Uint64()), ) } + +// Gauge for block base fee +// Metric Name: +// +// sei_evm_block_base_fee +func GaugeEvmBlockBaseFee(baseFee *big.Int, blockHeight int64) { + metrics.SetGauge( + []string{"sei", "evm", "block", "base", "fee"}, + float32(baseFee.Uint64()), + ) +} diff --git a/x/epoch/types/codec.go b/x/epoch/types/codec.go index ed7430baa..3ff1468d0 100644 --- a/x/epoch/types/codec.go +++ b/x/epoch/types/codec.go @@ -15,6 +15,11 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { } var ( - Amino = codec.NewLegacyAmino() - ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) ) + +func init() { + RegisterCodec(amino) + amino.Seal() +} diff --git a/x/evm/ante/fee.go b/x/evm/ante/fee.go index 262a88fe8..b85edc2b1 100644 --- a/x/evm/ante/fee.go +++ b/x/evm/ante/fee.go @@ -47,6 +47,9 @@ func (fc EVMFeeCheckDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b if txData.GetGasFeeCap().Cmp(fc.getMinimumFee(ctx)) < 0 { return ctx, sdkerrors.ErrInsufficientFee } + if txData.GetGasTipCap().Sign() < 0 { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "gas fee cap cannot be negative") + } // if EVM version is Cancun or later, and the transaction contains at least one blob, we need to // make sure the transaction carries a non-zero blob fee cap. @@ -99,12 +102,12 @@ func (fc EVMFeeCheckDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b return next(ctx, tx, simulate) } -// fee per gas to be burnt +// minimum fee per gas required for a tx to be processed func (fc EVMFeeCheckDecorator) getBaseFee(ctx sdk.Context) *big.Int { - return fc.evmKeeper.GetBaseFeePerGas(ctx).TruncateInt().BigInt() + return fc.evmKeeper.GetDynamicBaseFeePerGas(ctx).TruncateInt().BigInt() } -// lowest allowed fee per gas +// lowest allowed fee per gas, base fee will not be lower than this func (fc EVMFeeCheckDecorator) getMinimumFee(ctx sdk.Context) *big.Int { return fc.evmKeeper.GetMinimumFeePerGas(ctx).TruncateInt().BigInt() } diff --git a/x/evm/ante/fee_test.go b/x/evm/ante/fee_test.go index 138d22dbd..0d4015e9e 100644 --- a/x/evm/ante/fee_test.go +++ b/x/evm/ante/fee_test.go @@ -112,6 +112,24 @@ func TestEVMFeeCheckDecorator(t *testing.T) { return ctx, nil }) require.NotNil(t, err) + + // should fail because of negative gas tip cap + txData.GasTipCap = big.NewInt(-1) + txData.GasFeeCap = big.NewInt(10000000000000) + tx, err = ethtypes.SignTx(ethtypes.NewTx(&txData), signer, key) + require.Nil(t, err) + typedTx = newDynamicFeeTxWithoutValidation(tx) + msg, err = types.NewMsgEVMTransaction(typedTx) + require.Nil(t, err) + ctx, err = preprocessor.AnteHandle(ctx, mockTx{msgs: []sdk.Msg{msg}}, false, func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { + return ctx, nil + }) + require.Nil(t, err) + _, err = handler.AnteHandle(ctx, mockTx{msgs: []sdk.Msg{msg}}, false, func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { + return ctx, nil + }) + require.NotNil(t, err) + require.Contains(t, err.Error(), "gas fee cap cannot be negative") } func TestCalculatePriorityScenarios(t *testing.T) { @@ -227,3 +245,22 @@ func TestCalculatePriorityScenarios(t *testing.T) { }) } } + +func newDynamicFeeTxWithoutValidation(tx *ethtypes.Transaction) *ethtx.DynamicFeeTx { + txData := ðtx.DynamicFeeTx{ + Nonce: tx.Nonce(), + Data: tx.Data(), + GasLimit: tx.Gas(), + } + + v, r, s := tx.RawSignatureValues() + ethtx.SetConvertIfPresent(tx.To(), func(to *common.Address) string { return to.Hex() }, txData.SetTo) + ethtx.SetConvertIfPresent(tx.Value(), sdk.NewIntFromBigInt, txData.SetAmount) + ethtx.SetConvertIfPresent(tx.GasFeeCap(), sdk.NewIntFromBigInt, txData.SetGasFeeCap) + ethtx.SetConvertIfPresent(tx.GasTipCap(), sdk.NewIntFromBigInt, txData.SetGasTipCap) + al := tx.AccessList() + ethtx.SetConvertIfPresent(&al, ethtx.NewAccessList, txData.SetAccesses) + + txData.SetSignatureValues(tx.ChainId(), v, r, s) + return txData +} diff --git a/x/evm/ante/sig.go b/x/evm/ante/sig.go index 4d0ed5a8c..c23cce69c 100644 --- a/x/evm/ante/sig.go +++ b/x/evm/ante/sig.go @@ -47,13 +47,13 @@ func (svd *EVMSigVerifyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulat case ethtypes.LegacyTxType: // legacy either can have a zero or correct chain ID if txChainID.Cmp(big.NewInt(0)) != 0 && txChainID.Cmp(chainID) != 0 { - ctx.Logger().Error("chainID mismatch", "txChainID", ethTx.ChainId(), "chainID", chainID) + ctx.Logger().Debug("chainID mismatch", "txChainID", ethTx.ChainId(), "chainID", chainID) return ctx, sdkerrors.ErrInvalidChainID } default: // after legacy, all transactions must have the correct chain ID if txChainID.Cmp(chainID) != 0 { - ctx.Logger().Error("chainID mismatch", "txChainID", ethTx.ChainId(), "chainID", chainID) + ctx.Logger().Debug("chainID mismatch", "txChainID", ethTx.ChainId(), "chainID", chainID) return ctx, sdkerrors.ErrInvalidChainID } } diff --git a/x/evm/genesis_test.go b/x/evm/genesis_test.go index f43dc2d60..df2453b35 100644 --- a/x/evm/genesis_test.go +++ b/x/evm/genesis_test.go @@ -33,6 +33,8 @@ func TestExportImportGenesis(t *testing.T) { assert.Equal(t, types.DefaultParams().BaseFeePerGas, param.BaseFeePerGas) assert.Equal(t, types.DefaultParams().MinimumFeePerGas, param.MinimumFeePerGas) assert.Equal(t, types.DefaultParams().WhitelistedCwCodeHashesForDelegateCall, param.WhitelistedCwCodeHashesForDelegateCall) + assert.Equal(t, types.DefaultParams().MaxDynamicBaseFeeUpwardAdjustment, param.MaxDynamicBaseFeeUpwardAdjustment) + assert.Equal(t, types.DefaultParams().MaxDynamicBaseFeeDownwardAdjustment, param.MaxDynamicBaseFeeDownwardAdjustment) evm.InitGenesis(origctx, keeper, *genesis) require.Equal(t, evmAddr, keeper.GetEVMAddressOrDefault(origctx, seiAddr)) require.Equal(t, keeper.GetCode(ctx, codeAddr), keeper.GetCode(origctx, codeAddr)) diff --git a/x/evm/keeper/evm_test.go b/x/evm/keeper/evm_test.go index afd667b6e..3d4a0162b 100644 --- a/x/evm/keeper/evm_test.go +++ b/x/evm/keeper/evm_test.go @@ -39,11 +39,15 @@ func TestInternalCallCreateContract(t *testing.T) { _, err = k.HandleInternalEVMCall(ctx, req) require.Equal(t, "sei does not support EVM->CW->EVM call pattern", err.Error()) ctx = ctx.WithIsEVM(false) + oldBaseFee := k.GetDynamicBaseFeePerGas(ctx) + k.SetDynamicBaseFeePerGas(ctx, sdk.ZeroDec()) _, err = k.HandleInternalEVMCall(ctx, req) require.Nil(t, err) receipt, err := k.GetTransientReceipt(ctx, [32]byte{1, 2, 3}) require.Nil(t, err) require.NotNil(t, receipt) + // reset base fee + k.SetDynamicBaseFeePerGas(ctx, oldBaseFee) } func TestInternalCall(t *testing.T) { diff --git a/x/evm/keeper/fee.go b/x/evm/keeper/fee.go new file mode 100644 index 000000000..b00e7912a --- /dev/null +++ b/x/evm/keeper/fee.go @@ -0,0 +1,77 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/sei-protocol/sei-chain/x/evm/types" +) + +// modified eip-1559 adjustment using target gas used +func (k *Keeper) AdjustDynamicBaseFeePerGas(ctx sdk.Context, blockGasUsed uint64) *sdk.Dec { + if ctx.ConsensusParams() == nil || ctx.ConsensusParams().Block == nil { + return nil + } + currentBaseFee := k.GetDynamicBaseFeePerGas(ctx) + targetGasUsed := sdk.NewDec(int64(k.GetTargetGasUsedPerBlock(ctx))) + if targetGasUsed.IsZero() { + return ¤tBaseFee + } + minimumFeePerGas := k.GetParams(ctx).MinimumFeePerGas + blockGasLimit := sdk.NewDec(ctx.ConsensusParams().Block.MaxGas) + blockGasUsedDec := sdk.NewDec(int64(blockGasUsed)) + + // cap block gas used to block gas limit + if blockGasUsedDec.GT(blockGasLimit) { + blockGasUsedDec = blockGasLimit + } + + var newBaseFee sdk.Dec + if blockGasUsedDec.GT(targetGasUsed) { + // upward adjustment + numerator := blockGasUsedDec.Sub(targetGasUsed) + denominator := blockGasLimit.Sub(targetGasUsed) + percentageFull := numerator.Quo(denominator) + adjustmentFactor := k.GetMaxDynamicBaseFeeUpwardAdjustment(ctx).Mul(percentageFull) + newBaseFee = currentBaseFee.Mul(sdk.NewDec(1).Add(adjustmentFactor)) + } else { + // downward adjustment + numerator := targetGasUsed.Sub(blockGasUsedDec) + denominator := targetGasUsed + percentageEmpty := numerator.Quo(denominator) + adjustmentFactor := k.GetMaxDynamicBaseFeeDownwardAdjustment(ctx).Mul(percentageEmpty) + newBaseFee = currentBaseFee.Mul(sdk.NewDec(1).Sub(adjustmentFactor)) + } + + // Ensure the new base fee is not lower than the minimum fee + if newBaseFee.LT(minimumFeePerGas) { + newBaseFee = minimumFeePerGas + } + + // Set the new base fee for the next height + k.SetDynamicBaseFeePerGas(ctx.WithBlockHeight(ctx.BlockHeight()+1), newBaseFee) + + return &newBaseFee +} + +// dont have height be a prefix, just store the current base fee directly +func (k *Keeper) GetDynamicBaseFeePerGas(ctx sdk.Context) sdk.Dec { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.BaseFeePerGasPrefix) + if bz == nil { + return k.GetMinimumFeePerGas(ctx) + } + d := sdk.Dec{} + err := d.UnmarshalJSON(bz) + if err != nil { + panic(err) + } + return d +} + +func (k *Keeper) SetDynamicBaseFeePerGas(ctx sdk.Context, baseFeePerGas sdk.Dec) { + store := ctx.KVStore(k.storeKey) + bz, err := baseFeePerGas.MarshalJSON() + if err != nil { + panic(err) + } + store.Set(types.BaseFeePerGasPrefix, bz) +} diff --git a/x/evm/keeper/fee_test.go b/x/evm/keeper/fee_test.go new file mode 100644 index 000000000..981a4b2bb --- /dev/null +++ b/x/evm/keeper/fee_test.go @@ -0,0 +1,155 @@ +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" + "github.com/stretchr/testify/require" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" +) + +func TestBaseFeePerGas(t *testing.T) { + k := &testkeeper.EVMTestApp.EvmKeeper + ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}) + require.Equal(t, k.GetMinimumFeePerGas(ctx), k.GetDynamicBaseFeePerGas(ctx)) + originalbf := k.GetDynamicBaseFeePerGas(ctx) + k.SetDynamicBaseFeePerGas(ctx, sdk.OneDec()) + require.Equal(t, sdk.NewDecFromInt(sdk.NewInt(1)), k.GetDynamicBaseFeePerGas(ctx)) + k.SetDynamicBaseFeePerGas(ctx, originalbf) +} + +func TestAdjustBaseFeePerGas(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + testCases := []struct { + name string + currentBaseFee float64 + minimumFee float64 + blockGasUsed uint64 + blockGasLimit uint64 + upwardAdj sdk.Dec + downwardAdj sdk.Dec + targetGasUsed uint64 + expectedBaseFee uint64 + }{ + { + name: "Block gas usage exactly half of limit, 0% up, 0% down, no fee change", + currentBaseFee: 100, + minimumFee: 10, + blockGasUsed: 500000, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDec(0), + downwardAdj: sdk.NewDec(0), + targetGasUsed: 500000, + expectedBaseFee: 100, + }, + { + name: "Block gas usage 50%, 50% up, 50% down, no fee change", + currentBaseFee: 100, + minimumFee: 10, + blockGasUsed: 500000, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDecWithPrec(5, 1), + downwardAdj: sdk.NewDecWithPrec(5, 1), + targetGasUsed: 500000, + expectedBaseFee: 100, + }, + { + name: "Block gas usage 75%, 0% up, 0% down, base fee stays the same", + currentBaseFee: 10000, + minimumFee: 10, + blockGasUsed: 750000, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDec(0), + downwardAdj: sdk.NewDec(0), + targetGasUsed: 500000, + expectedBaseFee: 10000, + }, + { + name: "Block gas usage 25%, 0% up, 0% down, base fee stays the same", + currentBaseFee: 10000, + minimumFee: 10, + blockGasUsed: 250000, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDec(0), + downwardAdj: sdk.NewDec(0), + targetGasUsed: 500000, + expectedBaseFee: 10000, + }, + { + name: "Block gas usage 75%, 50% up, 0% down, base fee increases by 25%", + currentBaseFee: 10000, + minimumFee: 10, + blockGasUsed: 750000, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDecWithPrec(5, 1), + downwardAdj: sdk.NewDec(0), + targetGasUsed: 500000, + expectedBaseFee: 12500, + }, + { + name: "Block gas usage 25%, 0% up, 50% down, base fee decreases by 25%", + currentBaseFee: 10000, + minimumFee: 10, + blockGasUsed: 250000, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDec(0), + downwardAdj: sdk.NewDecWithPrec(5, 1), + targetGasUsed: 500000, + expectedBaseFee: 7500, + }, + { + name: "Block gas usage low, new base fee below minimum, set to minimum", + currentBaseFee: 100, + minimumFee: 99, + blockGasUsed: 0, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDecWithPrec(5, 2), + downwardAdj: sdk.NewDecWithPrec(5, 2), + targetGasUsed: 500000, + expectedBaseFee: 99, // Should not go below the minimum fee + }, + { + name: "target gas used is 0", + currentBaseFee: 10000, + minimumFee: 10, + blockGasUsed: 0, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDecWithPrec(5, 1), + downwardAdj: sdk.NewDecWithPrec(5, 1), + targetGasUsed: 0, + expectedBaseFee: 10000, + }, + { + name: "cap block gas used to block gas limit", + // block gas used is 1.5x block gas limit + currentBaseFee: 10000, + minimumFee: 10, + blockGasUsed: 1500000, + blockGasLimit: 1000000, + upwardAdj: sdk.NewDecWithPrec(5, 1), + downwardAdj: sdk.NewDecWithPrec(5, 1), + targetGasUsed: 500000, + expectedBaseFee: 15000, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ctx = ctx.WithConsensusParams(&tmproto.ConsensusParams{ + Block: &tmproto.BlockParams{MaxGas: int64(tc.blockGasLimit)}, + }) + k.SetDynamicBaseFeePerGas(ctx, sdk.NewDecFromInt(sdk.NewInt(int64(tc.currentBaseFee)))) + p := k.GetParams(ctx) + p.MinimumFeePerGas = sdk.NewDec(int64(tc.minimumFee)) + p.MaxDynamicBaseFeeUpwardAdjustment = tc.upwardAdj + p.MaxDynamicBaseFeeDownwardAdjustment = tc.downwardAdj + p.TargetGasUsedPerBlock = tc.targetGasUsed + k.SetParams(ctx, p) + k.AdjustDynamicBaseFeePerGas(ctx, tc.blockGasUsed) + expected := sdk.NewDecFromInt(sdk.NewInt(int64(tc.expectedBaseFee))) + height := ctx.BlockHeight() + require.Equal(t, expected, k.GetDynamicBaseFeePerGas(ctx.WithBlockHeight(height+1)), "base fee did not match expected value") + }) + } +} diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 889f1c167..9b754398e 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -209,9 +209,9 @@ func (k *Keeper) GetVMBlockContext(ctx sdk.Context, gp core.GasPool) (*vm.BlockC GasLimit: gp.Gas(), BlockNumber: big.NewInt(ctx.BlockHeight()), Time: uint64(ctx.BlockHeader().Time.Unix()), - Difficulty: utils.Big0, // only needed for PoW - BaseFee: k.GetBaseFeePerGas(ctx).TruncateInt().BigInt(), // feemarket not enabled - BlobBaseFee: utils.Big1, // Cancun not enabled + Difficulty: utils.Big0, // only needed for PoW + BaseFee: k.GetDynamicBaseFeePerGas(ctx).TruncateInt().BigInt(), + BlobBaseFee: utils.Big1, // Cancun not enabled Random: &rh, }, nil } diff --git a/x/evm/keeper/msg_server_test.go b/x/evm/keeper/msg_server_test.go index deb333287..d4bc82971 100644 --- a/x/evm/keeper/msg_server_test.go +++ b/x/evm/keeper/msg_server_test.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/sha256" "encoding/hex" + "fmt" "math/big" "os" "testing" @@ -338,14 +339,17 @@ func TestEVMPrecompiles(t *testing.T) { return ctx, nil }) require.Nil(t, err) + coinbaseBalanceBefore := k.BankKeeper().GetBalance(ctx, state.GetCoinbaseAddress(ctx.TxIndex()), "usei").Amount.Uint64() res, err := msgServer.EVMTransaction(sdk.WrapSDKContext(ctx), req) require.Nil(t, err) require.LessOrEqual(t, res.GasUsed, uint64(500000)) require.Empty(t, res.VmError) require.NotEmpty(t, res.ReturnData) 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.Equal(t, uint64(1000000)-res.GasUsed, k.BankKeeper().GetBalance(ctx, sdk.AccAddress(evmAddr[:]), k.GetBaseDenom(ctx)).Amount.Uint64()) + coinbaseBalanceAfter := k.BankKeeper().GetBalance(ctx, state.GetCoinbaseAddress(ctx.TxIndex()), k.GetBaseDenom(ctx)).Amount.Uint64() + diff := coinbaseBalanceAfter - coinbaseBalanceBefore + require.Equal(t, res.GasUsed, diff) require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) @@ -462,7 +466,11 @@ func TestEVMBlockEnv(t *testing.T) { require.NotEmpty(t, res.ReturnData) 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()) + fmt.Println("all balances sender = ", k.BankKeeper().GetAllBalances(ctx, sdk.AccAddress(evmAddr[:]))) + fmt.Println("all balances coinbase = ", k.BankKeeper().GetAllBalances(ctx, state.GetCoinbaseAddress(ctx.TxIndex()))) + fmt.Println("wei = ", k.BankKeeper().GetBalance(ctx, state.GetCoinbaseAddress(ctx.TxIndex()), "wei").Amount.Uint64()) + require.Equal(t, res.GasUsed, k.BankKeeper().GetBalance(ctx, state.GetCoinbaseAddress(ctx.TxIndex()), "usei").Amount.Uint64()) + require.NoError(t, k.FlushTransientReceipts(ctx)) receipt, err := k.GetReceipt(ctx, common.HexToHash(res.Hash)) require.Nil(t, err) diff --git a/x/evm/keeper/params.go b/x/evm/keeper/params.go index fc0b6dc57..992a6390f 100644 --- a/x/evm/keeper/params.go +++ b/x/evm/keeper/params.go @@ -37,10 +37,22 @@ func (k *Keeper) GetBaseFeePerGas(ctx sdk.Context) sdk.Dec { return k.GetParams(ctx).BaseFeePerGas } +func (k *Keeper) GetMaxDynamicBaseFeeUpwardAdjustment(ctx sdk.Context) sdk.Dec { + return k.GetParams(ctx).MaxDynamicBaseFeeUpwardAdjustment +} + +func (k *Keeper) GetMaxDynamicBaseFeeDownwardAdjustment(ctx sdk.Context) sdk.Dec { + return k.GetParams(ctx).MaxDynamicBaseFeeDownwardAdjustment +} + func (k *Keeper) GetMinimumFeePerGas(ctx sdk.Context) sdk.Dec { return k.GetParams(ctx).MinimumFeePerGas } +func (k *Keeper) GetTargetGasUsedPerBlock(ctx sdk.Context) uint64 { + return k.GetParams(ctx).TargetGasUsedPerBlock +} + func (k *Keeper) GetDeliverTxHookWasmGasLimit(ctx sdk.Context) uint64 { return k.GetParams(ctx).DeliverTxHookWasmGasLimit } diff --git a/x/evm/keeper/params_test.go b/x/evm/keeper/params_test.go index 2f157ad68..f47323152 100644 --- a/x/evm/keeper/params_test.go +++ b/x/evm/keeper/params_test.go @@ -15,10 +15,12 @@ func TestParams(t *testing.T) { ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}).WithBlockTime(time.Now()) require.Equal(t, "usei", k.GetBaseDenom(ctx)) require.Equal(t, types.DefaultPriorityNormalizer, k.GetPriorityNormalizer(ctx)) + require.Equal(t, types.DefaultMinFeePerGas, k.GetDynamicBaseFeePerGas(ctx)) require.Equal(t, types.DefaultBaseFeePerGas, k.GetBaseFeePerGas(ctx)) require.Equal(t, types.DefaultMinFeePerGas, k.GetMinimumFeePerGas(ctx)) require.Equal(t, types.DefaultDeliverTxHookWasmGasLimit, k.GetDeliverTxHookWasmGasLimit(ctx)) - + require.Equal(t, types.DefaultMaxDynamicBaseFeeUpwardAdjustment, k.GetMaxDynamicBaseFeeUpwardAdjustment(ctx)) + require.Equal(t, types.DefaultMaxDynamicBaseFeeDownwardAdjustment, k.GetMaxDynamicBaseFeeDownwardAdjustment(ctx)) require.Nil(t, k.GetParams(ctx).Validate()) } diff --git a/x/evm/keeper/replay.go b/x/evm/keeper/replay.go index c202b38ed..0af33741e 100644 --- a/x/evm/keeper/replay.go +++ b/x/evm/keeper/replay.go @@ -66,6 +66,7 @@ func (k *Keeper) VerifyTxResult(ctx sdk.Context, hash common.Hash) { } func (k *Keeper) VerifyAccount(ctx sdk.Context, addr common.Address, accountData core.GenesisAccount) { + // we no longer check eth balance due to limiting EVM max refund to 150% of used gas (https://github.com/sei-protocol/go-ethereum/pull/32) code := accountData.Code for key, expectedState := range accountData.Storage { actualState := k.GetState(ctx, addr, key) @@ -73,22 +74,24 @@ func (k *Keeper) VerifyAccount(ctx sdk.Context, addr common.Address, accountData panic(fmt.Sprintf("storage mismatch for address %s: expected %X, got %X", addr.Hex(), expectedState, actualState)) } } - balance := accountData.Balance nonce := accountData.Nonce if !bytes.Equal(code, k.GetCode(ctx, addr)) { panic(fmt.Sprintf("code mismatch for address %s", addr)) } - useiBalance := k.BankKeeper().GetBalance(ctx, k.GetSeiAddressOrDefault(ctx, addr), "usei").Amount - weiBalance := k.bankKeeper.GetWeiBalance(ctx, k.GetSeiAddressOrDefault(ctx, addr)) - totalSeiBalance := useiBalance.Mul(sdk.NewInt(1_000_000_000_000)).Add(weiBalance).BigInt() - if balance.Cmp(totalSeiBalance) != 0 { - panic(fmt.Sprintf("balance mismatch for address %s: expected %s, got %s", addr.Hex(), balance, totalSeiBalance)) - } if nonce != k.GetNonce(ctx, addr) { panic(fmt.Sprintf("nonce mismatch for address %s: expected %d, got %d", addr.Hex(), nonce, k.GetNonce(ctx, addr))) } } +func contains(slice []common.Address, element common.Address) bool { + for _, v := range slice { + if v == element { + return true + } + } + return false +} + func (k *Keeper) VerifyState(ctx sdk.Context, addr common.Address) { store := k.PrefixStore(ctx, types.StateKey(addr)) iter := store.Iterator(nil, nil) diff --git a/x/evm/migrations/migrate_eip_1559_params.go b/x/evm/migrations/migrate_eip_1559_params.go new file mode 100644 index 000000000..f3d8975c2 --- /dev/null +++ b/x/evm/migrations/migrate_eip_1559_params.go @@ -0,0 +1,17 @@ +package migrations + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/sei-protocol/sei-chain/x/evm/keeper" + "github.com/sei-protocol/sei-chain/x/evm/types" +) + +func MigrateEip1559Params(ctx sdk.Context, k *keeper.Keeper) error { + keeperParams := k.GetParamsIfExists(ctx) + keeperParams.MaxDynamicBaseFeeUpwardAdjustment = types.DefaultParams().MaxDynamicBaseFeeUpwardAdjustment + keeperParams.MaxDynamicBaseFeeDownwardAdjustment = types.DefaultParams().MaxDynamicBaseFeeDownwardAdjustment + keeperParams.TargetGasUsedPerBlock = types.DefaultParams().TargetGasUsedPerBlock + keeperParams.MinimumFeePerGas = types.DefaultParams().MinimumFeePerGas + k.SetParams(ctx, keeperParams) + return nil +} diff --git a/x/evm/migrations/migrate_eip_1559_params_test.go b/x/evm/migrations/migrate_eip_1559_params_test.go new file mode 100644 index 000000000..392b8820c --- /dev/null +++ b/x/evm/migrations/migrate_eip_1559_params_test.go @@ -0,0 +1,31 @@ +package migrations_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" + "github.com/sei-protocol/sei-chain/x/evm/migrations" + "github.com/sei-protocol/sei-chain/x/evm/types" + "github.com/stretchr/testify/require" + tmtypes "github.com/tendermint/tendermint/proto/tendermint/types" +) + +func TestMigrateEip1559Params(t *testing.T) { + k := testkeeper.EVMTestApp.EvmKeeper + ctx := testkeeper.EVMTestApp.NewContext(false, tmtypes.Header{}) + + keeperParams := k.GetParams(ctx) + keeperParams.BaseFeePerGas = sdk.NewDec(123) + + // Perform the migration + err := migrations.MigrateEip1559Params(ctx, &k) + require.NoError(t, err) + + // Ensure that the new EIP-1559 parameters were migrated and the old ones were not changed + require.Equal(t, keeperParams.BaseFeePerGas, sdk.NewDec(123)) + require.Equal(t, keeperParams.MaxDynamicBaseFeeUpwardAdjustment, types.DefaultParams().MaxDynamicBaseFeeUpwardAdjustment) + require.Equal(t, keeperParams.MaxDynamicBaseFeeDownwardAdjustment, types.DefaultParams().MaxDynamicBaseFeeDownwardAdjustment) + require.Equal(t, keeperParams.TargetGasUsedPerBlock, types.DefaultParams().TargetGasUsedPerBlock) + require.Equal(t, keeperParams.MinimumFeePerGas, types.DefaultParams().MinimumFeePerGas) +} diff --git a/x/evm/module.go b/x/evm/module.go index 16d44ecb5..a923df804 100644 --- a/x/evm/module.go +++ b/x/evm/module.go @@ -24,6 +24,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/sei-protocol/sei-chain/utils" + "github.com/sei-protocol/sei-chain/utils/metrics" "github.com/sei-protocol/sei-chain/x/evm/client/cli" "github.com/sei-protocol/sei-chain/x/evm/keeper" "github.com/sei-protocol/sei-chain/x/evm/migrations" @@ -49,9 +50,9 @@ func (AppModuleBasic) Name() string { return types.ModuleName } -func (AppModuleBasic) RegisterCodec(*codec.LegacyAmino) {} - -func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterCodec(cdc) +} // RegisterInterfaces registers the module's interface types func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { @@ -216,6 +217,10 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { _ = cfg.RegisterMigration(types.ModuleName, 12, func(ctx sdk.Context) error { return migrations.MigrateBlockBloom(ctx, am.keeper) }) + + _ = cfg.RegisterMigration(types.ModuleName, 13, func(ctx sdk.Context) error { + return migrations.MigrateEip1559Params(ctx, am.keeper) + }) } // RegisterInvariants registers the capability module's invariants. @@ -253,7 +258,7 @@ func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <- } // ConsensusVersion implements ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 13 } +func (AppModule) ConsensusVersion() uint64 { return 14 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { @@ -280,7 +285,11 @@ func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { // EndBlock executes all ABCI EndBlock logic respective to the evm module. It // returns no validator updates. -func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { +func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { + newBaseFee := am.keeper.AdjustDynamicBaseFeePerGas(ctx, uint64(req.BlockGasUsed)) + if newBaseFee != nil { + metrics.GaugeEvmBlockBaseFee(newBaseFee.TruncateInt().BigInt(), req.Height) + } var coinbase sdk.AccAddress if am.keeper.EthBlockTestConfig.Enabled { blocks := am.keeper.BlockTest.Json.Blocks diff --git a/x/evm/module_test.go b/x/evm/module_test.go index 624810dea..aecb5874e 100644 --- a/x/evm/module_test.go +++ b/x/evm/module_test.go @@ -51,15 +51,16 @@ func TestQuerierRoute(t *testing.T) { func TestModuleExportGenesis(t *testing.T) { k, ctx := testkeeper.MockEVMKeeper() module := evm.NewAppModule(nil, k) - jsonMsg := module.ExportGenesis(ctx, types.ModuleCdc) + cdc := app.MakeEncodingConfig().Marshaler + jsonMsg := module.ExportGenesis(ctx, cdc) jsonStr := string(jsonMsg) - assert.Equal(t, "{\"params\":{\"priority_normalizer\":\"1.000000000000000000\",\"base_fee_per_gas\":\"0.000000000000000000\",\"minimum_fee_per_gas\":\"100000000000.000000000000000000\",\"whitelisted_cw_code_hashes_for_delegate_call\":[],\"deliver_tx_hook_wasm_gas_limit\":\"300000\"},\"address_associations\":[{\"sei_address\":\"sei17xpfvakm2amg962yls6f84z3kell8c5la4jkdu\",\"eth_address\":\"0x27F7B8B8B5A4e71E8E9aA671f4e4031E3773303F\"}],\"codes\":[],\"states\":[],\"nonces\":[],\"serialized\":[{\"prefix\":\"Fg==\",\"key\":\"AwAC\",\"value\":\"AAAAAAAAAAM=\"},{\"prefix\":\"Fg==\",\"key\":\"BAAG\",\"value\":\"AAAAAAAAAAQ=\"}]}", jsonStr) + assert.Equal(t, `{"params":{"priority_normalizer":"1.000000000000000000","base_fee_per_gas":"0.000000000000000000","minimum_fee_per_gas":"1000000000.000000000000000000","whitelisted_cw_code_hashes_for_delegate_call":[],"deliver_tx_hook_wasm_gas_limit":"300000","max_dynamic_base_fee_upward_adjustment":"0.018900000000000000","max_dynamic_base_fee_downward_adjustment":"0.003900000000000000","target_gas_used_per_block":"250000"},"address_associations":[{"sei_address":"sei17xpfvakm2amg962yls6f84z3kell8c5la4jkdu","eth_address":"0x27F7B8B8B5A4e71E8E9aA671f4e4031E3773303F"}],"codes":[],"states":[],"nonces":[],"serialized":[{"prefix":"Fg==","key":"AwAC","value":"AAAAAAAAAAM="},{"prefix":"Fg==","key":"BAAG","value":"AAAAAAAAAAQ="}]}`, jsonStr) } func TestConsensusVersion(t *testing.T) { k, _ := testkeeper.MockEVMKeeper() module := evm.NewAppModule(nil, k) - assert.Equal(t, uint64(13), module.ConsensusVersion()) + assert.Equal(t, uint64(14), module.ConsensusVersion()) } func TestABCI(t *testing.T) { diff --git a/x/evm/types/codec.go b/x/evm/types/codec.go index e70f6d7a9..ac4ff396f 100644 --- a/x/evm/types/codec.go +++ b/x/evm/types/codec.go @@ -18,11 +18,11 @@ import ( var ( amino = codec.NewLegacyAmino() - ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) - AminoCdc = codec.NewAminoCodec(amino) + ModuleCdc = codec.NewAminoCodec(amino) ) func init() { + RegisterCodec(amino) cryptocodec.RegisterCrypto(amino) amino.Seal() } @@ -31,6 +31,14 @@ func GetAmino() *codec.LegacyAmino { return amino } +func RegisterCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgAssociate{}, "evm/MsgAssociate", nil) + cdc.RegisterConcrete(&MsgEVMTransaction{}, "evm/MsgEVMTransaction", nil) + cdc.RegisterConcrete(&MsgSend{}, "evm/MsgSend", nil) + cdc.RegisterConcrete(&MsgRegisterPointer{}, "evm/MsgRegisterPointer", nil) + cdc.RegisterConcrete(&MsgAssociateContractAddress{}, "evm/MsgAssociateContractAddress", nil) +} + func RegisterInterfaces(registry codectypes.InterfaceRegistry) { registry.RegisterImplementations((*govtypes.Content)(nil), &AddERCNativePointerProposal{}, diff --git a/x/evm/types/keys.go b/x/evm/types/keys.go index d6e269b3f..47402aa70 100644 --- a/x/evm/types/keys.go +++ b/x/evm/types/keys.go @@ -56,6 +56,7 @@ var ( DeferredInfoPrefix = []byte{0x19} // transient LegacyBlockBloomCutoffHeightKey = []byte{0x1a} + BaseFeePerGasPrefix = []byte{0x1b} ) var ( diff --git a/x/evm/types/params.go b/x/evm/types/params.go index 45663986b..905f9234b 100644 --- a/x/evm/types/params.go +++ b/x/evm/types/params.go @@ -10,11 +10,14 @@ import ( ) var ( - KeyPriorityNormalizer = []byte("KeyPriorityNormalizer") - KeyBaseFeePerGas = []byte("KeyBaseFeePerGas") - KeyMinFeePerGas = []byte("KeyMinFeePerGas") - KeyDeliverTxHookWasmGasLimit = []byte("KeyDeliverTxHookWasmGasLimit") + KeyPriorityNormalizer = []byte("KeyPriorityNormalizer") + KeyMinFeePerGas = []byte("KeyMinFeePerGas") + KeyDeliverTxHookWasmGasLimit = []byte("KeyDeliverTxHookWasmGasLimit") + KeyMaxDynamicBaseFeeUpwardAdjustment = []byte("KeyMaxDynamicBaseFeeUpwardAdjustment") + KeyMaxDynamicBaseFeeDownwardAdjustment = []byte("KeyMaxDynamicBaseFeeDownwardAdjustment") + KeyTargetGasUsedPerBlock = []byte("KeyTargetGasUsedPerBlock") // deprecated + KeyBaseFeePerGas = []byte("KeyBaseFeePerGas") KeyWhitelistedCwCodeHashesForDelegateCall = []byte("KeyWhitelistedCwCodeHashesForDelegateCall") ) @@ -23,12 +26,16 @@ var DefaultPriorityNormalizer = sdk.NewDec(1) // DefaultBaseFeePerGas determines how much usei per gas spent is // burnt rather than go to validators (similar to base fee on // Ethereum). -var DefaultBaseFeePerGas = sdk.NewDec(0) -var DefaultMinFeePerGas = sdk.NewDec(100000000000) +var DefaultBaseFeePerGas = sdk.NewDec(0) // used for static base fee, deprecated in favor of dynamic base fee +var DefaultMinFeePerGas = sdk.NewDec(1000000000) // 1gwei var DefaultDeliverTxHookWasmGasLimit = uint64(300000) var DefaultWhitelistedCwCodeHashesForDelegateCall = generateDefaultWhitelistedCwCodeHashesForDelegateCall() +var DefaultMaxDynamicBaseFeeUpwardAdjustment = sdk.NewDecWithPrec(189, 4) // 1.89% +var DefaultMaxDynamicBaseFeeDownwardAdjustment = sdk.NewDecWithPrec(39, 4) // .39% +var DefaultTargetGasUsedPerBlock = uint64(250000) // 250k + var _ paramtypes.ParamSet = (*Params)(nil) func ParamKeyTable() paramtypes.KeyTable { @@ -39,9 +46,12 @@ func DefaultParams() Params { return Params{ PriorityNormalizer: DefaultPriorityNormalizer, BaseFeePerGas: DefaultBaseFeePerGas, + MaxDynamicBaseFeeUpwardAdjustment: DefaultMaxDynamicBaseFeeUpwardAdjustment, + MaxDynamicBaseFeeDownwardAdjustment: DefaultMaxDynamicBaseFeeDownwardAdjustment, MinimumFeePerGas: DefaultMinFeePerGas, DeliverTxHookWasmGasLimit: DefaultDeliverTxHookWasmGasLimit, WhitelistedCwCodeHashesForDelegateCall: DefaultWhitelistedCwCodeHashesForDelegateCall, + TargetGasUsedPerBlock: DefaultTargetGasUsedPerBlock, } } @@ -49,9 +59,12 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyPriorityNormalizer, &p.PriorityNormalizer, validatePriorityNormalizer), paramtypes.NewParamSetPair(KeyBaseFeePerGas, &p.BaseFeePerGas, validateBaseFeePerGas), + paramtypes.NewParamSetPair(KeyMaxDynamicBaseFeeUpwardAdjustment, &p.MaxDynamicBaseFeeUpwardAdjustment, validateBaseFeeAdjustment), + paramtypes.NewParamSetPair(KeyMaxDynamicBaseFeeDownwardAdjustment, &p.MaxDynamicBaseFeeDownwardAdjustment, validateBaseFeeAdjustment), paramtypes.NewParamSetPair(KeyMinFeePerGas, &p.MinimumFeePerGas, validateMinFeePerGas), paramtypes.NewParamSetPair(KeyWhitelistedCwCodeHashesForDelegateCall, &p.WhitelistedCwCodeHashesForDelegateCall, validateWhitelistedCwHashesForDelegateCall), paramtypes.NewParamSetPair(KeyDeliverTxHookWasmGasLimit, &p.DeliverTxHookWasmGasLimit, validateDeliverTxHookWasmGasLimit), + paramtypes.NewParamSetPair(KeyTargetGasUsedPerBlock, &p.TargetGasUsedPerBlock, func(i interface{}) error { return nil }), } } @@ -71,9 +84,29 @@ func (p Params) Validate() error { if p.MinimumFeePerGas.LT(p.BaseFeePerGas) { return errors.New("minimum fee cannot be lower than base fee") } + if err := validateBaseFeeAdjustment(p.MaxDynamicBaseFeeUpwardAdjustment); err != nil { + return fmt.Errorf("invalid max dynamic base fee upward adjustment: %s, err: %s", p.MaxDynamicBaseFeeUpwardAdjustment, err) + } + if err := validateBaseFeeAdjustment(p.MaxDynamicBaseFeeDownwardAdjustment); err != nil { + return fmt.Errorf("invalid max dynamic base fee downward adjustment: %s, err: %s", p.MaxDynamicBaseFeeDownwardAdjustment, err) + } return validateWhitelistedCwHashesForDelegateCall(p.WhitelistedCwCodeHashesForDelegateCall) } +func validateBaseFeeAdjustment(i interface{}) error { + adjustment, ok := i.(sdk.Dec) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + if adjustment.IsNegative() { + return fmt.Errorf("negative base fee adjustment: %s", adjustment) + } + if adjustment.GT(sdk.OneDec()) { + return fmt.Errorf("base fee adjustment must be less than or equal to 1: %s", adjustment) + } + return nil +} + func (p Params) String() string { out, _ := yaml.Marshal(p) return string(out) diff --git a/x/evm/types/params.pb.go b/x/evm/types/params.pb.go index 44d20f736..fa42412a4 100644 --- a/x/evm/types/params.pb.go +++ b/x/evm/types/params.pb.go @@ -44,8 +44,11 @@ type Params struct { // (gogoproto.moretags) = "yaml:\"whitelisted_codehashes_bank_send\"", // (gogoproto.jsontag) = "whitelisted_codehashes_bank_send" // ]; - WhitelistedCwCodeHashesForDelegateCall [][]byte `protobuf:"bytes,8,rep,name=whitelisted_cw_code_hashes_for_delegate_call,json=whitelistedCwCodeHashesForDelegateCall,proto3" json:"whitelisted_cw_code_hashes_for_delegate_call" yaml:"whitelisted_cw_code_hashes_for_delegate_call"` - DeliverTxHookWasmGasLimit uint64 `protobuf:"varint,9,opt,name=deliver_tx_hook_wasm_gas_limit,json=deliverTxHookWasmGasLimit,proto3" json:"deliver_tx_hook_wasm_gas_limit,omitempty"` + WhitelistedCwCodeHashesForDelegateCall [][]byte `protobuf:"bytes,8,rep,name=whitelisted_cw_code_hashes_for_delegate_call,json=whitelistedCwCodeHashesForDelegateCall,proto3" json:"whitelisted_cw_code_hashes_for_delegate_call" yaml:"whitelisted_cw_code_hashes_for_delegate_call"` + DeliverTxHookWasmGasLimit uint64 `protobuf:"varint,9,opt,name=deliver_tx_hook_wasm_gas_limit,json=deliverTxHookWasmGasLimit,proto3" json:"deliver_tx_hook_wasm_gas_limit,omitempty"` + MaxDynamicBaseFeeUpwardAdjustment github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,10,opt,name=max_dynamic_base_fee_upward_adjustment,json=maxDynamicBaseFeeUpwardAdjustment,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_dynamic_base_fee_upward_adjustment" yaml:"max_dynamic_base_fee_upward_adjustment"` + MaxDynamicBaseFeeDownwardAdjustment github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,11,opt,name=max_dynamic_base_fee_downward_adjustment,json=maxDynamicBaseFeeDownwardAdjustment,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_dynamic_base_fee_downward_adjustment" yaml:"max_dynamic_base_fee_downward_adjustment"` + TargetGasUsedPerBlock uint64 `protobuf:"varint,12,opt,name=target_gas_used_per_block,json=targetGasUsedPerBlock,proto3" json:"target_gas_used_per_block,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -94,6 +97,13 @@ func (m *Params) GetDeliverTxHookWasmGasLimit() uint64 { return 0 } +func (m *Params) GetTargetGasUsedPerBlock() uint64 { + if m != nil { + return m.TargetGasUsedPerBlock + } + return 0 +} + func init() { proto.RegisterType((*Params)(nil), "seiprotocol.seichain.evm.Params") } @@ -101,37 +111,46 @@ func init() { func init() { proto.RegisterFile("evm/params.proto", fileDescriptor_9272f3679901ea94) } var fileDescriptor_9272f3679901ea94 = []byte{ - // 473 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xcf, 0x8b, 0xd3, 0x40, - 0x14, 0x4e, 0xdc, 0xba, 0xb8, 0x41, 0xa1, 0x64, 0x05, 0x63, 0x0f, 0x49, 0xc9, 0x61, 0xe9, 0xc1, - 0x26, 0x87, 0xbd, 0xed, 0xcd, 0x76, 0xd9, 0xee, 0x41, 0x64, 0x09, 0x82, 0x20, 0xc8, 0x30, 0x4d, - 0x5e, 0x93, 0xa1, 0x33, 0x7d, 0x61, 0x26, 0xdb, 0x1f, 0xfe, 0x01, 0x9e, 0x45, 0x3c, 0x78, 0xf4, - 0x9f, 0x11, 0xf6, 0x24, 0x7b, 0x14, 0x0f, 0x41, 0xda, 0xdb, 0x1e, 0xfb, 0x17, 0x48, 0xa6, 0x5d, - 0xb7, 0x6a, 0x2f, 0xf5, 0x94, 0x97, 0xef, 0xfb, 0xde, 0xc7, 0x37, 0xef, 0xf1, 0xac, 0x3a, 0x8c, - 0x45, 0x98, 0x53, 0x49, 0x85, 0x0a, 0x72, 0x89, 0x05, 0xda, 0x8e, 0x02, 0xa6, 0xab, 0x18, 0x79, - 0xa0, 0x80, 0xc5, 0x19, 0x65, 0xa3, 0x00, 0xc6, 0xa2, 0xf1, 0x38, 0xc5, 0x14, 0x35, 0x15, 0x56, - 0xd5, 0x4a, 0xdf, 0xd0, 0x0e, 0x31, 0x8e, 0x06, 0x2c, 0x5d, 0x21, 0xfe, 0xb7, 0xfb, 0xd6, 0xfe, - 0x85, 0xb6, 0xb4, 0x3f, 0x99, 0xd6, 0x61, 0x2e, 0x19, 0x4a, 0x56, 0xcc, 0xc8, 0x08, 0xa5, 0xa0, - 0x9c, 0xbd, 0x03, 0xe9, 0xdc, 0x6b, 0x9a, 0xad, 0x83, 0x4e, 0x7c, 0x55, 0x7a, 0xc6, 0x8f, 0xd2, - 0x3b, 0x4a, 0x59, 0x91, 0x5d, 0xf6, 0x83, 0x18, 0x2b, 0x27, 0x25, 0x50, 0xad, 0x3f, 0x6d, 0x95, - 0x0c, 0xc3, 0x62, 0x96, 0x83, 0x0a, 0x4e, 0x21, 0xbe, 0x29, 0xbd, 0x6d, 0x66, 0xcb, 0xd2, 0x6b, - 0xcc, 0xa8, 0xe0, 0x27, 0xfe, 0x16, 0xd2, 0x8f, 0xec, 0x5b, 0xf4, 0xe5, 0x6f, 0xd0, 0x7e, 0x6f, - 0x5a, 0xf5, 0x3e, 0x55, 0x40, 0x06, 0x00, 0x24, 0x07, 0x49, 0x52, 0xaa, 0x9c, 0x3d, 0x9d, 0xe9, - 0xed, 0xce, 0x99, 0xfe, 0x71, 0x5a, 0x96, 0xde, 0x93, 0x55, 0xa0, 0xbf, 0x19, 0x3f, 0x7a, 0x54, - 0x41, 0x67, 0x00, 0x17, 0x20, 0x7b, 0x54, 0xd9, 0x1f, 0x4d, 0xeb, 0x50, 0xb0, 0x11, 0x13, 0x97, - 0xe2, 0x8f, 0x2c, 0xb5, 0xff, 0x9d, 0xcf, 0x16, 0xb3, 0xbb, 0xf9, 0x6c, 0x21, 0xfd, 0xa8, 0xbe, - 0x46, 0xef, 0x42, 0x7d, 0x35, 0xad, 0x67, 0x93, 0x8c, 0x15, 0xc0, 0x99, 0x2a, 0x20, 0x21, 0xf1, - 0x84, 0xc4, 0x98, 0x00, 0xc9, 0xa8, 0xca, 0x40, 0x91, 0x01, 0x4a, 0x92, 0x00, 0x87, 0x94, 0x16, - 0x40, 0x62, 0xca, 0xb9, 0xf3, 0xa0, 0xb9, 0xd7, 0x7a, 0xd8, 0x49, 0x6f, 0x4a, 0x6f, 0xa7, 0xbe, - 0x65, 0xe9, 0x1d, 0xaf, 0x82, 0xed, 0xd2, 0xe5, 0x47, 0x47, 0x1b, 0xf2, 0xee, 0xa4, 0x8b, 0x09, - 0x9c, 0x6b, 0xed, 0x19, 0xca, 0xd3, 0xb5, 0xb2, 0x4b, 0x39, 0xb7, 0x9f, 0x5b, 0x6e, 0x02, 0x9c, - 0x8d, 0x41, 0x92, 0x62, 0x4a, 0x32, 0xc4, 0x21, 0x99, 0x50, 0x25, 0xaa, 0x67, 0x13, 0xce, 0x04, - 0x2b, 0x9c, 0x83, 0xa6, 0xd9, 0xaa, 0x45, 0x4f, 0xd7, 0xaa, 0x57, 0xd3, 0x73, 0xc4, 0xe1, 0x6b, - 0xaa, 0x44, 0x8f, 0xaa, 0x17, 0x95, 0xe0, 0xa4, 0xf6, 0xf9, 0x8b, 0x67, 0x74, 0x7a, 0x57, 0x73, - 0xd7, 0xbc, 0x9e, 0xbb, 0xe6, 0xcf, 0xb9, 0x6b, 0x7e, 0x58, 0xb8, 0xc6, 0xf5, 0xc2, 0x35, 0xbe, - 0x2f, 0x5c, 0xe3, 0x4d, 0x7b, 0x63, 0x33, 0x0a, 0x58, 0xfb, 0xf6, 0x70, 0xf4, 0x8f, 0xbe, 0x9c, - 0x70, 0x1a, 0x56, 0x07, 0xa2, 0x97, 0xd4, 0xdf, 0xd7, 0xfc, 0xf1, 0xaf, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x12, 0x58, 0xeb, 0xa3, 0x76, 0x03, 0x00, 0x00, + // 609 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0x4f, 0x6b, 0x13, 0x4f, + 0x18, 0xc7, 0x33, 0xbf, 0x96, 0xf2, 0xeb, 0x5a, 0xa1, 0x6c, 0x15, 0xb7, 0x3d, 0xec, 0xd6, 0x15, + 0x4a, 0x0e, 0x26, 0x7b, 0xe8, 0x45, 0x7a, 0x6b, 0x1a, 0x9a, 0x1e, 0x44, 0xca, 0x62, 0x11, 0x04, + 0x19, 0x26, 0x3b, 0x4f, 0x37, 0x63, 0x66, 0x32, 0x61, 0x66, 0xd2, 0x24, 0xbe, 0x00, 0xc1, 0x83, + 0x20, 0xe2, 0xc1, 0xa3, 0x6f, 0x46, 0xe8, 0xb1, 0x47, 0x11, 0x5c, 0xa4, 0xc5, 0x4b, 0x8f, 0x79, + 0x05, 0x92, 0xc9, 0xf6, 0x8f, 0xed, 0x22, 0x89, 0xa7, 0x4c, 0x9e, 0xe7, 0x33, 0xcf, 0x7c, 0xbf, + 0xcf, 0x33, 0x3b, 0xce, 0x32, 0x1c, 0x89, 0xa8, 0x4b, 0x14, 0x11, 0xba, 0xda, 0x55, 0xd2, 0x48, + 0xd7, 0xd3, 0xc0, 0xec, 0x2a, 0x91, 0xbc, 0xaa, 0x81, 0x25, 0x2d, 0xc2, 0x3a, 0x55, 0x38, 0x12, + 0x6b, 0xf7, 0x52, 0x99, 0x4a, 0x9b, 0x8a, 0xc6, 0xab, 0x09, 0x1f, 0x9e, 0x2c, 0x3a, 0x0b, 0xfb, + 0xb6, 0x80, 0xfb, 0x09, 0x39, 0x2b, 0x5d, 0xc5, 0xa4, 0x62, 0x66, 0x88, 0x3b, 0x52, 0x09, 0xc2, + 0xd9, 0x1b, 0x50, 0xde, 0x7f, 0xeb, 0xa8, 0xbc, 0x58, 0x4b, 0x8e, 0xb3, 0xa0, 0xf4, 0x3d, 0x0b, + 0x36, 0x52, 0x66, 0x5a, 0xbd, 0x66, 0x35, 0x91, 0x22, 0x4a, 0xa4, 0x16, 0x52, 0xe7, 0x3f, 0x15, + 0x4d, 0xdb, 0x91, 0x19, 0x76, 0x41, 0x57, 0xeb, 0x90, 0x9c, 0x67, 0x41, 0x51, 0xb1, 0x51, 0x16, + 0xac, 0x0d, 0x89, 0xe0, 0x5b, 0x61, 0x41, 0x32, 0x8c, 0xdd, 0x8b, 0xe8, 0xb3, 0xcb, 0xa0, 0xfb, + 0x16, 0x39, 0xcb, 0x4d, 0xa2, 0x01, 0x1f, 0x02, 0xe0, 0x2e, 0x28, 0x9c, 0x12, 0xed, 0xcd, 0x59, + 0x4d, 0xaf, 0x66, 0xd6, 0x74, 0xab, 0xd2, 0x28, 0x0b, 0x1e, 0x4c, 0x04, 0xdd, 0xcc, 0x84, 0xf1, + 0xdd, 0x71, 0x68, 0x17, 0x60, 0x1f, 0x54, 0x83, 0x68, 0xf7, 0x23, 0x72, 0x56, 0x04, 0xeb, 0x30, + 0xd1, 0x13, 0x7f, 0x68, 0x99, 0xff, 0xd7, 0xfe, 0x14, 0x14, 0xbb, 0xea, 0x4f, 0x41, 0x32, 0x8c, + 0x97, 0xf3, 0xe8, 0x95, 0xa8, 0xaf, 0xc8, 0x79, 0xdc, 0x6f, 0x31, 0x03, 0x9c, 0x69, 0x03, 0x14, + 0x27, 0x7d, 0x9c, 0x48, 0x0a, 0xb8, 0x45, 0x74, 0x0b, 0x34, 0x3e, 0x94, 0x0a, 0x53, 0xe0, 0x90, + 0x12, 0x03, 0x38, 0x21, 0x9c, 0x7b, 0xff, 0xaf, 0xcf, 0x95, 0x97, 0x6a, 0xe9, 0x79, 0x16, 0xcc, + 0xb4, 0x6f, 0x94, 0x05, 0x9b, 0x13, 0x61, 0xb3, 0xec, 0x0a, 0xe3, 0x8d, 0x6b, 0xf8, 0x4e, 0x7f, + 0x47, 0x52, 0xd8, 0xb3, 0xec, 0xae, 0x54, 0xf5, 0x9c, 0xdc, 0x21, 0x9c, 0xbb, 0xdb, 0x8e, 0x4f, + 0x81, 0xb3, 0x23, 0x50, 0xd8, 0x0c, 0x70, 0x4b, 0xca, 0x36, 0xee, 0x13, 0x2d, 0xc6, 0xb6, 0x31, + 0x67, 0x82, 0x19, 0x6f, 0x71, 0x1d, 0x95, 0xe7, 0xe3, 0xd5, 0x9c, 0x7a, 0x3e, 0xd8, 0x93, 0xb2, + 0xfd, 0x82, 0x68, 0xd1, 0x20, 0xfa, 0xe9, 0x18, 0x70, 0x7f, 0x20, 0x67, 0x43, 0x90, 0x01, 0xa6, + 0xc3, 0x0e, 0x11, 0x2c, 0xc1, 0x97, 0x03, 0xed, 0x75, 0xfb, 0x44, 0x51, 0x4c, 0xe8, 0xeb, 0x9e, + 0x36, 0x02, 0x3a, 0xc6, 0x73, 0xec, 0xc8, 0xde, 0xa1, 0x99, 0x67, 0x36, 0xe5, 0x01, 0xa3, 0x2c, + 0xa8, 0xe4, 0x63, 0x9c, 0x8a, 0x0f, 0xe3, 0x87, 0x82, 0x0c, 0xea, 0x13, 0xae, 0x36, 0xb9, 0x75, + 0x07, 0x16, 0xda, 0xbe, 0x64, 0xdc, 0x5f, 0xc8, 0x29, 0x17, 0x96, 0xa3, 0xb2, 0xdf, 0xb9, 0xe9, + 0xf0, 0x8e, 0x75, 0xf8, 0x7e, 0x76, 0x87, 0x53, 0x1f, 0x31, 0xca, 0x82, 0xe8, 0x2f, 0x1e, 0x0b, + 0x76, 0x84, 0xf1, 0xa3, 0x5b, 0x2e, 0xeb, 0x39, 0x76, 0xcd, 0xe7, 0x13, 0x67, 0xd5, 0x10, 0x95, + 0x82, 0xb1, 0xc3, 0xef, 0x69, 0xa0, 0xf6, 0x03, 0x68, 0x72, 0x99, 0xb4, 0xbd, 0x25, 0x7b, 0x0b, + 0xee, 0x4f, 0x80, 0x06, 0xd1, 0x07, 0x1a, 0xe8, 0x3e, 0xa8, 0xda, 0x38, 0xb9, 0x35, 0xff, 0xf9, + 0x4b, 0x50, 0xaa, 0x35, 0x8e, 0x4f, 0x7d, 0x74, 0x72, 0xea, 0xa3, 0x9f, 0xa7, 0x3e, 0xfa, 0x70, + 0xe6, 0x97, 0x4e, 0xce, 0xfc, 0xd2, 0xb7, 0x33, 0xbf, 0xf4, 0xb2, 0x72, 0xad, 0x0b, 0x1a, 0x58, + 0xe5, 0xe2, 0xa1, 0xb4, 0x7f, 0xec, 0x4b, 0x19, 0x0d, 0xa2, 0xf1, 0x93, 0x6a, 0x1b, 0xd2, 0x5c, + 0xb0, 0xf9, 0xcd, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x48, 0xda, 0x43, 0x66, 0x05, 0x00, + 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -154,6 +173,31 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.TargetGasUsedPerBlock != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.TargetGasUsedPerBlock)) + i-- + dAtA[i] = 0x60 + } + { + size := m.MaxDynamicBaseFeeDownwardAdjustment.Size() + i -= size + if _, err := m.MaxDynamicBaseFeeDownwardAdjustment.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + { + size := m.MaxDynamicBaseFeeUpwardAdjustment.Size() + i -= size + if _, err := m.MaxDynamicBaseFeeUpwardAdjustment.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 if m.DeliverTxHookWasmGasLimit != 0 { i = encodeVarintParams(dAtA, i, uint64(m.DeliverTxHookWasmGasLimit)) i-- @@ -233,6 +277,13 @@ func (m *Params) Size() (n int) { if m.DeliverTxHookWasmGasLimit != 0 { n += 1 + sovParams(uint64(m.DeliverTxHookWasmGasLimit)) } + l = m.MaxDynamicBaseFeeUpwardAdjustment.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.MaxDynamicBaseFeeDownwardAdjustment.Size() + n += 1 + l + sovParams(uint64(l)) + if m.TargetGasUsedPerBlock != 0 { + n += 1 + sovParams(uint64(m.TargetGasUsedPerBlock)) + } return n } @@ -424,6 +475,93 @@ func (m *Params) Unmarshal(dAtA []byte) error { break } } + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxDynamicBaseFeeUpwardAdjustment", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxDynamicBaseFeeUpwardAdjustment.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxDynamicBaseFeeDownwardAdjustment", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxDynamicBaseFeeDownwardAdjustment.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TargetGasUsedPerBlock", wireType) + } + m.TargetGasUsedPerBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TargetGasUsedPerBlock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/evm/types/params_test.go b/x/evm/types/params_test.go index 40b7dc911..f07fa5f3c 100644 --- a/x/evm/types/params_test.go +++ b/x/evm/types/params_test.go @@ -16,8 +16,10 @@ func TestDefaultParams(t *testing.T) { MinimumFeePerGas: types.DefaultMinFeePerGas, DeliverTxHookWasmGasLimit: types.DefaultDeliverTxHookWasmGasLimit, WhitelistedCwCodeHashesForDelegateCall: types.DefaultWhitelistedCwCodeHashesForDelegateCall, + MaxDynamicBaseFeeUpwardAdjustment: types.DefaultMaxDynamicBaseFeeUpwardAdjustment, + MaxDynamicBaseFeeDownwardAdjustment: types.DefaultMaxDynamicBaseFeeDownwardAdjustment, + TargetGasUsedPerBlock: types.DefaultTargetGasUsedPerBlock, }, types.DefaultParams()) - require.Nil(t, types.DefaultParams().Validate()) } @@ -48,6 +50,34 @@ func TestBaseFeeMinimumFee(t *testing.T) { require.Contains(t, err.Error(), "minimum fee cannot be lower than base fee") } +func TestValidateParamsInvalidMaxDynamicBaseFeeUpwardAdjustment(t *testing.T) { + params := types.DefaultParams() + params.MaxDynamicBaseFeeUpwardAdjustment = sdk.NewDec(-1) // Set to invalid negative value + + err := params.Validate() + require.Error(t, err) + require.Contains(t, err.Error(), "negative base fee adjustment") + + params.MaxDynamicBaseFeeUpwardAdjustment = sdk.NewDec(2) + err = params.Validate() + require.Error(t, err) + require.Contains(t, err.Error(), "base fee adjustment must be less than or equal to 1") +} + +func TestValidateParamsInvalidMaxDynamicBaseFeeDownwardAdjustment(t *testing.T) { + params := types.DefaultParams() + params.MaxDynamicBaseFeeDownwardAdjustment = sdk.NewDec(-1) // Set to invalid negative value + + err := params.Validate() + require.Error(t, err) + require.Contains(t, err.Error(), "negative base fee adjustment") + + params.MaxDynamicBaseFeeDownwardAdjustment = sdk.NewDec(2) + err = params.Validate() + require.Error(t, err) + require.Contains(t, err.Error(), "base fee adjustment must be less than or equal to 1") +} + func TestValidateParamsInvalidDeliverTxHookWasmGasLimit(t *testing.T) { params := types.DefaultParams() params.DeliverTxHookWasmGasLimit = 0 // Set to invalid value (0) diff --git a/x/mint/types/codec.go b/x/mint/types/codec.go index 0f1b15969..3018320c1 100644 --- a/x/mint/types/codec.go +++ b/x/mint/types/codec.go @@ -7,9 +7,13 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ) -var amino = codec.NewLegacyAmino() +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) func init() { + RegisterCodec(amino) cryptocodec.RegisterCrypto(amino) amino.Seal() } @@ -23,5 +27,3 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &UpdateMinterProposal{}, ) } - -var ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) diff --git a/x/oracle/keeper/test_utils.go b/x/oracle/keeper/test_utils.go index b8b49ec53..2e2fe60a7 100644 --- a/x/oracle/keeper/test_utils.go +++ b/x/oracle/keeper/test_utils.go @@ -70,7 +70,7 @@ func MakeEncodingConfig(_ *testing.T) simparams.EncodingConfig { ModuleBasics.RegisterLegacyAminoCodec(amino) ModuleBasics.RegisterInterfaces(interfaceRegistry) - types.RegisterLegacyAminoCodec(amino) + types.RegisterCodec(amino) types.RegisterInterfaces(interfaceRegistry) return simparams.EncodingConfig{ InterfaceRegistry: interfaceRegistry, diff --git a/x/oracle/module.go b/x/oracle/module.go index 02c6f9cc0..76f129638 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -44,7 +44,7 @@ func (AppModuleBasic) Name() string { // RegisterLegacyAminoCodec registers the module's types on the given LegacyAmino codec. func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { - types.RegisterLegacyAminoCodec(cdc) + types.RegisterCodec(cdc) } // RegisterInterfaces registers the module's interface types diff --git a/x/oracle/types/codec.go b/x/oracle/types/codec.go index f0feaf2b0..d84dcaaed 100755 --- a/x/oracle/types/codec.go +++ b/x/oracle/types/codec.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" ) -func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { +func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgAggregateExchangeRateVote{}, "oracle/MsgAggregateExchangeRateVote", nil) cdc.RegisterConcrete(&MsgDelegateFeedConsent{}, "oracle/MsgDelegateFeedConsent", nil) } @@ -24,6 +24,12 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { } var ( - Amino = codec.NewLegacyAmino() - ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) ) + +func init() { + RegisterCodec(amino) + sdk.RegisterLegacyAminoCodec(amino) + amino.Seal() +} diff --git a/x/tokenfactory/keeper/migrations_test.go b/x/tokenfactory/keeper/migrations_test.go index 41b9d5564..e0db6d88b 100644 --- a/x/tokenfactory/keeper/migrations_test.go +++ b/x/tokenfactory/keeper/migrations_test.go @@ -36,7 +36,7 @@ func TestMigrate2to3(t *testing.T) { cdc := codec.NewProtoCodec(registry) paramsSubspace := typesparams.NewSubspace(cdc, - types.Amino, + codec.NewLegacyAmino(), storeKey, memStoreKey, "TokenfactoryParams", diff --git a/x/tokenfactory/types/codec.go b/x/tokenfactory/types/codec.go index c182eea77..0525131e3 100644 --- a/x/tokenfactory/types/codec.go +++ b/x/tokenfactory/types/codec.go @@ -10,16 +10,21 @@ import ( ) func RegisterCodec(cdc *codec.LegacyAmino) { - cdc.RegisterConcrete(&MsgCreateDenom{}, "tokenfactory/create-denom", nil) - cdc.RegisterConcrete(&MsgMint{}, "tokenfactory/mint", nil) - cdc.RegisterConcrete(&MsgBurn{}, "tokenfactory/burn", nil) - cdc.RegisterConcrete(&MsgChangeAdmin{}, "tokenfactory/change-admin", nil) + cdc.RegisterConcrete(&MsgCreateDenom{}, "tokenfactory/MsgCreateDenom", nil) + cdc.RegisterConcrete(&MsgUpdateDenom{}, "tokenfactory/MsgUpdateDenom", nil) + cdc.RegisterConcrete(&MsgMint{}, "tokenfactory/MsgMint", nil) + cdc.RegisterConcrete(&MsgBurn{}, "tokenfactory/MsgBurn", nil) + cdc.RegisterConcrete(&MsgChangeAdmin{}, "tokenfactory/MsgChangeAdmin", nil) + cdc.RegisterConcrete(&MsgSetDenomMetadata{}, "tokenfactory/MsgSetDenomMetadata", nil) } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgCreateDenom{}, ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgUpdateDenom{}, + ) registry.RegisterImplementations((*sdk.Msg)(nil), &MsgMint{}, ) @@ -29,11 +34,21 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgChangeAdmin{}, ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgSetDenomMetadata{}, + ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } var ( - Amino = codec.NewLegacyAmino() - ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) ) + +func init() { + RegisterCodec(amino) + sdk.RegisterLegacyAminoCodec(amino) + + amino.Seal() +} From 98ab03c27c5c10d334fec3f307727bcfd18227cc Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Mon, 28 Oct 2024 21:17:10 +0100 Subject: [PATCH 20/28] Remove dex --- tools/migration/sc/migrator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/migration/sc/migrator.go b/tools/migration/sc/migrator.go index 6ee951f11..debb1ffb7 100644 --- a/tools/migration/sc/migrator.go +++ b/tools/migration/sc/migrator.go @@ -56,7 +56,7 @@ var Keys = sdk.NewKVStoreKeys( minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, oracletypes.StoreKey, - evmtypes.StoreKey, wasm.StoreKey, epochmoduletypes.StoreKey, tokenfactorytypes.StoreKey, "dex", + evmtypes.StoreKey, wasm.StoreKey, epochmoduletypes.StoreKey, tokenfactorytypes.StoreKey, ) func NewMigrator(homeDir string, db dbm.DB) *Migrator { From 95137f71e8e0f4cb8b9e5d24a758070e37c35990 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Tue, 29 Oct 2024 08:46:36 -0400 Subject: [PATCH 21/28] Add Faq section --- docs/migration/seidb_archive_migration.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index 16fd1bef3..a4887d39a 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -90,7 +90,7 @@ ss-import-num-workers = 1 ```bash systemctl stop seid -seid tools migrate-iavl --target-db SC --home-dir /root/.sei +seid tools migrate-iavl --home-dir /root/.sei ``` This may take a couple hours to run. You will see logs of form @@ -98,7 +98,7 @@ This may take a couple hours to run. You will see logs of form ### Step 3: Note down MIGRATION_HEIGHT -Note down the latest height as outputted from the sc migration. +Note down the latest height as outputted from the sc migration log. Save it as an env var $MIGRATION_HEIGHT. ```bash MIGRATION_HEIGHT=<> @@ -175,3 +175,14 @@ Both of these metrics have a `module` label which indicates what module is curre ## FAQ + +### Can the state store migration be stopped and restarted? + +The state store migration can be stopped and restarted at any time. The migration +process saves the latest `module` and `key` written to State Store (pebbledb) and will +automatically resume the migration from that latest key once restarted. + +All one needs to do is restart seid with the migration command as in step 4 +```bash +seid start --migrate-iavl --migrate-height $MIGRATION_HEIGHT --chain-id pacific-1 +``` From de06161dc62781a7b37678833675458021be0a88 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Tue, 29 Oct 2024 11:05:59 -0400 Subject: [PATCH 22/28] Add requirements section --- docs/migration/seidb_archive_migration.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index a4887d39a..257859eb7 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -17,7 +17,13 @@ The overall process will work as follows: 6. Restart seid normally and verify node runs properly 7. Clear out iavl and restart seid normally, now only using SeiDB fully -You may need to ensure you have sufficient disk space available, as during the migration process, both IAVL and SeiDB state stores will need to be maintained simultaneously. This could potentially double your storage requirements temporarily. + +## Requirements + +### Additional Disk Space + +Ensure you have at least 10TB of free disk space available for the migration process. This extra space is needed because during migration, both IAVL and SeiDB state stores will exist simultaneously. Note +that this is ONLY during the migration process, and will not be necessary after completion ## Migration Steps From 95b6762cdeea238e7fdfabf3683d33d037450c8a Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Tue, 29 Oct 2024 11:18:12 -0400 Subject: [PATCH 23/28] Systemd instructions --- docs/migration/seidb_archive_migration.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index 257859eb7..8e266c564 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -112,6 +112,8 @@ MIGRATION_HEIGHT=<> ### Step 4: Restart seid with background SS migration + +If you are using systemd, make sure to update your service configuration to use this command: ```bash seid start --migrate-iavl --migrate-height $MIGRATION_HEIGHT --chain-id pacific-1 ``` @@ -123,10 +125,9 @@ You will see logs of form `SeiDB Archive Migration: Iterating through %s module...` and `SeiDB Archive Migration: Last 1,000,000 iterations took:...` - NOTE: While this is running, any historical queries will be routed to iavl if they are for a height BEFORE the migrate-height. Any queries on heights -AFTER the migrate-height will be routed to state store (pebbbledb). +AFTER the migrate-height will be routed to state store (pebbledb). ### Step 5: Verify State Store Migration after completion @@ -149,6 +150,7 @@ This will output `Verification Succeeded` if the verification was successful. Once the verification has completed, we can restart seid normally and verify that the node operates. +If you are using systemd, make sure to update your service configuration to use this command: ```bash seid start --chain-id pacific-1 ``` From 240ccb1910afd695a1527b79358122228bdbb989 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Tue, 29 Oct 2024 11:19:01 -0400 Subject: [PATCH 24/28] Minor add to readme --- docs/migration/seidb_archive_migration.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index 8e266c564..f06dd19b9 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -113,7 +113,8 @@ MIGRATION_HEIGHT=<> ### Step 4: Restart seid with background SS migration -If you are using systemd, make sure to update your service configuration to use this command: +If you are using systemd, make sure to update your service configuration to use this command. +Always be sure to run with these flags until migration is complete. ```bash seid start --migrate-iavl --migrate-height $MIGRATION_HEIGHT --chain-id pacific-1 ``` From 3fea70e84806b96fe03a62f3fc9e14ea7cd05d00 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Tue, 29 Oct 2024 11:28:17 -0400 Subject: [PATCH 25/28] Add more examples for migration height --- docs/migration/seidb_archive_migration.md | 12 +++++++++++- tools/migration/ss/migrator.go | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index f06dd19b9..7c41e4284 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -105,7 +105,17 @@ This may take a couple hours to run. You will see logs of form ### Step 3: Note down MIGRATION_HEIGHT Note down the latest height as outputted from the sc migration log. -Save it as an env var $MIGRATION_HEIGHT. + +As an example the sc migration log would show: +``` +latest version: 111417590 +D[2024-10-29|15:26:03.657] Finished loading IAVL tree +D[2024-10-29|15:26:03.657] Finished loading IAVL tree +D[2024-10-29|15:26:03.657] Finished loading IAVL tree +``` + +Save that `latest version` (in example 111417590) as an env var $MIGRATION_HEIGHT. + ```bash MIGRATION_HEIGHT=<> ``` diff --git a/tools/migration/ss/migrator.go b/tools/migration/ss/migrator.go index 1b4fe5b4d..3f86b406e 100644 --- a/tools/migration/ss/migrator.go +++ b/tools/migration/ss/migrator.go @@ -95,7 +95,7 @@ func (m *Migrator) Verify(version int64) error { verifyErr = fmt.Errorf("verification error: value doesn't match for key %s", string(key)) } count++ - if count%10000 == 0 { + if count%1000000 == 0 { fmt.Printf("SeiDB Archive Migration:: Verified %d keys in for module %s\n", count, module) } return false From 2e3376af3449b46038d82422522ebe1670ed01fb Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Tue, 29 Oct 2024 14:46:28 -0400 Subject: [PATCH 26/28] Bump sei cosmos --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d1d55a32f..719d2ae89 100644 --- a/go.mod +++ b/go.mod @@ -346,7 +346,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.2.4 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.39-0.20241028105359-4193e4f26917 + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.41 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.2.0 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.2 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-23 diff --git a/go.sum b/go.sum index c9c096b68..b3b017463 100644 --- a/go.sum +++ b/go.sum @@ -1347,8 +1347,8 @@ github.com/sei-protocol/go-ethereum v1.13.5-sei-23 h1:rkgeOHC56QTco4mIyGd6cZHtlo github.com/sei-protocol/go-ethereum v1.13.5-sei-23/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.39-0.20241028105359-4193e4f26917 h1:h4QV0suNrGyK7u8fn3xpI+/864DVN8f9Qat2J2KAjvA= -github.com/sei-protocol/sei-cosmos v0.3.39-0.20241028105359-4193e4f26917/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= +github.com/sei-protocol/sei-cosmos v0.3.41 h1:w5ekTGC5J/7kxJhRkfdHk2KWOqi1zhic0gOXNm6W5vI= +github.com/sei-protocol/sei-cosmos v0.3.41/go.mod h1:ZwWxF/69WlcLEn4BzVjPPToTFkE2sjPanU8PNNyKoOk= github.com/sei-protocol/sei-db v0.0.45-0.20241009171123-c9b6c253819b h1:q25KpfxNwTrS8UZgkjdTvQkNI1Wo84KkavDpPA3aHwI= github.com/sei-protocol/sei-db v0.0.45-0.20241009171123-c9b6c253819b/go.mod h1:F/ZKZA8HJPcUzSZPA8yt6pfwlGriJ4RDR4eHKSGLStI= github.com/sei-protocol/sei-iavl v0.2.0 h1:OisPjXiDT+oe+aeckzDEFgkZCYuUjHgs/PP8DPicN+I= From e2714b56739bd4ce753e3be7a54f017d2a0b1f65 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 30 Oct 2024 09:08:46 -0400 Subject: [PATCH 27/28] Update error log --- tools/migration/ss/migrator.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/migration/ss/migrator.go b/tools/migration/ss/migrator.go index 3f86b406e..e050d27ec 100644 --- a/tools/migration/ss/migrator.go +++ b/tools/migration/ss/migrator.go @@ -92,11 +92,11 @@ func (m *Migrator) Verify(version int64) error { return true } if !bytes.Equal(val, value) { - verifyErr = fmt.Errorf("verification error: value doesn't match for key %s", string(key)) + verifyErr = fmt.Errorf("verification error: value doesn't match for key %s. Expected %s, got %s", string(key), string(value), string(val)) } count++ if count%1000000 == 0 { - fmt.Printf("SeiDB Archive Migration:: Verified %d keys in for module %s\n", count, module) + fmt.Printf("SeiDB Archive Migration: Verified %d keys in for module %s\n", count, module) } return false }) From 9a538af46428d6c739a6413af43d4c31a0f568a4 Mon Sep 17 00:00:00 2001 From: kbhat1 Date: Wed, 30 Oct 2024 12:51:03 -0400 Subject: [PATCH 28/28] Update command sc migration background --- docs/migration/seidb_archive_migration.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/migration/seidb_archive_migration.md b/docs/migration/seidb_archive_migration.md index 7c41e4284..9d2747951 100644 --- a/docs/migration/seidb_archive_migration.md +++ b/docs/migration/seidb_archive_migration.md @@ -99,6 +99,11 @@ systemctl stop seid seid tools migrate-iavl --home-dir /root/.sei ``` +You can also run this sc migration in the background: +```bash +seid tools migrate-iavl --home-dir /root/.sei > migrate-sc.log 2>&1 & +``` + This may take a couple hours to run. You will see logs of form `Start restoring SC store for height`