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)
- }
- }
}