From 49292346b34efa5f2ea2c09a316327aa2e993acf Mon Sep 17 00:00:00 2001
From: Enrique Jose  Avila Asapche <eavilaasapche@gmail.com>
Date: Fri, 3 Jun 2022 09:38:10 +0100
Subject: [PATCH] Auto correcting sync mode instead of giving an error (#4337)

---
 cmd/integration/commands/stages.go | 14 ++++-
 eth/backend.go                     | 88 +++++++++++++++++++-----------
 turbo/snapshotsync/snap/flags.go   | 13 ++---
 3 files changed, 73 insertions(+), 42 deletions(-)

diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go
index e7f2163cf6..93d3222a2a 100644
--- a/cmd/integration/commands/stages.go
+++ b/cmd/integration/commands/stages.go
@@ -1106,7 +1106,19 @@ func allSnapshots(cc *params.ChainConfig, db kv.RwDB) *snapshotsync.RoSnapshots
 	openSnapshotOnce.Do(func() {
 		syncmode := ethconfig.SyncModeByChainName(cc.ChainName, syncmodeStr)
 		snapCfg := ethconfig.NewSnapCfg(syncmode == ethconfig.SnapSync, true, true)
-		if err := db.Update(context.Background(), func(tx kv.RwTx) error { return snap.EnsureNotChanged(tx, snapCfg) }); err != nil {
+		if err := db.Update(context.Background(), func(tx kv.RwTx) error {
+			// if we dont have the correct syncmode here return an error
+			changed, snapSync, err := snap.EnsureNotChanged(tx, snapCfg)
+			if err != nil {
+				return err
+			}
+
+			if !changed {
+				return fmt.Errorf("syncmode has changed. Run erigon again with %v", snapSync)
+			}
+
+			return nil
+		}); err != nil {
 			panic(err)
 		}
 		_allSnapshotsSingleton = snapshotsync.NewRoSnapshots(snapCfg, filepath.Join(datadir, "snapshots"))
diff --git a/eth/backend.go b/eth/backend.go
index e080163612..4700b75597 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -181,7 +181,6 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
 	}
 
 	config.Sync.Mode = ethconfig.SyncModeByChainName(chainConfig.ChainName, config.Sync.ModeCli)
-	log.Info("Syncmode", "type", config.Sync.Mode)
 	config.Snapshot.Enabled = config.Sync.Mode == ethconfig.SnapSync
 
 	types.SetHeaderSealFlag(chainConfig.IsHeaderWithSeal())
@@ -269,37 +268,9 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
 		}()
 	}
 
-	var blockReader services.FullBlockReader
-	var allSnapshots *snapshotsync.RoSnapshots
-	if config.Snapshot.Enabled {
-		allSnapshots = snapshotsync.NewRoSnapshots(config.Snapshot, config.SnapDir)
-		if err = allSnapshots.Reopen(); err != nil {
-			return nil, fmt.Errorf("[Snapshots] Reopen: %w", err)
-		}
-		blockReader = snapshotsync.NewBlockReaderWithSnapshots(allSnapshots)
-
-		if len(stack.Config().DownloaderAddr) > 0 {
-			// connect to external Downloader
-			backend.downloaderClient, err = downloadergrpc.NewClient(ctx, stack.Config().DownloaderAddr)
-		} else {
-			// start embedded Downloader
-			backend.downloader, err = downloader.New(config.Torrent)
-			if err != nil {
-				return nil, err
-			}
-			go downloader.MainLoop(ctx, backend.downloader, true)
-			bittorrentServer, err := downloader.NewGrpcServer(backend.downloader)
-			if err != nil {
-				return nil, fmt.Errorf("new server: %w", err)
-			}
-
-			backend.downloaderClient = direct.NewDownloaderClient(bittorrentServer)
-		}
-		if err != nil {
-			return nil, err
-		}
-	} else {
-		blockReader = snapshotsync.NewBlockReader()
+	blockReader, allSnapshots, err := backend.setUpBlockReader(ctx, config.Snapshot.Enabled, config, stack)
+	if err != nil {
+		return nil, err
 	}
 
 	var consensusConfig interface{}
@@ -320,6 +291,7 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
 	backend.engine = ethconsensusconfig.CreateConsensusEngine(chainConfig, logger, consensusConfig, config.Miner.Notify, config.Miner.Noverify, config.HeimdallURL, config.WithoutHeimdall, stack.DataDir(), allSnapshots)
 
 	log.Info("Initialising Ethereum protocol", "network", config.NetworkID)
+	log.Info("Syncmode", "type", config.Sync.Mode)
 
 	if err := chainKv.Update(context.Background(), func(tx kv.RwTx) error {
 		if err = stagedsync.UpdateMetrics(tx); err != nil {
@@ -330,9 +302,20 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
 		if err != nil {
 			return err
 		}
-		if err := snap.EnsureNotChanged(tx, config.Snapshot); err != nil {
+		isCorrectSync, syncMode, err := snap.EnsureNotChanged(tx, config.Snapshot)
+		if err != nil {
 			return err
 		}
+		// if we are in the incorrect syncmode then we change it to the appropriate one
+		if !isCorrectSync {
+			log.Warn("Incorrect Syncmode", "got", config.Sync.Mode, "change_to", syncMode)
+			config.Sync.Mode = syncMode
+			config.Snapshot.Enabled = config.Sync.Mode == ethconfig.SnapSync
+			blockReader, allSnapshots, err = backend.setUpBlockReader(ctx, config.Snapshot.Enabled, config, stack)
+			if err != nil {
+				return err
+			}
+		}
 		log.Info("Effective", "prune_flags", config.Prune.String(), "snapshot_flags", config.Snapshot.String())
 
 		return nil
@@ -764,6 +747,45 @@ func (s *Ethereum) NodesInfo(limit int) (*remote.NodesInfoReply, error) {
 	return nodesInfo, nil
 }
 
+// sets up blockReader and client downloader
+func (s *Ethereum) setUpBlockReader(ctx context.Context, isSnapshotEnabled bool, config *ethconfig.Config, stack *node.Node) (services.FullBlockReader, *snapshotsync.RoSnapshots, error) {
+	var err error
+
+	if isSnapshotEnabled {
+		allSnapshots := snapshotsync.NewRoSnapshots(config.Snapshot, config.SnapDir)
+		if err = allSnapshots.Reopen(); err != nil {
+			return nil, nil, fmt.Errorf("[Snapshots] Reopen: %w", err)
+		}
+		blockReader := snapshotsync.NewBlockReaderWithSnapshots(allSnapshots)
+
+		if len(stack.Config().DownloaderAddr) > 0 {
+			// connect to external Downloader
+			s.downloaderClient, err = downloadergrpc.NewClient(ctx, stack.Config().DownloaderAddr)
+		} else {
+			// start embedded Downloader
+			s.downloader, err = downloader.New(config.Torrent)
+			if err != nil {
+				return nil, nil, err
+			}
+			go downloader.MainLoop(ctx, s.downloader, true)
+			bittorrentServer, err := downloader.NewGrpcServer(s.downloader)
+			if err != nil {
+				return nil, nil, fmt.Errorf("new server: %w", err)
+			}
+
+			s.downloaderClient = direct.NewDownloaderClient(bittorrentServer)
+		}
+		if err != nil {
+			return nil, nil, err
+		}
+		return blockReader, allSnapshots, nil
+	} else {
+		blockReader := snapshotsync.NewBlockReader()
+		return blockReader, nil, nil
+	}
+
+}
+
 func (s *Ethereum) Peers(ctx context.Context) (*remote.PeersReply, error) {
 	var reply remote.PeersReply
 	for _, sentryClient := range s.sentriesClient.Sentries() {
diff --git a/turbo/snapshotsync/snap/flags.go b/turbo/snapshotsync/snap/flags.go
index f05eb8175a..7c88e19aa6 100644
--- a/turbo/snapshotsync/snap/flags.go
+++ b/turbo/snapshotsync/snap/flags.go
@@ -1,8 +1,6 @@
 package snap
 
 import (
-	"fmt"
-
 	"github.com/ledgerwatch/erigon-lib/kv"
 	"github.com/ledgerwatch/erigon/eth/ethconfig"
 )
@@ -15,20 +13,19 @@ func Enabled(tx kv.Getter) (bool, error) {
 	return kv.GetBool(tx, kv.DatabaseInfo, blockSnapshotEnabledKey)
 }
 
-// makes sure that erigon is on the same syncmode used previously
-func EnsureNotChanged(tx kv.GetPut, cfg ethconfig.Snapshot) error {
+func EnsureNotChanged(tx kv.GetPut, cfg ethconfig.Snapshot) (bool, ethconfig.SyncMode, error) {
 	ok, v, err := kv.EnsureNotChangedBool(tx, kv.DatabaseInfo, blockSnapshotEnabledKey, cfg.Enabled)
 	if err != nil {
-		return err
+		return false, "", err
 	}
 	if !ok {
 		if v {
-			return fmt.Errorf("we recently changed default of --syncmode flag, or you forgot to set --syncmode flag, please add flag --syncmode=snap")
+			return false, ethconfig.SnapSync, nil
 		} else {
-			return fmt.Errorf("we recently changed default of --syncmode flag, or you forgot to set --syncmode flag, please add flag --syncmode=full")
+			return false, ethconfig.FullSync, nil
 		}
 	}
-	return nil
+	return true, "", nil
 }
 
 // ForceSetFlags - if you know what you are doing
-- 
GitLab