github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/cmd/geth/main.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // geth is the official command-line client for Ethereum. 18 package main 19 20 import ( 21 "fmt" 22 "math" 23 "os" 24 godebug "runtime/debug" 25 "sort" 26 "strconv" 27 "strings" 28 "time" 29 30 "github.com/kisexp/xdchain/accounts" 31 "github.com/kisexp/xdchain/accounts/keystore" 32 "github.com/kisexp/xdchain/accounts/pluggable" 33 "github.com/kisexp/xdchain/cmd/utils" 34 "github.com/kisexp/xdchain/common" 35 "github.com/kisexp/xdchain/console/prompt" 36 "github.com/kisexp/xdchain/eth" 37 "github.com/kisexp/xdchain/eth/downloader" 38 "github.com/kisexp/xdchain/ethclient" 39 "github.com/kisexp/xdchain/internal/debug" 40 "github.com/kisexp/xdchain/internal/ethapi" 41 "github.com/kisexp/xdchain/internal/flags" 42 "github.com/kisexp/xdchain/log" 43 "github.com/kisexp/xdchain/metrics" 44 "github.com/kisexp/xdchain/node" 45 "github.com/kisexp/xdchain/permission" 46 "github.com/kisexp/xdchain/plugin" 47 gopsutil "github.com/shirou/gopsutil/mem" 48 "gopkg.in/urfave/cli.v1" 49 ) 50 51 const ( 52 clientIdentifier = "geth" // Client identifier to advertise over the network 53 ) 54 55 var ( 56 // Git SHA1 commit hash of the release (set via linker flags) 57 gitCommit = "" 58 gitDate = "" 59 // The app that holds all commands and flags. 60 app = flags.NewApp(gitCommit, gitDate, "the go-ethereum command line interface") 61 // flags that configure the node 62 nodeFlags = []cli.Flag{ 63 utils.IdentityFlag, 64 utils.UnlockedAccountFlag, 65 utils.PasswordFileFlag, 66 utils.BootnodesFlag, 67 utils.LegacyBootnodesV4Flag, 68 utils.LegacyBootnodesV5Flag, 69 utils.DataDirFlag, 70 utils.RaftLogDirFlag, 71 utils.AncientFlag, 72 utils.KeyStoreDirFlag, 73 utils.ExternalSignerFlag, 74 utils.NoUSBFlag, 75 utils.SmartCardDaemonPathFlag, 76 utils.EthashCacheDirFlag, 77 utils.EthashCachesInMemoryFlag, 78 utils.EthashCachesOnDiskFlag, 79 utils.EthashCachesLockMmapFlag, 80 utils.EthashDatasetDirFlag, 81 utils.EthashDatasetsInMemoryFlag, 82 utils.EthashDatasetsOnDiskFlag, 83 utils.EthashDatasetsLockMmapFlag, 84 utils.TxPoolLocalsFlag, 85 utils.TxPoolNoLocalsFlag, 86 utils.TxPoolJournalFlag, 87 utils.TxPoolRejournalFlag, 88 utils.TxPoolPriceLimitFlag, 89 utils.TxPoolPriceBumpFlag, 90 utils.TxPoolAccountSlotsFlag, 91 utils.TxPoolGlobalSlotsFlag, 92 utils.TxPoolAccountQueueFlag, 93 utils.TxPoolGlobalQueueFlag, 94 utils.TxPoolLifetimeFlag, 95 utils.SyncModeFlag, 96 utils.ExitWhenSyncedFlag, 97 utils.GCModeFlag, 98 utils.SnapshotFlag, 99 utils.TxLookupLimitFlag, 100 utils.LightServeFlag, 101 utils.LegacyLightServFlag, 102 utils.LightIngressFlag, 103 utils.LightEgressFlag, 104 utils.LightMaxPeersFlag, 105 utils.LegacyLightPeersFlag, 106 utils.LightNoPruneFlag, 107 utils.LightKDFFlag, 108 utils.UltraLightServersFlag, 109 utils.UltraLightFractionFlag, 110 utils.UltraLightOnlyAnnounceFlag, 111 utils.AuthorizationListFlag, 112 utils.CacheFlag, 113 utils.CacheDatabaseFlag, 114 utils.CacheTrieFlag, 115 utils.CacheTrieJournalFlag, 116 utils.CacheTrieRejournalFlag, 117 utils.CacheGCFlag, 118 utils.CacheSnapshotFlag, 119 utils.CacheNoPrefetchFlag, 120 utils.CachePreimagesFlag, 121 utils.ListenPortFlag, 122 utils.MaxPeersFlag, 123 utils.MaxPendingPeersFlag, 124 utils.MiningEnabledFlag, 125 utils.MinerThreadsFlag, 126 utils.LegacyMinerThreadsFlag, 127 utils.MinerNotifyFlag, 128 utils.MinerGasTargetFlag, 129 utils.LegacyMinerGasTargetFlag, 130 utils.MinerGasLimitFlag, 131 utils.MinerGasPriceFlag, 132 utils.LegacyMinerGasPriceFlag, 133 utils.MinerEtherbaseFlag, 134 utils.LegacyMinerEtherbaseFlag, 135 utils.MinerExtraDataFlag, 136 utils.LegacyMinerExtraDataFlag, 137 utils.MinerRecommitIntervalFlag, 138 utils.MinerNoVerfiyFlag, 139 utils.NATFlag, 140 utils.NoDiscoverFlag, 141 utils.DiscoveryV5Flag, 142 utils.NetrestrictFlag, 143 utils.NodeKeyFileFlag, 144 utils.NodeKeyHexFlag, 145 utils.DNSDiscoveryFlag, 146 utils.DeveloperFlag, 147 utils.DeveloperPeriodFlag, 148 utils.LegacyTestnetFlag, 149 utils.RopstenFlag, 150 utils.RinkebyFlag, 151 utils.GoerliFlag, 152 utils.YoloV2Flag, 153 utils.VMEnableDebugFlag, 154 utils.NetworkIdFlag, 155 utils.EthStatsURLFlag, 156 utils.FakePoWFlag, 157 utils.NoCompactionFlag, 158 utils.GpoBlocksFlag, 159 utils.LegacyGpoBlocksFlag, 160 utils.GpoPercentileFlag, 161 utils.LegacyGpoPercentileFlag, 162 utils.GpoMaxGasPriceFlag, 163 utils.EWASMInterpreterFlag, 164 utils.EVMInterpreterFlag, 165 configFileFlag, 166 // Quorum 167 utils.PrivateCacheTrieJournalFlag, 168 utils.QuorumImmutabilityThreshold, 169 utils.EnableNodePermissionFlag, 170 utils.RaftModeFlag, 171 utils.RaftBlockTimeFlag, 172 utils.RaftJoinExistingFlag, 173 utils.RaftPortFlag, 174 utils.RaftDNSEnabledFlag, 175 utils.EmitCheckpointsFlag, 176 utils.IstanbulRequestTimeoutFlag, 177 utils.IstanbulBlockPeriodFlag, 178 utils.PluginSettingsFlag, 179 utils.PluginSkipVerifyFlag, 180 utils.PluginLocalVerifyFlag, 181 utils.PluginPublicKeyFlag, 182 utils.AllowedFutureBlockTimeFlag, 183 utils.EVMCallTimeOutFlag, 184 utils.MultitenancyFlag, 185 utils.RevertReasonFlag, 186 utils.QuorumEnablePrivacyMarker, 187 utils.QuorumPTMUnixSocketFlag, 188 utils.QuorumPTMUrlFlag, 189 utils.QuorumPTMTimeoutFlag, 190 utils.QuorumPTMDialTimeoutFlag, 191 utils.QuorumPTMHttpIdleTimeoutFlag, 192 utils.QuorumPTMHttpWriteBufferSizeFlag, 193 utils.QuorumPTMHttpReadBufferSizeFlag, 194 utils.QuorumPTMTlsModeFlag, 195 utils.QuorumPTMTlsRootCaFlag, 196 utils.QuorumPTMTlsClientCertFlag, 197 utils.QuorumPTMTlsClientKeyFlag, 198 utils.QuorumPTMTlsInsecureSkipVerify, 199 // End-Quorum 200 } 201 202 rpcFlags = []cli.Flag{ 203 utils.HTTPEnabledFlag, 204 utils.HTTPListenAddrFlag, 205 utils.HTTPPortFlag, 206 utils.HTTPCORSDomainFlag, 207 utils.HTTPVirtualHostsFlag, 208 utils.LegacyRPCEnabledFlag, 209 utils.LegacyRPCListenAddrFlag, 210 utils.LegacyRPCPortFlag, 211 utils.LegacyRPCCORSDomainFlag, 212 utils.LegacyRPCVirtualHostsFlag, 213 utils.GraphQLEnabledFlag, 214 utils.GraphQLCORSDomainFlag, 215 utils.GraphQLVirtualHostsFlag, 216 utils.HTTPApiFlag, 217 utils.LegacyRPCApiFlag, 218 utils.WSEnabledFlag, 219 utils.WSListenAddrFlag, 220 utils.LegacyWSListenAddrFlag, 221 utils.WSPortFlag, 222 utils.LegacyWSPortFlag, 223 utils.WSApiFlag, 224 utils.LegacyWSApiFlag, 225 utils.WSAllowedOriginsFlag, 226 utils.LegacyWSAllowedOriginsFlag, 227 utils.IPCDisabledFlag, 228 utils.IPCPathFlag, 229 utils.InsecureUnlockAllowedFlag, 230 utils.RPCGlobalGasCapFlag, 231 utils.RPCGlobalTxFeeCapFlag, 232 } 233 234 whisperFlags = []cli.Flag{ 235 utils.WhisperEnabledFlag, 236 utils.WhisperMaxMessageSizeFlag, 237 utils.WhisperMinPOWFlag, 238 utils.WhisperRestrictConnectionBetweenLightClientsFlag, 239 } 240 241 metricsFlags = []cli.Flag{ 242 utils.MetricsEnabledFlag, 243 utils.MetricsEnabledExpensiveFlag, 244 utils.MetricsHTTPFlag, 245 utils.MetricsPortFlag, 246 utils.MetricsEnableInfluxDBFlag, 247 utils.MetricsInfluxDBEndpointFlag, 248 utils.MetricsInfluxDBDatabaseFlag, 249 utils.MetricsInfluxDBUsernameFlag, 250 utils.MetricsInfluxDBPasswordFlag, 251 utils.MetricsInfluxDBTagsFlag, 252 } 253 ) 254 255 func init() { 256 // Initialize the CLI app and start Geth 257 app.Action = geth 258 app.HideVersion = true // we have a command to print the version 259 app.Copyright = "Copyright 2013-2020 The go-ethereum Authors" 260 app.Commands = []cli.Command{ 261 // See chaincmd.go: 262 initCommand, 263 mpsdbUpgradeCommand, 264 importCommand, 265 exportCommand, 266 importPreimagesCommand, 267 exportPreimagesCommand, 268 copydbCommand, 269 removedbCommand, 270 dumpCommand, 271 dumpGenesisCommand, 272 inspectCommand, 273 // See accountcmd.go: 274 accountCommand, 275 walletCommand, 276 // See consolecmd.go: 277 consoleCommand, 278 attachCommand, 279 javascriptCommand, 280 // See misccmd.go: 281 makecacheCommand, 282 makedagCommand, 283 versionCommand, 284 versionCheckCommand, 285 licenseCommand, 286 // See config.go 287 dumpConfigCommand, 288 // See cmd/utils/flags_legacy.go 289 utils.ShowDeprecated, 290 } 291 sort.Sort(cli.CommandsByName(app.Commands)) 292 293 app.Flags = append(app.Flags, nodeFlags...) 294 app.Flags = append(app.Flags, rpcFlags...) 295 app.Flags = append(app.Flags, consoleFlags...) 296 app.Flags = append(app.Flags, debug.Flags...) 297 app.Flags = append(app.Flags, debug.DeprecatedFlags...) 298 app.Flags = append(app.Flags, whisperFlags...) 299 app.Flags = append(app.Flags, metricsFlags...) 300 301 app.Before = func(ctx *cli.Context) error { 302 return debug.Setup(ctx) 303 } 304 app.After = func(ctx *cli.Context) error { 305 debug.Exit() 306 prompt.Stdin.Close() // Resets terminal mode. 307 return nil 308 } 309 } 310 311 func main() { 312 if err := app.Run(os.Args); err != nil { 313 fmt.Fprintln(os.Stderr, err) 314 os.Exit(1) 315 } 316 } 317 318 // prepare manipulates memory cache allowance and setups metric system. 319 // This function should be called before launching devp2p stack. 320 func prepare(ctx *cli.Context) { 321 // If we're running a known preset, log it for convenience. 322 switch { 323 case ctx.GlobalIsSet(utils.LegacyTestnetFlag.Name): 324 log.Info("Starting Geth on Ropsten testnet...") 325 log.Warn("The --testnet flag is ambiguous! Please specify one of --goerli, --rinkeby, or --ropsten.") 326 log.Warn("The generic --testnet flag is deprecated and will be removed in the future!") 327 328 case ctx.GlobalIsSet(utils.RopstenFlag.Name): 329 log.Info("Starting Geth on Ropsten testnet...") 330 331 case ctx.GlobalIsSet(utils.RinkebyFlag.Name): 332 log.Info("Starting Geth on Rinkeby testnet...") 333 334 case ctx.GlobalIsSet(utils.GoerliFlag.Name): 335 log.Info("Starting Geth on Görli testnet...") 336 337 case ctx.GlobalIsSet(utils.DeveloperFlag.Name): 338 log.Info("Starting Geth in ephemeral dev mode...") 339 340 case !ctx.GlobalIsSet(utils.NetworkIdFlag.Name): 341 log.Info("Starting Geth on Ethereum mainnet...") 342 } 343 // If we're a full node on mainnet without --cache specified, bump default cache allowance 344 if ctx.GlobalString(utils.SyncModeFlag.Name) != "light" && !ctx.GlobalIsSet(utils.CacheFlag.Name) && !ctx.GlobalIsSet(utils.NetworkIdFlag.Name) { 345 // Make sure we're not on any supported preconfigured testnet either 346 if !ctx.GlobalIsSet(utils.LegacyTestnetFlag.Name) && !ctx.GlobalIsSet(utils.RopstenFlag.Name) && !ctx.GlobalIsSet(utils.RinkebyFlag.Name) && !ctx.GlobalIsSet(utils.GoerliFlag.Name) && !ctx.GlobalIsSet(utils.DeveloperFlag.Name) { 347 // Nope, we're really on mainnet. Bump that cache up! 348 log.Info("Bumping default cache on mainnet", "provided", ctx.GlobalInt(utils.CacheFlag.Name), "updated", 4096) 349 ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(4096)) 350 } 351 } 352 // If we're running a light client on any network, drop the cache to some meaningfully low amount 353 if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" && !ctx.GlobalIsSet(utils.CacheFlag.Name) { 354 log.Info("Dropping default light client cache", "provided", ctx.GlobalInt(utils.CacheFlag.Name), "updated", 128) 355 ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(128)) 356 } 357 // Cap the cache allowance and tune the garbage collector 358 mem, err := gopsutil.VirtualMemory() 359 if err == nil { 360 if 32<<(^uintptr(0)>>63) == 32 && mem.Total > 2*1024*1024*1024 { 361 log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024) 362 mem.Total = 2 * 1024 * 1024 * 1024 363 } 364 allowance := int(mem.Total / 1024 / 1024 / 3) 365 if cache := ctx.GlobalInt(utils.CacheFlag.Name); cache > allowance { 366 log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) 367 ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(allowance)) 368 } 369 } 370 // Ensure Go's GC ignores the database cache for trigger percentage 371 cache := ctx.GlobalInt(utils.CacheFlag.Name) 372 gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024))) 373 374 log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc)) 375 godebug.SetGCPercent(int(gogc)) 376 377 // Start metrics export if enabled 378 utils.SetupMetrics(ctx) 379 380 // Start system runtime metrics collection 381 go metrics.CollectProcessMetrics(3 * time.Second) 382 } 383 384 // geth is the main entry point into the system if no special subcommand is ran. 385 // It creates a default node based on the command line arguments and runs it in 386 // blocking mode, waiting for it to be shut down. 387 func geth(ctx *cli.Context) error { 388 if args := ctx.Args(); len(args) > 0 { 389 return fmt.Errorf("invalid command: %q", args[0]) 390 } 391 392 prepare(ctx) 393 394 stack, backend := makeFullNode(ctx) 395 defer stack.Close() 396 397 startNode(ctx, stack, backend) 398 399 stack.Wait() 400 return nil 401 } 402 403 // startNode boots up the system node and all registered protocols, after which 404 // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the 405 // miner. 406 func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend) { 407 log.DoEmitCheckpoints = ctx.GlobalBool(utils.EmitCheckpointsFlag.Name) 408 debug.Memsize.Add("node", stack) 409 410 // raft mode does not support --exitwhensynced 411 if ctx.GlobalBool(utils.ExitWhenSyncedFlag.Name) && ctx.GlobalBool(utils.RaftModeFlag.Name) { 412 utils.Fatalf("raft consensus does not support --exitwhensynced") 413 } 414 415 // Start up the node itself 416 utils.StartNode(stack) 417 418 // Now that the plugin manager has been started we register the account plugin with the corresponding account backend. All other account management is disabled when using External Signer 419 if !ctx.IsSet(utils.ExternalSignerFlag.Name) && stack.PluginManager().IsEnabled(plugin.AccountPluginInterfaceName) { 420 b := stack.AccountManager().Backends(pluggable.BackendType)[0].(*pluggable.Backend) 421 if err := stack.PluginManager().AddAccountPluginToBackend(b); err != nil { 422 log.Error("failed to setup account plugin", "err", err) 423 } 424 } 425 426 // Unlock any account specifically requested 427 unlockAccounts(ctx, stack) 428 429 // Register wallet event handlers to open and auto-derive wallets 430 events := make(chan accounts.WalletEvent, 16) 431 stack.AccountManager().Subscribe(events) 432 433 // Create a client to interact with local geth node. 434 rpcClient, err := stack.Attach() 435 if err != nil { 436 utils.Fatalf("Failed to attach to self: %v", err) 437 } 438 ethClient := ethclient.NewClient(rpcClient) 439 440 // Quorum 441 if ctx.GlobalBool(utils.MultitenancyFlag.Name) && !stack.PluginManager().IsEnabled(plugin.SecurityPluginInterfaceName) { 442 utils.Fatalf("multitenancy requires RPC Security Plugin to be configured") 443 } 444 // End Quorum 445 446 go func() { 447 // Open any wallets already attached 448 for _, wallet := range stack.AccountManager().Wallets() { 449 if err := wallet.Open(""); err != nil { 450 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 451 } 452 } 453 // Listen for wallet event till termination 454 for event := range events { 455 switch event.Kind { 456 case accounts.WalletArrived: 457 if err := event.Wallet.Open(""); err != nil { 458 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 459 } 460 case accounts.WalletOpened: 461 status, _ := event.Wallet.Status() 462 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 463 464 var derivationPaths []accounts.DerivationPath 465 if event.Wallet.URL().Scheme == "ledger" { 466 derivationPaths = append(derivationPaths, accounts.LegacyLedgerBaseDerivationPath) 467 } 468 derivationPaths = append(derivationPaths, accounts.DefaultBaseDerivationPath) 469 470 event.Wallet.SelfDerive(derivationPaths, ethClient) 471 472 case accounts.WalletDropped: 473 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 474 event.Wallet.Close() 475 } 476 } 477 }() 478 479 // Spawn a standalone goroutine for status synchronization monitoring, 480 // close the node when synchronization is complete if user required. 481 if ctx.GlobalBool(utils.ExitWhenSyncedFlag.Name) { 482 go func() { 483 sub := stack.EventMux().Subscribe(downloader.DoneEvent{}) 484 defer sub.Unsubscribe() 485 for { 486 event := <-sub.Chan() 487 if event == nil { 488 continue 489 } 490 done, ok := event.Data.(downloader.DoneEvent) 491 if !ok { 492 continue 493 } 494 if timestamp := time.Unix(int64(done.Latest.Time), 0); time.Since(timestamp) < 10*time.Minute { 495 log.Info("Synchronisation completed", "latestnum", done.Latest.Number, "latesthash", done.Latest.Hash(), 496 "age", common.PrettyAge(timestamp)) 497 stack.Close() 498 } 499 } 500 }() 501 } 502 503 // Quorum 504 // 505 // checking if permissions is enabled and staring the permissions service 506 if stack.Config().EnableNodePermission { 507 stack.Server().SetIsNodePermissioned(permission.IsNodePermissioned) 508 if stack.IsPermissionEnabled() { 509 var permissionService *permission.PermissionCtrl 510 if err := stack.Lifecycle(&permissionService); err != nil { 511 utils.Fatalf("Permission service not runnning: %v", err) 512 } 513 if err := permissionService.AfterStart(); err != nil { 514 utils.Fatalf("Permission service post construct failure: %v", err) 515 } 516 } 517 } 518 519 // Start auxiliary services if enabled 520 if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { 521 // Mining only makes sense if a full Ethereum node is running 522 if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { 523 utils.Fatalf("Light clients do not support mining") 524 } 525 ethBackend, ok := backend.(*eth.EthAPIBackend) 526 if !ok { 527 utils.Fatalf("Ethereum service not running: %v", err) 528 } 529 530 // Set the gas price to the limits from the CLI and start mining 531 gasprice := utils.GlobalBig(ctx, utils.MinerGasPriceFlag.Name) 532 if ctx.GlobalIsSet(utils.LegacyMinerGasPriceFlag.Name) && !ctx.GlobalIsSet(utils.MinerGasPriceFlag.Name) { 533 gasprice = utils.GlobalBig(ctx, utils.LegacyMinerGasPriceFlag.Name) 534 } 535 ethBackend.TxPool().SetGasPrice(gasprice) 536 // start mining 537 threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name) 538 if ctx.GlobalIsSet(utils.LegacyMinerThreadsFlag.Name) && !ctx.GlobalIsSet(utils.MinerThreadsFlag.Name) { 539 threads = ctx.GlobalInt(utils.LegacyMinerThreadsFlag.Name) 540 log.Warn("The flag --minerthreads is deprecated and will be removed in the future, please use --miner.threads") 541 } 542 if err := ethBackend.StartMining(threads); err != nil { 543 utils.Fatalf("Failed to start mining: %v", err) 544 } 545 } 546 547 // checks quorum features that depend on the ethereum service 548 quorumValidateEthService(stack, ctx.GlobalBool(utils.RaftModeFlag.Name)) 549 } 550 551 // unlockAccounts unlocks any account specifically requested. 552 func unlockAccounts(ctx *cli.Context, stack *node.Node) { 553 var unlocks []string 554 inputs := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") 555 for _, input := range inputs { 556 if trimmed := strings.TrimSpace(input); trimmed != "" { 557 unlocks = append(unlocks, trimmed) 558 } 559 } 560 // Short circuit if there is no account to unlock. 561 if len(unlocks) == 0 { 562 return 563 } 564 // If insecure account unlocking is not allowed if node's APIs are exposed to external. 565 // Print warning log to user and skip unlocking. 566 if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() { 567 utils.Fatalf("Account unlock with HTTP access is forbidden!") 568 } 569 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 570 passwords := utils.MakePasswordList(ctx) 571 for i, account := range unlocks { 572 unlockAccount(ks, account, i, passwords) 573 } 574 }