Skip to content

startPoWFeatures

Source (upstream pre-purge) Current
File cmd/geth/main.go main_pow.go
Symbol startNode startPoWFeatures
Ref d8e0807da~1 etc/v1.17.3-full-node

Standalone mining startup and --exitwhensynced handler that upstream removed in PR #28623 (commit d8e0807da) as part of the post-Merge miner refactor. Char-for-char transplant of the block that used to live inline inside startNode(); only the surrounding function header/footer are new, keeping cmd/geth/main.go identical to upstream and the PoW wiring isolated in main_pow.go (same pattern as misccmd_pow.go). In v1.17.3 the legacy downloader TypeMux was replaced by SubscribeSyncEvents, so the ExitWhenSynced handler now consumes downloader.SyncEvent.

3-way merge — purge → getc ← upstream

pre-purgeupstreamcommoncore-geth≈ adapted (origin inferred by similarity)fork-only
// startPoWFeatures starts the standalone mining and exit-when-synced handlers
// that upstream go-ethereum removed in PR #28623 (commit d8e0807da) as part of
// the post-Merge miner refactor. The body below is a char-for-char transplant
// of the block that used to live inline in startNode(); only the surrounding
// function header/footer are new.
func startPoWFeatures(ctx *cli.Context, stack *node.Node, ethBackend *eth.Ethereum) {
// Start mining if requested
if ctx.Bool(utils.MiningEnabledFlag.Name) && ethBackend != nil {
threads := ctx.Int(utils.MinerThreadsFlag.Name)
if err := ethBackend.StartMining(threads); err != nil {
utils.Fatalf("Failed to start mining: %v", err)
}
}
// Spawn a standalone goroutine for status synchronization monitoring,
// close the node when synchronization is complete if user required.
if ctx.Bool(utils.ExitWhenSyncedFlag.Name) && ethBackend != nil {
go func() {
eventCh := make(chan downloader.SyncEvent, 16)
sub := ethBackend.Downloader().SubscribeSyncEvents(eventCh)
defer sub.Unsubscribe()
for ev := range eventCh {
if ev.Type != downloader.SyncCompleted || ev.Latest == nil {
continue
}
if timestamp := time.Unix(int64(ev.Latest.Time), 0); time.Since(timestamp) < 10*time.Minute {
log.Info("Synchronisation completed", "latestnum", ev.Latest.Number, "latesthash", ev.Latest.Hash(),
"age", common.PrettyAge(timestamp))
stack.Close()
}
}
}()
}
}
core-geth validation — +18 -82 | | | |---|---| | File | [`main.go`](https://github.com/etclabscore/core-geth/blob/v1.12.20/cmd/geth/main.go) | | Symbol | `startNode` | | Ref | `v1.12.20` |
--- a/core-geth/cmd/geth/main.go
+++ b/etc/cmd/geth/main_pow.go
@@ -1,98 +1,34 @@
-// startNode boots up the system node and all registered protocols, after which
-// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
-// miner.
-func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isConsole bool) {
-   debug.Memsize.Add("node", stack)
-
-   // Start up the node itself
-   utils.StartNode(ctx, stack, isConsole)
-
-   // Unlock any account specifically requested
-   unlockAccounts(ctx, stack)
-
-   // Register wallet event handlers to open and auto-derive wallets
-   events := make(chan accounts.WalletEvent, 16)
-   stack.AccountManager().Subscribe(events)
-
-   // Create a client to interact with local geth node.
-   rpcClient := stack.Attach()
-   ethClient := ethclient.NewClient(rpcClient)
-
-   go func() {
-       // Open any wallets already attached
-       for _, wallet := range stack.AccountManager().Wallets() {
-           if err := wallet.Open(""); err != nil {
-               log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
-           }
-       }
-       // Listen for wallet event till termination
-       for event := range events {
-           switch event.Kind {
-           case accounts.WalletArrived:
-               if err := event.Wallet.Open(""); err != nil {
-                   log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
-               }
-           case accounts.WalletOpened:
-               status, _ := event.Wallet.Status()
-               log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status)
-
-               var derivationPaths []accounts.DerivationPath
-               if event.Wallet.URL().Scheme == "ledger" {
-                   derivationPaths = append(derivationPaths, accounts.LegacyLedgerBaseDerivationPath)
-               }
-               derivationPaths = append(derivationPaths, accounts.DefaultBaseDerivationPath)
-
-               event.Wallet.SelfDerive(derivationPaths, ethClient)
-
-           case accounts.WalletDropped:
-               log.Info("Old wallet dropped", "url", event.Wallet.URL())
-               event.Wallet.Close()
+// startPoWFeatures starts the standalone mining and exit-when-synced handlers
+// that upstream go-ethereum removed in PR #28623 (commit d8e0807da) as part of
+// the post-Merge miner refactor. The body below is a char-for-char transplant
+// of the block that used to live inline in startNode(); only the surrounding
+// function header/footer are new.
+func startPoWFeatures(ctx *cli.Context, stack *node.Node, ethBackend *eth.Ethereum) {
+   // Start mining if requested
+   if ctx.Bool(utils.MiningEnabledFlag.Name) && ethBackend != nil {
+       threads := ctx.Int(utils.MinerThreadsFlag.Name)
+       if err := ethBackend.StartMining(threads); err != nil {
+           utils.Fatalf("Failed to start mining: %v", err)
            }
        }
-   }()

    // Spawn a standalone goroutine for status synchronization monitoring,
    // close the node when synchronization is complete if user required.
-   if ctx.Bool(utils.ExitWhenSyncedFlag.Name) {
+   if ctx.Bool(utils.ExitWhenSyncedFlag.Name) && ethBackend != nil {
        go func() {
-           sub := stack.EventMux().Subscribe(downloader.DoneEvent{})
+           eventCh := make(chan downloader.SyncEvent, 16)
+           sub := ethBackend.Downloader().SubscribeSyncEvents(eventCh)
            defer sub.Unsubscribe()
-           for {
-               event := <-sub.Chan()
-               if event == nil {
+           for ev := range eventCh {
+               if ev.Type != downloader.SyncCompleted || ev.Latest == nil {
                    continue
                }
-               done, ok := event.Data.(downloader.DoneEvent)
-               if !ok {
-                   continue
-               }
-               if timestamp := time.Unix(int64(done.Latest.Time), 0); time.Since(timestamp) < 10*time.Minute {
-                   log.Info("Synchronisation completed", "latestnum", done.Latest.Number, "latesthash", done.Latest.Hash(),
+               if timestamp := time.Unix(int64(ev.Latest.Time), 0); time.Since(timestamp) < 10*time.Minute {
+                   log.Info("Synchronisation completed", "latestnum", ev.Latest.Number, "latesthash", ev.Latest.Hash(),
                        "age", common.PrettyAge(timestamp))
                    stack.Close()
                }
            }
        }()
    }
-
-   // Start auxiliary services if enabled
-   isDeveloperMode := ctx.Bool(utils.DeveloperFlag.Name) || ctx.Bool(utils.DeveloperPoWFlag.Name)
-   if ctx.Bool(utils.MiningEnabledFlag.Name) || isDeveloperMode {
-       // Mining only makes sense if a full Ethereum node is running
-       if ctx.String(utils.SyncModeFlag.Name) == "light" {
-           utils.Fatalf("Light clients do not support mining")
-       }
-       ethBackend, ok := backend.(*eth.EthAPIBackend)
-       if !ok {
-           utils.Fatalf("Ethereum service not running")
-       }
-       // Set the gas price to the limits from the CLI and start mining
-       gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
-       ethBackend.TxPool().SetGasTip(gasprice)
-       // start mining
-       threads := ctx.Int(utils.MinerThreadsFlag.Name)
-       if err := ethBackend.StartMining(threads); err != nil {
-           utils.Fatalf("Failed to start mining: %v", err)
-       }
-   }
 }

← CLI, Config & Genesis