github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/cmd/quickchain/main.go (about) 1 // quickchain is the official command-line client for Quickchain. 2 package main 3 4 import ( 5 "fmt" 6 "os" 7 "runtime" 8 "sort" 9 "strings" 10 "time" 11 12 "github.com/quickchainproject/quickchain/accounts" 13 "github.com/quickchainproject/quickchain/accounts/keystore" 14 "github.com/quickchainproject/quickchain/cmd/utils" 15 "github.com/quickchainproject/quickchain/console" 16 "github.com/quickchainproject/quickchain/internal/debug" 17 "github.com/quickchainproject/quickchain/qct" 18 "github.com/quickchainproject/quickchain/qctclient" 19 "github.com/quickchainproject/quickchain/log" 20 "github.com/quickchainproject/quickchain/metrics" 21 "github.com/quickchainproject/quickchain/node" 22 "gopkg.in/urfave/cli.v1" 23 ) 24 25 const ( 26 clientIdentifier = "quickchain" // Client identifier to advertise over the network 27 ) 28 29 var ( 30 // Git SHA1 commit hash of the release (set via linker flags) 31 gitCommit = "" 32 // The app that holds all commands and flags. 33 app = utils.NewApp(gitCommit, "the quickchain command line interface") 34 // flags that configure the node 35 nodeFlags = []cli.Flag{ 36 utils.IdentityFlag, 37 utils.UnlockedAccountFlag, 38 utils.PasswordFileFlag, 39 utils.BootnodesFlag, 40 utils.BootnodesV4Flag, 41 utils.BootnodesV5Flag, 42 utils.DataDirFlag, 43 utils.KeyStoreDirFlag, 44 utils.NoUSBFlag, 45 utils.DashboardEnabledFlag, 46 utils.DashboardAddrFlag, 47 utils.DashboardPortFlag, 48 utils.DashboardRefreshFlag, 49 utils.TxPoolNoLocalsFlag, 50 utils.TxPoolJournalFlag, 51 utils.TxPoolRejournalFlag, 52 utils.TxPoolPriceLimitFlag, 53 utils.TxPoolPriceBumpFlag, 54 utils.TxPoolAccountSlotsFlag, 55 utils.TxPoolGlobalSlotsFlag, 56 utils.TxPoolAccountQueueFlag, 57 utils.TxPoolGlobalQueueFlag, 58 utils.TxPoolLifetimeFlag, 59 utils.FastSyncFlag, 60 utils.LightModeFlag, 61 utils.SyncModeFlag, 62 utils.GCModeFlag, 63 utils.LightServFlag, 64 utils.LightPeersFlag, 65 utils.LightKDFFlag, 66 utils.CacheFlag, 67 utils.CacheDatabaseFlag, 68 utils.CacheGCFlag, 69 utils.TrieCacheGenFlag, 70 utils.ListenPortFlag, 71 utils.MaxPeersFlag, 72 utils.MaxPendingPeersFlag, 73 utils.EtherbaseFlag, 74 utils.GasPriceFlag, 75 utils.MinerThreadsFlag, 76 utils.MiningEnabledFlag, 77 utils.TargetGasLimitFlag, 78 utils.NATFlag, 79 utils.NoDiscoverFlag, 80 utils.DiscoveryV5Flag, 81 utils.NetrestrictFlag, 82 utils.NodeKeyFileFlag, 83 utils.NodeKeyHexFlag, 84 utils.DeveloperFlag, 85 utils.DeveloperPeriodFlag, 86 utils.TestnetFlag, 87 utils.POAFlag, 88 utils.BFTFlag, 89 utils.DBFTFlag, 90 utils.VMEnableDebugFlag, 91 utils.NetworkIdFlag, 92 utils.RPCCORSDomainFlag, 93 utils.RPCVirtualHostsFlag, 94 utils.EthStatsURLFlag, 95 utils.MetricsEnabledFlag, 96 utils.NoCompactionFlag, 97 utils.GpoBlocksFlag, 98 utils.GpoPercentileFlag, 99 utils.ExtraDataFlag, 100 configFileFlag, 101 } 102 103 rpcFlags = []cli.Flag{ 104 utils.RPCEnabledFlag, 105 utils.RPCListenAddrFlag, 106 utils.RPCPortFlag, 107 utils.RPCApiFlag, 108 utils.WSEnabledFlag, 109 utils.WSListenAddrFlag, 110 utils.WSPortFlag, 111 utils.WSApiFlag, 112 utils.WSAllowedOriginsFlag, 113 utils.IPCDisabledFlag, 114 utils.IPCPathFlag, 115 } 116 ) 117 118 func init() { 119 // Initialize the CLI app and start Geth 120 app.Action = quickchain 121 app.HideVersion = true // we have a command to print the version 122 app.Copyright = "Copyright 2019 The quickchain Authors" 123 app.Commands = []cli.Command{ 124 // See chaincmd.go: 125 initCommand, 126 importCommand, 127 exportCommand, 128 importPreimagesCommand, 129 exportPreimagesCommand, 130 copydbCommand, 131 removedbCommand, 132 dumpCommand, 133 // See monitorcmd.go: 134 monitorCommand, 135 // See accountcmd.go: 136 accountCommand, 137 walletCommand, 138 // See consolecmd.go: 139 consoleCommand, 140 attachCommand, 141 javascriptCommand, 142 // See misccmd.go: 143 versionCommand, 144 bugCommand, 145 licenseCommand, 146 // See config.go 147 dumpConfigCommand, 148 } 149 sort.Sort(cli.CommandsByName(app.Commands)) 150 151 app.Flags = append(app.Flags, nodeFlags...) 152 app.Flags = append(app.Flags, rpcFlags...) 153 app.Flags = append(app.Flags, consoleFlags...) 154 app.Flags = append(app.Flags, debug.Flags...) 155 156 app.Before = func(ctx *cli.Context) error { 157 runtime.GOMAXPROCS(runtime.NumCPU()) 158 if err := debug.Setup(ctx); err != nil { 159 return err 160 } 161 // Start system runtime metrics collection 162 go metrics.CollectProcessMetrics(3 * time.Second) 163 164 utils.SetupNetwork(ctx) 165 return nil 166 } 167 168 app.After = func(ctx *cli.Context) error { 169 debug.Exit() 170 console.Stdin.Close() // Resets terminal mode. 171 return nil 172 } 173 } 174 175 func main() { 176 if err := app.Run(os.Args); err != nil { 177 fmt.Fprintln(os.Stderr, err) 178 os.Exit(1) 179 } 180 } 181 182 // quickchain is the main entry point into the system if no special subcommand is ran. 183 // It creates a default node based on the command line arguments and runs it in 184 // blocking mode, waiting for it to be shut down. 185 func quickchain(ctx *cli.Context) error { 186 node := makeFullNode(ctx) 187 startNode(ctx, node) 188 node.Wait() 189 return nil 190 } 191 192 // startNode boots up the system node and all registered protocols, after which 193 // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the 194 // miner. 195 func startNode(ctx *cli.Context, stack *node.Node) { 196 debug.Memsize.Add("node", stack) 197 198 // Start up the node itself 199 utils.StartNode(stack) 200 201 // Unlock any account specifically requested 202 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 203 204 passwords := utils.MakePasswordList(ctx) 205 unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") 206 for i, account := range unlocks { 207 if trimmed := strings.TrimSpace(account); trimmed != "" { 208 unlockAccount(ctx, ks, trimmed, i, passwords) 209 } 210 } 211 // Register wallet event handlers to open and auto-derive wallets 212 events := make(chan accounts.WalletEvent, 16) 213 stack.AccountManager().Subscribe(events) 214 215 go func() { 216 // Create a chain state reader for self-derivation 217 rpcClient, err := stack.Attach() 218 if err != nil { 219 utils.Fatalf("Failed to attach to self: %v", err) 220 } 221 stateReader := qctclient.NewClient(rpcClient) 222 223 // Open any wallets already attached 224 for _, wallet := range stack.AccountManager().Wallets() { 225 if err := wallet.Open(""); err != nil { 226 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 227 } 228 } 229 // Listen for wallet event till termination 230 for event := range events { 231 switch event.Kind { 232 case accounts.WalletArrived: 233 if err := event.Wallet.Open(""); err != nil { 234 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 235 } 236 case accounts.WalletOpened: 237 status, _ := event.Wallet.Status() 238 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 239 240 if event.Wallet.URL().Scheme == "ledger" { 241 event.Wallet.SelfDerive(accounts.DefaultLedgerBaseDerivationPath, stateReader) 242 } else { 243 event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader) 244 } 245 246 case accounts.WalletDropped: 247 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 248 event.Wallet.Close() 249 } 250 } 251 }() 252 // Start auxiliary services if enabled 253 if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { 254 // Mining only makes sense if a full Ethereum node is running 255 if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { 256 utils.Fatalf("Light clients do not support mining") 257 } 258 var quickchain *qct.Ethereum 259 if err := stack.Service(&quickchain); err != nil { 260 utils.Fatalf("Ethereum service not running: %v", err) 261 } 262 // Use a reduced number of threads if requested 263 if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > 0 { 264 type threaded interface { 265 SetThreads(threads int) 266 } 267 if th, ok := quickchain.Engine().(threaded); ok { 268 th.SetThreads(threads) 269 } 270 } 271 // Set the gas price to the limits from the CLI and start mining 272 quickchain.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name)) 273 if err := quickchain.StartMining(true); err != nil { 274 utils.Fatalf("Failed to start mining: %v", err) 275 } 276 } 277 }