github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/cmd/smc/main.go (about) 1 // Copyright 2014 The Spectrum Authors 2 // This file is part of Spectrum. 3 // 4 // Spectrum 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 // Spectrum 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 Spectrum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "fmt" 21 "os" 22 "runtime" 23 "sort" 24 "strings" 25 "time" 26 27 "github.com/SmartMeshFoundation/Spectrum/accounts" 28 "github.com/SmartMeshFoundation/Spectrum/accounts/keystore" 29 "github.com/SmartMeshFoundation/Spectrum/cmd/utils" 30 "github.com/SmartMeshFoundation/Spectrum/console" 31 "github.com/SmartMeshFoundation/Spectrum/eth" 32 "github.com/SmartMeshFoundation/Spectrum/ethclient" 33 "github.com/SmartMeshFoundation/Spectrum/internal/debug" 34 "github.com/SmartMeshFoundation/Spectrum/log" 35 "github.com/SmartMeshFoundation/Spectrum/metrics" 36 "github.com/SmartMeshFoundation/Spectrum/node" 37 "gopkg.in/urfave/cli.v1" 38 ) 39 40 const ( 41 clientIdentifier = "smc" // Client identifier to advertise over the network 42 ) 43 44 var ( 45 // Git SHA1 commit hash of the release (set via linker flags) 46 gitCommit = "" 47 // Ethereum address of the Geth release oracle. 48 // relOracle = common.HexToAddress("0xfa7b9770ca4cb04296cac84f37736d4041251cdf") 49 // The app that holds all commands and flags. 50 app = utils.NewApp(gitCommit, "the Spectrum command line interface") 51 // flags that configure the node 52 nodeFlags = []cli.Flag{ 53 utils.IdentityFlag, 54 utils.UnlockedAccountFlag, 55 utils.PasswordFileFlag, 56 utils.BootnodesFlag, 57 //utils.BootnodesV4Flag, 58 //utils.BootnodesV5Flag, 59 utils.DataDirFlag, 60 utils.KeyStoreDirFlag, 61 /* 62 utils.EthashCacheDirFlag, 63 utils.EthashCachesInMemoryFlag, 64 utils.EthashCachesOnDiskFlag, 65 utils.EthashDatasetDirFlag, 66 utils.EthashDatasetsInMemoryFlag, 67 utils.EthashDatasetsOnDiskFlag, 68 */ 69 utils.TxPoolNoLocalsFlag, 70 utils.TxPoolJournalFlag, 71 utils.TxPoolRejournalFlag, 72 utils.TxPoolPriceLimitFlag, 73 utils.TxPoolPriceBumpFlag, 74 utils.TxPoolAccountSlotsFlag, 75 utils.TxPoolGlobalSlotsFlag, 76 utils.TxPoolAccountQueueFlag, 77 utils.TxPoolGlobalQueueFlag, 78 utils.TxPoolLifetimeFlag, 79 /* add by liangc : disable 80 utils.FastSyncFlag, 81 utils.LightModeFlag, 82 utils.SyncModeFlag, 83 84 utils.LightServFlag, 85 utils.LightPeersFlag, 86 utils.LightKDFFlag, 87 88 89 utils.DashboardEnabledFlag, 90 utils.DashboardAddrFlag, 91 utils.DashboardPortFlag, 92 utils.DashboardRefreshFlag, 93 utils.DashboardAssetsFlag, 94 95 utils.NoUSBFlag, 96 97 utils.NodeKeyFileFlag, 98 utils.NodeKeyHexFlag, 99 100 utils.MinerThreadsFlag, 101 utils.MiningEnabledFlag, 102 103 utils.DiscoveryV5Flag, 104 105 utils.FakePoWFlag, 106 utils.DeveloperPeriodFlag, 107 utils.EtherbaseFlag, 108 */ 109 utils.CacheFlag, 110 utils.TrieCacheGenFlag, 111 utils.ListenPortFlag, 112 utils.MaxPeersFlag, 113 utils.MaxPendingPeersFlag, 114 utils.GasPriceFlag, 115 utils.TargetGasLimitFlag, 116 utils.NATFlag, 117 utils.NoDiscoverFlag, 118 utils.NetrestrictFlag, 119 //utils.DeveloperFlag, 120 utils.DevnetFlag, 121 utils.DevnetResetFlag, 122 utils.DevnetMasterFlag, 123 utils.TestnetFlag, 124 utils.VMEnableDebugFlag, 125 utils.NetworkIdFlag, 126 utils.RPCCORSDomainFlag, 127 utils.EthStatsURLFlag, 128 utils.MetricsEnabledFlag, 129 utils.NoCompactionFlag, 130 utils.GpoBlocksFlag, 131 utils.GpoPercentileFlag, 132 utils.ExtraDataFlag, 133 configFileFlag, 134 } 135 136 rpcFlags = []cli.Flag{ 137 utils.RPCEnabledFlag, 138 utils.RPCListenAddrFlag, 139 utils.RPCPortFlag, 140 utils.RPCApiFlag, 141 utils.WSEnabledFlag, 142 utils.WSListenAddrFlag, 143 utils.WSPortFlag, 144 utils.WSApiFlag, 145 utils.WSAllowedOriginsFlag, 146 utils.IPCDisabledFlag, 147 utils.IPCPathFlag, 148 } 149 150 whisperFlags = []cli.Flag{ 151 utils.WhisperEnabledFlag, 152 utils.WhisperMaxMessageSizeFlag, 153 utils.WhisperMinPOWFlag, 154 } 155 ) 156 157 func init() { 158 // Initialize the CLI app and start Geth 159 app.Action = smc 160 app.HideVersion = true // we have a command to print the version 161 app.Copyright = "Copyright 2017-2018 The Spectrum Author" 162 app.Commands = []cli.Command{ 163 // See chaincmd.go: 164 initCommand, 165 importCommand, 166 exportCommand, 167 copydbCommand, 168 removedbCommand, 169 dumpCommand, 170 // See monitorcmd.go: 171 //monitorCommand, 172 // See accountcmd.go: 173 accountCommand, 174 walletCommand, 175 // See consolecmd.go: 176 consoleCommand, 177 attachCommand, 178 javascriptCommand, 179 // See misccmd.go: 180 //makecacheCommand, 181 //makedagCommand, 182 versionCommand, 183 bugCommand, 184 licenseCommand, 185 // See config.go 186 dumpConfigCommand, 187 // add by liangc 188 securityCommand, 189 } 190 sort.Sort(cli.CommandsByName(app.Commands)) 191 192 app.Flags = append(app.Flags, nodeFlags...) 193 app.Flags = append(app.Flags, rpcFlags...) 194 app.Flags = append(app.Flags, consoleFlags...) 195 app.Flags = append(app.Flags, debug.Flags...) 196 //app.Flags = append(app.Flags, whisperFlags...) 197 198 app.Before = func(ctx *cli.Context) error { 199 // add by liangc : append testnet flag 200 if tn := ctx.GlobalBool(utils.TestnetFlag.Name); tn { 201 fmt.Println("Testnet started.") 202 os.Setenv("TESTNET", "1") 203 } 204 if tn := ctx.GlobalBool(utils.DevnetFlag.Name); tn { 205 fmt.Println("Devnet started.") 206 os.Setenv("DEVNET", "1") 207 } 208 ipc := node.DefaultIPCEndpoint(clientIdentifier) 209 210 if dir := ctx.GlobalString(utils.DataDirFlag.Name); ctx.GlobalIsSet(utils.DataDirFlag.Name) { 211 ipc = node.DefaultIPCEndpointWithDir(dir, clientIdentifier) 212 } 213 os.Setenv("IPCPATH", ipc) 214 215 runtime.GOMAXPROCS(runtime.NumCPU()) 216 if err := debug.Setup(ctx); err != nil { 217 return err 218 } 219 // Start system runtime metrics collection 220 go metrics.CollectProcessMetrics(3 * time.Second) 221 222 utils.SetupNetwork(ctx) 223 return nil 224 } 225 226 app.After = func(ctx *cli.Context) error { 227 debug.Exit() 228 console.Stdin.Close() // Resets terminal mode. 229 return nil 230 } 231 } 232 233 func main() { 234 if err := app.Run(os.Args); err != nil { 235 fmt.Fprintln(os.Stderr, err) 236 os.Exit(1) 237 } 238 } 239 240 func smc(ctx *cli.Context) error { 241 node := makeFullNode(ctx) 242 startNode(ctx, node) 243 node.Wait() 244 return nil 245 } 246 247 // startNode boots up the system node and all registered protocols, after which 248 // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the 249 // miner. 250 func startNode(ctx *cli.Context, stack *node.Node) { 251 // Start up the node itself 252 utils.StartNode(stack) 253 // Unlock any account specifically requested 254 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 255 256 passwords := utils.MakePasswordList(ctx) 257 unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") 258 for i, account := range unlocks { 259 if trimmed := strings.TrimSpace(account); trimmed != "" { 260 unlockAccount(ctx, ks, trimmed, i, passwords) 261 } 262 } 263 // Register wallet event handlers to open and auto-derive wallets 264 events := make(chan accounts.WalletEvent, 16) 265 stack.AccountManager().Subscribe(events) 266 267 go func() { 268 // Create an chain state reader for self-derivation 269 rpcClient, err := stack.Attach() 270 if err != nil { 271 utils.Fatalf("Failed to attach to self: %v", err) 272 } 273 stateReader := ethclient.NewClient(rpcClient) 274 275 // Open any wallets already attached 276 for _, wallet := range stack.AccountManager().Wallets() { 277 if err := wallet.Open(""); err != nil { 278 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 279 } 280 } 281 // Listen for wallet event till termination 282 for event := range events { 283 switch event.Kind { 284 case accounts.WalletArrived: 285 if err := event.Wallet.Open(""); err != nil { 286 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 287 } 288 case accounts.WalletOpened: 289 status, _ := event.Wallet.Status() 290 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 291 292 if event.Wallet.URL().Scheme == "ledger" { 293 event.Wallet.SelfDerive(accounts.DefaultLedgerBaseDerivationPath, stateReader) 294 } else { 295 event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader) 296 } 297 298 case accounts.WalletDropped: 299 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 300 event.Wallet.Close() 301 } 302 } 303 }() 304 // Start auxiliary services if enabled 305 if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { 306 // Mining only makes sense if a full Ethereum node is running 307 var ethereum *eth.Ethereum 308 if err := stack.Service(ðereum); err != nil { 309 utils.Fatalf("ethereum service not running: %v", err) 310 } 311 // Use a reduced number of threads if requested 312 if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > 0 { 313 type threaded interface { 314 SetThreads(threads int) 315 } 316 if th, ok := ethereum.Engine().(threaded); ok { 317 th.SetThreads(threads) 318 } 319 } 320 // Set the gas price to the limits from the CLI and start mining 321 ethereum.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name)) 322 if err := ethereum.StartMining(true); err != nil { 323 utils.Fatalf("Failed to start mining: %v", err) 324 } 325 } 326 }