From f0d4401c51a41d6f9921147c923900dfaffb7b67 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Thu, 8 May 2025 11:30:46 +0530 Subject: [PATCH] eth, internal/cli: allow bor to run in snap sync (#1532) This PR enables snap sync download mechanism. It allows users to use it as sync mode via setting the flag `syncmode` to `snap`. Snap sync instead of executing every block, downloads the state and chain from the p2p network trusting the peer(s) it's downloading from. --- docs/cli/example_config.toml | 2 +- docs/cli/server.md | 2 +- eth/handler.go | 21 ++++++--------- eth/sync.go | 50 +++++++++++++++-------------------- internal/cli/server/config.go | 5 +--- internal/cli/server/flags.go | 2 +- 6 files changed, 33 insertions(+), 49 deletions(-) diff --git a/docs/cli/example_config.toml b/docs/cli/example_config.toml index 0485ac36a6..ec62ab3b4a 100644 --- a/docs/cli/example_config.toml +++ b/docs/cli/example_config.toml @@ -13,7 +13,7 @@ ancient = "" # Data directory for ancient chain segments (def keystore = "" # Path of the directory where keystores are located "rpc.batchlimit" = 100 # Maximum number of messages in a batch (default=100, use 0 for no limits) "rpc.returndatalimit" = 100000 # Maximum size (in bytes) a result of an rpc request could have (default=100000, use 0 for no limits) -syncmode = "full" # Blockchain sync mode (only "full" sync supported) +syncmode = "full" # Blockchain sync mode ("full" or "snap") gcmode = "full" # Blockchain garbage collection mode ("full", "archive") snapshot = true # Enables the snapshot-database mode "bor.logs" = false # Enables bor log retrieval diff --git a/docs/cli/server.md b/docs/cli/server.md index de54441bfb..2c26e409a2 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -90,7 +90,7 @@ The ```bor server``` command runs the Bor client. - ```state.scheme```: Scheme to use for storing ethereum state ('hash' or 'path') (default: path) -- ```syncmode```: Blockchain sync mode (only "full" sync supported) (default: full) +- ```syncmode```: Blockchain sync mode ("full" or "snap") (default: full) - ```verbosity```: Logging verbosity for the server (5=trace|4=debug|3=info|2=warn|1=error|0=crit) (default: 3) diff --git a/eth/handler.go b/eth/handler.go index e91d2f03ac..e24bd3bf93 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -175,19 +175,14 @@ func newHandler(config *handlerConfig) (*handler, error) { // * the last snap sync is not finished while user specifies a full sync this // time. But we don't have any recent state for full sync. // In these cases however it's safe to reenable snap sync. - - // TODO - uncomment when we (Polygon-PoS, bor) have snap sync/pbss - // fullBlock, snapBlock := h.chain.CurrentBlock(), h.chain.CurrentSnapBlock() - - // TODO - uncomment when we (Polygon-PoS, bor) have snap sync/pbss - // For more info - https://github.com/ethereum/go-ethereum/pull/28171 - // if fullBlock.Number.Uint64() == 0 && snapBlock.Number.Uint64() > 0 { - // h.snapSync.Store(true) - // log.Warn("Switch sync mode from full sync to snap sync", "reason", "snap sync incomplete") - // } else if !h.chain.HasState(fullBlock.Root) { - // h.snapSync.Store(true) - // log.Warn("Switch sync mode from full sync to snap sync", "reason", "head state missing") - // } + fullBlock, snapBlock := h.chain.CurrentBlock(), h.chain.CurrentSnapBlock() + if fullBlock.Number.Uint64() == 0 && snapBlock.Number.Uint64() > 0 { + h.snapSync.Store(true) + log.Warn("Switch sync mode from full sync to snap sync", "reason", "snap sync incomplete") + } else if !h.chain.HasState(fullBlock.Root) { + h.snapSync.Store(true) + log.Warn("Switch sync mode from full sync to snap sync", "reason", "head state missing") + } } else { head := h.chain.CurrentBlock() if head.Number.Uint64() > 0 && h.chain.HasState(head.Root) { diff --git a/eth/sync.go b/eth/sync.go index 6475b80f9f..8599ee55a0 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -201,43 +201,35 @@ func peerToSyncOp(mode downloader.SyncMode, p *eth.Peer) *chainSyncOp { } func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) { - // TODO - uncomment when we (Polygon-PoS, bor) have snap sync/pbss - /* - // If we're in snap sync mode, return that directly - if cs.handler.snapSync.Load() { - block := cs.handler.chain.CurrentSnapBlock() - td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) - return downloader.SnapSync, td - } - */ + // If we're in snap sync mode, return that directly + if cs.handler.snapSync.Load() { + block := cs.handler.chain.CurrentSnapBlock() + td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) + return downloader.SnapSync, td + } // We are probably in full sync, but we might have rewound to before the // snap sync pivot, check if we should re-enable snap sync. head := cs.handler.chain.CurrentBlock() - // TODO - uncomment when we (Polygon-PoS, bor) have snap sync/pbss - /* - if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil { - if head.Number.Uint64() < *pivot { - block := cs.handler.chain.CurrentSnapBlock() - td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) - return downloader.SnapSync, td - } - } - */ - - // TODO - uncomment when we (Polygon-PoS, bor) have snap sync/pbss - // For more info - https://github.com/ethereum/go-ethereum/pull/28171 - /* - // We are in a full sync, but the associated head state is missing. To complete - // the head state, forcefully rerun the snap sync. Note it doesn't mean the - // persistent state is corrupted, just mismatch with the head block. - if !cs.handler.chain.HasState(head.Root) { + if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil { + if head.Number.Uint64() < *pivot { block := cs.handler.chain.CurrentSnapBlock() td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) - log.Info("Reenabled snap sync as chain is stateless") return downloader.SnapSync, td } - */ + } + + // For more info - https://github.com/ethereum/go-ethereum/pull/28171 + // We are in a full sync, but the associated head state is missing. To complete + // the head state, forcefully rerun the snap sync. Note it doesn't mean the + // persistent state is corrupted, just mismatch with the head block. + if !cs.handler.chain.HasState(head.Root) { + block := cs.handler.chain.CurrentSnapBlock() + td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) + log.Info("Reenabled snap sync as chain is stateless") + return downloader.SnapSync, td + } + // Nope, we're really full syncing td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64()) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index f6326254f8..ddbf2d04b4 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -1161,10 +1161,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* case "full": n.SyncMode = downloader.FullSync case "snap": - // n.SyncMode = downloader.SnapSync // TODO(snap): Uncomment when we have snap sync working - n.SyncMode = downloader.FullSync - - log.Warn("Bor doesn't support Snap Sync yet, switching to Full Sync mode") + n.SyncMode = downloader.SnapSync default: return nil, fmt.Errorf("sync mode '%s' not found", c.SyncMode) } diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index 5110c22cba..533d2b6c7b 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -88,7 +88,7 @@ func (c *Command) Flags(config *Config) *flagset.Flagset { }) f.StringFlag(&flagset.StringFlag{ Name: "syncmode", - Usage: `Blockchain sync mode (only "full" sync supported)`, + Usage: `Blockchain sync mode ("full" or "snap")`, Value: &c.cliConfig.SyncMode, Default: c.cliConfig.SyncMode, })