diff options
Diffstat (limited to 'cmd/gdex/main.go')
-rw-r--r-- | cmd/gdex/main.go | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/cmd/gdex/main.go b/cmd/gdex/main.go new file mode 100644 index 000000000..84a02cca4 --- /dev/null +++ b/cmd/gdex/main.go @@ -0,0 +1,373 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. + +// gdex is the official command-line client for Ethereum. +package main + +import ( + "fmt" + "math" + "os" + godebug "runtime/debug" + "sort" + "strconv" + "strings" + "time" + + "github.com/dexon-foundation/dexon/accounts" + "github.com/dexon-foundation/dexon/accounts/keystore" + "github.com/dexon-foundation/dexon/cmd/utils" + "github.com/dexon-foundation/dexon/console" + "github.com/dexon-foundation/dexon/dex" + "github.com/dexon-foundation/dexon/eth" + "github.com/dexon-foundation/dexon/ethclient" + "github.com/dexon-foundation/dexon/internal/debug" + "github.com/dexon-foundation/dexon/log" + "github.com/dexon-foundation/dexon/metrics" + "github.com/dexon-foundation/dexon/node" + "github.com/elastic/gosigar" + cli "gopkg.in/urfave/cli.v1" +) + +const ( + clientIdentifier = "gdex" // Client identifier to advertise over the network +) + +var ( + // Git SHA1 commit hash of the release (set via linker flags) + gitCommit = "" + // The app that holds all commands and flags. + app = utils.NewApp(gitCommit, "the go-ethereum command line interface") + // flags that configure the node + nodeFlags = []cli.Flag{ + utils.IdentityFlag, + utils.UnlockedAccountFlag, + utils.PasswordFileFlag, + utils.BootnodesFlag, + utils.BootnodesV4Flag, + utils.BootnodesV5Flag, + utils.DataDirFlag, + utils.KeyStoreDirFlag, + utils.NoUSBFlag, + utils.DashboardEnabledFlag, + utils.DashboardAddrFlag, + utils.DashboardPortFlag, + utils.DashboardRefreshFlag, + utils.EthashCacheDirFlag, + utils.EthashCachesInMemoryFlag, + utils.EthashCachesOnDiskFlag, + utils.EthashDatasetDirFlag, + utils.EthashDatasetsInMemoryFlag, + utils.EthashDatasetsOnDiskFlag, + utils.TxPoolLocalsFlag, + utils.TxPoolNoLocalsFlag, + utils.TxPoolJournalFlag, + utils.TxPoolRejournalFlag, + utils.TxPoolPriceLimitFlag, + utils.TxPoolPriceBumpFlag, + utils.TxPoolAccountSlotsFlag, + utils.TxPoolGlobalSlotsFlag, + utils.TxPoolAccountQueueFlag, + utils.TxPoolGlobalQueueFlag, + utils.TxPoolLifetimeFlag, + utils.SyncModeFlag, + utils.GCModeFlag, + utils.LightServFlag, + utils.LightPeersFlag, + utils.LightKDFFlag, + utils.WhitelistFlag, + utils.CacheFlag, + utils.CacheDatabaseFlag, + utils.CacheTrieFlag, + utils.CacheGCFlag, + utils.TrieCacheGenFlag, + utils.ListenPortFlag, + utils.MaxPeersFlag, + utils.MaxPendingPeersFlag, + utils.ProposingEnabledFlag, + utils.MiningEnabledFlag, + utils.MinerThreadsFlag, + utils.MinerLegacyThreadsFlag, + utils.MinerNotifyFlag, + utils.MinerGasTargetFlag, + utils.MinerLegacyGasTargetFlag, + utils.MinerGasLimitFlag, + utils.MinerGasPriceFlag, + utils.MinerLegacyGasPriceFlag, + utils.MinerEtherbaseFlag, + utils.MinerLegacyEtherbaseFlag, + utils.MinerExtraDataFlag, + utils.MinerLegacyExtraDataFlag, + utils.MinerRecommitIntervalFlag, + utils.MinerNoVerfiyFlag, + utils.NATFlag, + utils.NoDiscoverFlag, + utils.DiscoveryV5Flag, + utils.NetrestrictFlag, + utils.NodeKeyFileFlag, + utils.NodeKeyHexFlag, + utils.DeveloperFlag, + utils.DeveloperPeriodFlag, + utils.TestnetFlag, + utils.VMEnableDebugFlag, + utils.NetworkIdFlag, + utils.ConstantinopleOverrideFlag, + utils.RPCCORSDomainFlag, + utils.RPCVirtualHostsFlag, + utils.EthStatsURLFlag, + utils.MetricsEnabledFlag, + utils.FakePoWFlag, + utils.NoCompactionFlag, + utils.GpoBlocksFlag, + utils.GpoPercentileFlag, + utils.EWASMInterpreterFlag, + utils.EVMInterpreterFlag, + configFileFlag, + } + + rpcFlags = []cli.Flag{ + utils.RPCEnabledFlag, + utils.RPCListenAddrFlag, + utils.RPCPortFlag, + utils.RPCApiFlag, + utils.WSEnabledFlag, + utils.WSListenAddrFlag, + utils.WSPortFlag, + utils.WSApiFlag, + utils.WSAllowedOriginsFlag, + utils.IPCDisabledFlag, + utils.IPCPathFlag, + utils.RPCGlobalGasCap, + } + + whisperFlags = []cli.Flag{ + utils.WhisperEnabledFlag, + utils.WhisperMaxMessageSizeFlag, + utils.WhisperMinPOWFlag, + utils.WhisperRestrictConnectionBetweenLightClientsFlag, + } + + metricsFlags = []cli.Flag{ + utils.MetricsEnableInfluxDBFlag, + utils.MetricsInfluxDBEndpointFlag, + utils.MetricsInfluxDBDatabaseFlag, + utils.MetricsInfluxDBUsernameFlag, + utils.MetricsInfluxDBPasswordFlag, + utils.MetricsInfluxDBTagsFlag, + } +) + +func init() { + // Initialize the CLI app and start Geth + app.Action = gdex + app.HideVersion = true // we have a command to print the version + app.Copyright = "Copyright 2013-2018 The go-ethereum Authors" + app.Commands = []cli.Command{ + // See chaincmd.go: + initCommand, + importCommand, + exportCommand, + importPreimagesCommand, + exportPreimagesCommand, + copydbCommand, + removedbCommand, + dumpCommand, + // See monitorcmd.go: + monitorCommand, + // See accountcmd.go: + accountCommand, + walletCommand, + // See consolecmd.go: + consoleCommand, + attachCommand, + javascriptCommand, + // See misccmd.go: + makecacheCommand, + makedagCommand, + versionCommand, + bugCommand, + licenseCommand, + // See config.go + dumpConfigCommand, + } + sort.Sort(cli.CommandsByName(app.Commands)) + + app.Flags = append(app.Flags, nodeFlags...) + app.Flags = append(app.Flags, rpcFlags...) + app.Flags = append(app.Flags, consoleFlags...) + app.Flags = append(app.Flags, debug.Flags...) + app.Flags = append(app.Flags, whisperFlags...) + app.Flags = append(app.Flags, metricsFlags...) + + app.Before = func(ctx *cli.Context) error { + logdir := "" + if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) { + logdir = (&node.Config{DataDir: utils.MakeDataDir(ctx)}).ResolvePath("logs") + } + if err := debug.Setup(ctx, logdir); err != nil { + return err + } + // Cap the cache allowance and tune the garbage collector + var mem gosigar.Mem + if err := mem.Get(); err == nil { + allowance := int(mem.Total / 1024 / 1024 / 3) + if cache := ctx.GlobalInt(utils.CacheFlag.Name); cache > allowance { + log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) + ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(allowance)) + } + } + // Ensure Go's GC ignores the database cache for trigger percentage + cache := ctx.GlobalInt(utils.CacheFlag.Name) + gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024))) + + log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc)) + godebug.SetGCPercent(int(gogc)) + + // Start metrics export if enabled + utils.SetupMetrics(ctx) + + // Start system runtime metrics collection + go metrics.CollectProcessMetrics(3 * time.Second) + + return nil + } + + app.After = func(ctx *cli.Context) error { + debug.Exit() + console.Stdin.Close() // Resets terminal mode. + return nil + } +} + +func main() { + if err := app.Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +// gdex is the main entry point into the system if no special subcommand is ran. +// It creates a default node based on the command line arguments and runs it in +// blocking mode, waiting for it to be shut down. +func gdex(ctx *cli.Context) error { + if args := ctx.Args(); len(args) > 0 { + return fmt.Errorf("invalid command: %q", args[0]) + } + node := makeFullNode(ctx) + startNode(ctx, node) + node.Wait() + return nil +} + +// 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) { + debug.Memsize.Add("node", stack) + + // Start up the node itself + utils.StartNode(stack) + + // Unlock any account specifically requested + ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + + passwords := utils.MakePasswordList(ctx) + unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") + for i, account := range unlocks { + if trimmed := strings.TrimSpace(account); trimmed != "" { + unlockAccount(ctx, ks, trimmed, i, passwords) + } + } + // Register wallet event handlers to open and auto-derive wallets + events := make(chan accounts.WalletEvent, 16) + stack.AccountManager().Subscribe(events) + + go func() { + // Create a chain state reader for self-derivation + rpcClient, err := stack.Attach() + if err != nil { + utils.Fatalf("Failed to attach to self: %v", err) + } + stateReader := ethclient.NewClient(rpcClient) + + // 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) + + derivationPath := accounts.DefaultBaseDerivationPath + if event.Wallet.URL().Scheme == "ledger" { + derivationPath = accounts.DefaultLedgerBaseDerivationPath + } + event.Wallet.SelfDerive(derivationPath, stateReader) + + case accounts.WalletDropped: + log.Info("Old wallet dropped", "url", event.Wallet.URL()) + event.Wallet.Close() + } + } + }() + // Start auxiliary services if enabled + if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { + // Mining only makes sense if a full Ethereum node is running + if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { + utils.Fatalf("Light clients do not support mining") + } + var ethereum *eth.Ethereum + if err := stack.Service(ðereum); err != nil { + utils.Fatalf("Ethereum service not running: %v", err) + } + // Set the gas price to the limits from the CLI and start mining + gasprice := utils.GlobalBig(ctx, utils.MinerLegacyGasPriceFlag.Name) + if ctx.IsSet(utils.MinerGasPriceFlag.Name) { + gasprice = utils.GlobalBig(ctx, utils.MinerGasPriceFlag.Name) + } + ethereum.TxPool().SetGasPrice(gasprice) + + threads := ctx.GlobalInt(utils.MinerLegacyThreadsFlag.Name) + if ctx.GlobalIsSet(utils.MinerThreadsFlag.Name) { + threads = ctx.GlobalInt(utils.MinerThreadsFlag.Name) + } + if err := ethereum.StartMining(threads); err != nil { + utils.Fatalf("Failed to start mining: %v", err) + } + } + + if ctx.GlobalBool(utils.ProposingEnabledFlag.Name) { + if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { + utils.Fatalf("Light clients do not support proposing") + } + var dexon *dex.Dexon + if err := stack.Service(&dexon); err != nil { + utils.Fatalf("Dexon service not running: %v", err) + } + if err := dexon.StartProposing(); err != nil { + utils.Fatalf("Failed to string proposing: %v", err) + } + } +} |