diff options
author | Determinant <[email protected]> | 2020-06-28 14:47:41 -0400 |
---|---|---|
committer | Determinant <[email protected]> | 2020-06-28 14:47:41 -0400 |
commit | d235e2c6a5788ec4a6cff15a16f56b38a3876a0d (patch) | |
tree | 5f2727f7a50ee5840f889c82776d3a30a88dd59b /cmd/geth | |
parent | 13ebd8bd9468e9d769d598b0ca2afb72ba78cb97 (diff) |
...
Diffstat (limited to 'cmd/geth')
-rw-r--r-- | cmd/geth/chaincmd.go | 559 | ||||
-rw-r--r-- | cmd/geth/config.go | 211 | ||||
-rw-r--r-- | cmd/geth/consolecmd.go | 220 | ||||
-rw-r--r-- | cmd/geth/main.go | 403 | ||||
-rw-r--r-- | cmd/geth/misccmd.go | 142 | ||||
-rw-r--r-- | cmd/geth/retesteth.go | 891 | ||||
-rw-r--r-- | cmd/geth/retesteth_copypaste.go | 148 | ||||
-rw-r--r-- | cmd/geth/usage.go | 370 |
8 files changed, 0 insertions, 2944 deletions
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go deleted file mode 100644 index 97b5870..0000000 --- a/cmd/geth/chaincmd.go +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright 2015 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/>. - -package geth - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "runtime" - "strconv" - "sync/atomic" - "time" - - "github.com/ava-labs/coreth/cmd/utils" - "github.com/ava-labs/go-ethereum/common" - "github.com/ava-labs/go-ethereum/console" - "github.com/ava-labs/go-ethereum/core" - "github.com/ava-labs/go-ethereum/core/rawdb" - "github.com/ava-labs/go-ethereum/core/state" - "github.com/ava-labs/go-ethereum/core/types" - "github.com/ava-labs/go-ethereum/eth/downloader" - "github.com/ava-labs/go-ethereum/event" - "github.com/ava-labs/go-ethereum/log" - "github.com/ava-labs/go-ethereum/trie" - "gopkg.in/urfave/cli.v1" -) - -var ( - initCommand = cli.Command{ - Action: utils.MigrateFlags(initGenesis), - Name: "init", - Usage: "Bootstrap and initialize a new genesis block", - ArgsUsage: "<genesisPath>", - Flags: []cli.Flag{ - utils.DataDirFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - Description: ` -The init command initializes a new genesis block and definition for the network. -This is a destructive action and changes the network in which you will be -participating. - -It expects the genesis file as argument.`, - } - importCommand = cli.Command{ - Action: utils.MigrateFlags(importChain), - Name: "import", - Usage: "Import a blockchain file", - ArgsUsage: "<filename> (<filename 2> ... <filename N>) ", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.CacheFlag, - utils.SyncModeFlag, - utils.GCModeFlag, - utils.CacheDatabaseFlag, - utils.CacheGCFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - Description: ` -The import command imports blocks from an RLP-encoded form. The form can be one file -with several RLP-encoded blocks, or several files can be used. - -If only one file is used, import error will result in failure. If several files are used, -processing will proceed even if an individual RLP-file import failure occurs.`, - } - exportCommand = cli.Command{ - Action: utils.MigrateFlags(exportChain), - Name: "export", - Usage: "Export blockchain into file", - ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.CacheFlag, - utils.SyncModeFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - Description: ` -Requires a first argument of the file to write to. -Optional second and third arguments control the first and -last block to write. In this mode, the file will be appended -if already existing. If the file ends with .gz, the output will -be gzipped.`, - } - importPreimagesCommand = cli.Command{ - Action: utils.MigrateFlags(importPreimages), - Name: "import-preimages", - Usage: "Import the preimage database from an RLP stream", - ArgsUsage: "<datafile>", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.CacheFlag, - utils.SyncModeFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - Description: ` - The import-preimages command imports hash preimages from an RLP encoded stream.`, - } - exportPreimagesCommand = cli.Command{ - Action: utils.MigrateFlags(exportPreimages), - Name: "export-preimages", - Usage: "Export the preimage database into an RLP stream", - ArgsUsage: "<dumpfile>", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.CacheFlag, - utils.SyncModeFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - Description: ` -The export-preimages command export hash preimages to an RLP encoded stream`, - } - copydbCommand = cli.Command{ - Action: utils.MigrateFlags(copyDb), - Name: "copydb", - Usage: "Create a local chain from a target chaindata folder", - ArgsUsage: "<sourceChaindataDir>", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.CacheFlag, - utils.SyncModeFlag, - utils.FakePoWFlag, - utils.TestnetFlag, - utils.RinkebyFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - Description: ` -The first argument must be the directory containing the blockchain to download from`, - } - removedbCommand = cli.Command{ - Action: utils.MigrateFlags(removeDB), - Name: "removedb", - Usage: "Remove blockchain and state databases", - ArgsUsage: " ", - Flags: []cli.Flag{ - utils.DataDirFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - Description: ` -Remove blockchain and state databases`, - } - dumpCommand = cli.Command{ - Action: utils.MigrateFlags(dump), - Name: "dump", - Usage: "Dump a specific block from storage", - ArgsUsage: "[<blockHash> | <blockNum>]...", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.CacheFlag, - utils.SyncModeFlag, - utils.IterativeOutputFlag, - utils.ExcludeCodeFlag, - utils.ExcludeStorageFlag, - utils.IncludeIncompletesFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - Description: ` -The arguments are interpreted as block numbers or hashes. -Use "ethereum dump 0" to dump the genesis block.`, - } - inspectCommand = cli.Command{ - Action: utils.MigrateFlags(inspect), - Name: "inspect", - Usage: "Inspect the storage size for each type of data in the database", - ArgsUsage: " ", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.AncientFlag, - utils.CacheFlag, - utils.TestnetFlag, - utils.RinkebyFlag, - utils.GoerliFlag, - utils.SyncModeFlag, - }, - Category: "BLOCKCHAIN COMMANDS", - } -) - -// initGenesis will initialise the given JSON format genesis file and writes it as -// the zero'd block (i.e. genesis) or will fail hard if it can't succeed. -func initGenesis(ctx *cli.Context) error { - // Make sure we have a valid genesis JSON - genesisPath := ctx.Args().First() - if len(genesisPath) == 0 { - utils.Fatalf("Must supply path to genesis JSON file") - } - file, err := os.Open(genesisPath) - if err != nil { - utils.Fatalf("Failed to read genesis file: %v", err) - } - defer file.Close() - - genesis := new(core.Genesis) - if err := json.NewDecoder(file).Decode(genesis); err != nil { - utils.Fatalf("invalid genesis file: %v", err) - } - // Open an initialise both full and light databases - stack := makeFullNode(ctx) - defer stack.Close() - - for _, name := range []string{"chaindata", "lightchaindata"} { - chaindb, err := stack.OpenDatabase(name, 0, 0, "") - if err != nil { - utils.Fatalf("Failed to open database: %v", err) - } - _, hash, err := core.SetupGenesisBlock(chaindb, genesis) - if err != nil { - utils.Fatalf("Failed to write genesis block: %v", err) - } - chaindb.Close() - log.Info("Successfully wrote genesis state", "database", name, "hash", hash) - } - return nil -} - -func importChain(ctx *cli.Context) error { - if len(ctx.Args()) < 1 { - utils.Fatalf("This command requires an argument.") - } - stack := makeFullNode(ctx) - defer stack.Close() - - chain, db := utils.MakeChain(ctx, stack) - defer db.Close() - - // Start periodically gathering memory profiles - var peakMemAlloc, peakMemSys uint64 - go func() { - stats := new(runtime.MemStats) - for { - runtime.ReadMemStats(stats) - if atomic.LoadUint64(&peakMemAlloc) < stats.Alloc { - atomic.StoreUint64(&peakMemAlloc, stats.Alloc) - } - if atomic.LoadUint64(&peakMemSys) < stats.Sys { - atomic.StoreUint64(&peakMemSys, stats.Sys) - } - time.Sleep(5 * time.Second) - } - }() - // Import the chain - start := time.Now() - - if len(ctx.Args()) == 1 { - if err := utils.ImportChain(chain, ctx.Args().First()); err != nil { - log.Error("Import error", "err", err) - } - } else { - for _, arg := range ctx.Args() { - if err := utils.ImportChain(chain, arg); err != nil { - log.Error("Import error", "file", arg, "err", err) - } - } - } - chain.Stop() - fmt.Printf("Import done in %v.\n\n", time.Since(start)) - - // Output pre-compaction stats mostly to see the import trashing - stats, err := db.Stat("leveldb.stats") - if err != nil { - utils.Fatalf("Failed to read database stats: %v", err) - } - fmt.Println(stats) - - ioStats, err := db.Stat("leveldb.iostats") - if err != nil { - utils.Fatalf("Failed to read database iostats: %v", err) - } - fmt.Println(ioStats) - - // Print the memory statistics used by the importing - mem := new(runtime.MemStats) - runtime.ReadMemStats(mem) - - fmt.Printf("Object memory: %.3f MB current, %.3f MB peak\n", float64(mem.Alloc)/1024/1024, float64(atomic.LoadUint64(&peakMemAlloc))/1024/1024) - fmt.Printf("System memory: %.3f MB current, %.3f MB peak\n", float64(mem.Sys)/1024/1024, float64(atomic.LoadUint64(&peakMemSys))/1024/1024) - fmt.Printf("Allocations: %.3f million\n", float64(mem.Mallocs)/1000000) - fmt.Printf("GC pause: %v\n\n", time.Duration(mem.PauseTotalNs)) - - if ctx.GlobalBool(utils.NoCompactionFlag.Name) { - return nil - } - - // Compact the entire database to more accurately measure disk io and print the stats - start = time.Now() - fmt.Println("Compacting entire database...") - if err = db.Compact(nil, nil); err != nil { - utils.Fatalf("Compaction failed: %v", err) - } - fmt.Printf("Compaction done in %v.\n\n", time.Since(start)) - - stats, err = db.Stat("leveldb.stats") - if err != nil { - utils.Fatalf("Failed to read database stats: %v", err) - } - fmt.Println(stats) - - ioStats, err = db.Stat("leveldb.iostats") - if err != nil { - utils.Fatalf("Failed to read database iostats: %v", err) - } - fmt.Println(ioStats) - return nil -} - -func exportChain(ctx *cli.Context) error { - if len(ctx.Args()) < 1 { - utils.Fatalf("This command requires an argument.") - } - stack := makeFullNode(ctx) - defer stack.Close() - - chain, _ := utils.MakeChain(ctx, stack) - start := time.Now() - - var err error - fp := ctx.Args().First() - if len(ctx.Args()) < 3 { - err = utils.ExportChain(chain, fp) - } else { - // This can be improved to allow for numbers larger than 9223372036854775807 - first, ferr := strconv.ParseInt(ctx.Args().Get(1), 10, 64) - last, lerr := strconv.ParseInt(ctx.Args().Get(2), 10, 64) - if ferr != nil || lerr != nil { - utils.Fatalf("Export error in parsing parameters: block number not an integer\n") - } - if first < 0 || last < 0 { - utils.Fatalf("Export error: block number must be greater than 0\n") - } - err = utils.ExportAppendChain(chain, fp, uint64(first), uint64(last)) - } - - if err != nil { - utils.Fatalf("Export error: %v\n", err) - } - fmt.Printf("Export done in %v\n", time.Since(start)) - return nil -} - -// importPreimages imports preimage data from the specified file. -func importPreimages(ctx *cli.Context) error { - if len(ctx.Args()) < 1 { - utils.Fatalf("This command requires an argument.") - } - stack := makeFullNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack) - start := time.Now() - - if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil { - utils.Fatalf("Import error: %v\n", err) - } - fmt.Printf("Import done in %v\n", time.Since(start)) - return nil -} - -// exportPreimages dumps the preimage data to specified json file in streaming way. -func exportPreimages(ctx *cli.Context) error { - if len(ctx.Args()) < 1 { - utils.Fatalf("This command requires an argument.") - } - stack := makeFullNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack) - start := time.Now() - - if err := utils.ExportPreimages(db, ctx.Args().First()); err != nil { - utils.Fatalf("Export error: %v\n", err) - } - fmt.Printf("Export done in %v\n", time.Since(start)) - return nil -} - -func copyDb(ctx *cli.Context) error { - // Ensure we have a source chain directory to copy - if len(ctx.Args()) < 1 { - utils.Fatalf("Source chaindata directory path argument missing") - } - if len(ctx.Args()) < 2 { - utils.Fatalf("Source ancient chain directory path argument missing") - } - // Initialize a new chain for the running node to sync into - stack := makeFullNode(ctx) - defer stack.Close() - - chain, chainDb := utils.MakeChain(ctx, stack) - syncMode := *utils.GlobalTextMarshaler(ctx, utils.SyncModeFlag.Name).(*downloader.SyncMode) - - var syncBloom *trie.SyncBloom - if syncMode == downloader.FastSync { - syncBloom = trie.NewSyncBloom(uint64(ctx.GlobalInt(utils.CacheFlag.Name)/2), chainDb) - } - dl := downloader.New(0, chainDb, syncBloom, new(event.TypeMux), chain, nil, nil) - - // Create a source peer to satisfy downloader requests from - db, err := rawdb.NewLevelDBDatabaseWithFreezer(ctx.Args().First(), ctx.GlobalInt(utils.CacheFlag.Name)/2, 256, ctx.Args().Get(1), "") - if err != nil { - return err - } - hc, err := core.NewHeaderChain(db, chain.Config(), chain.Engine(), func() bool { return false }) - if err != nil { - return err - } - peer := downloader.NewFakePeer("local", db, hc, dl) - if err = dl.RegisterPeer("local", 63, peer); err != nil { - return err - } - // Synchronise with the simulated peer - start := time.Now() - - currentHeader := hc.CurrentHeader() - if err = dl.Synchronise("local", currentHeader.Hash(), hc.GetTd(currentHeader.Hash(), currentHeader.Number.Uint64()), syncMode); err != nil { - return err - } - for dl.Synchronising() { - time.Sleep(10 * time.Millisecond) - } - fmt.Printf("Database copy done in %v\n", time.Since(start)) - - // Compact the entire database to remove any sync overhead - start = time.Now() - fmt.Println("Compacting entire database...") - if err = db.Compact(nil, nil); err != nil { - utils.Fatalf("Compaction failed: %v", err) - } - fmt.Printf("Compaction done in %v.\n\n", time.Since(start)) - return nil -} - -func removeDB(ctx *cli.Context) error { - stack, config := makeConfigNode(ctx) - - // Remove the full node state database - path := stack.ResolvePath("chaindata") - if common.FileExist(path) { - confirmAndRemoveDB(path, "full node state database") - } else { - log.Info("Full node state database missing", "path", path) - } - // Remove the full node ancient database - path = config.Eth.DatabaseFreezer - switch { - case path == "": - path = filepath.Join(stack.ResolvePath("chaindata"), "ancient") - case !filepath.IsAbs(path): - path = config.Node.ResolvePath(path) - } - if common.FileExist(path) { - confirmAndRemoveDB(path, "full node ancient database") - } else { - log.Info("Full node ancient database missing", "path", path) - } - // Remove the light node database - path = stack.ResolvePath("lightchaindata") - if common.FileExist(path) { - confirmAndRemoveDB(path, "light node database") - } else { - log.Info("Light node database missing", "path", path) - } - return nil -} - -// confirmAndRemoveDB prompts the user for a last confirmation and removes the -// folder if accepted. -func confirmAndRemoveDB(database string, kind string) { - confirm, err := console.Stdin.PromptConfirm(fmt.Sprintf("Remove %s (%s)?", kind, database)) - switch { - case err != nil: - utils.Fatalf("%v", err) - case !confirm: - log.Info("Database deletion skipped", "path", database) - default: - start := time.Now() - filepath.Walk(database, func(path string, info os.FileInfo, err error) error { - // If we're at the top level folder, recurse into - if path == database { - return nil - } - // Delete all the files, but not subfolders - if !info.IsDir() { - os.Remove(path) - return nil - } - return filepath.SkipDir - }) - log.Info("Database successfully deleted", "path", database, "elapsed", common.PrettyDuration(time.Since(start))) - } -} - -func dump(ctx *cli.Context) error { - stack := makeFullNode(ctx) - defer stack.Close() - - chain, chainDb := utils.MakeChain(ctx, stack) - defer chainDb.Close() - for _, arg := range ctx.Args() { - var block *types.Block - if hashish(arg) { - block = chain.GetBlockByHash(common.HexToHash(arg)) - } else { - num, _ := strconv.Atoi(arg) - block = chain.GetBlockByNumber(uint64(num)) - } - if block == nil { - fmt.Println("{}") - utils.Fatalf("block not found") - } else { - state, err := state.New(block.Root(), state.NewDatabase(chainDb)) - if err != nil { - utils.Fatalf("could not create new state: %v", err) - } - excludeCode := ctx.Bool(utils.ExcludeCodeFlag.Name) - excludeStorage := ctx.Bool(utils.ExcludeStorageFlag.Name) - includeMissing := ctx.Bool(utils.IncludeIncompletesFlag.Name) - if ctx.Bool(utils.IterativeOutputFlag.Name) { - state.IterativeDump(excludeCode, excludeStorage, !includeMissing, json.NewEncoder(os.Stdout)) - } else { - if includeMissing { - fmt.Printf("If you want to include accounts with missing preimages, you need iterative output, since" + - " otherwise the accounts will overwrite each other in the resulting mapping.") - } - fmt.Printf("%v %s\n", includeMissing, state.Dump(excludeCode, excludeStorage, false)) - } - } - } - return nil -} - -func inspect(ctx *cli.Context) error { - node, _ := makeConfigNode(ctx) - defer node.Close() - - _, chainDb := utils.MakeChain(ctx, node) - defer chainDb.Close() - - return rawdb.InspectDatabase(chainDb) -} - -// hashish returns true for strings that look like hashes. -func hashish(x string) bool { - _, err := strconv.Atoi(x) - return err != nil -} diff --git a/cmd/geth/config.go b/cmd/geth/config.go deleted file mode 100644 index b3dc833..0000000 --- a/cmd/geth/config.go +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2017 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/>. - -package geth - -import ( - "bufio" - "errors" - "fmt" - "os" - "reflect" - "unicode" - - cli "gopkg.in/urfave/cli.v1" - - "github.com/ava-labs/coreth/cmd/utils" - "github.com/ava-labs/go-ethereum/dashboard" - "github.com/ava-labs/coreth/eth" - "github.com/ava-labs/coreth/node" - "github.com/ava-labs/go-ethereum/params" - whisper "github.com/ava-labs/go-ethereum/whisper/whisperv6" - "github.com/naoina/toml" -) - -var ( - dumpConfigCommand = cli.Command{ - Action: utils.MigrateFlags(dumpConfig), - Name: "dumpconfig", - Usage: "Show configuration values", - ArgsUsage: "", - Flags: append(append(nodeFlags, rpcFlags...), whisperFlags...), - Category: "MISCELLANEOUS COMMANDS", - Description: `The dumpconfig command shows configuration values.`, - } - - configFileFlag = cli.StringFlag{ - Name: "config", - Usage: "TOML configuration file", - } -) - -// These settings ensure that TOML keys use the same names as Go struct fields. -var tomlSettings = toml.Config{ - NormFieldName: func(rt reflect.Type, key string) string { - return key - }, - FieldToKey: func(rt reflect.Type, field string) string { - return field - }, - MissingField: func(rt reflect.Type, field string) error { - link := "" - if unicode.IsUpper(rune(rt.Name()[0])) && rt.PkgPath() != "main" { - link = fmt.Sprintf(", see https://godoc.org/%s#%s for available fields", rt.PkgPath(), rt.Name()) - } - return fmt.Errorf("field '%s' is not defined in %s%s", field, rt.String(), link) - }, -} - -type ethstatsConfig struct { - URL string `toml:",omitempty"` -} - -type gethConfig struct { - Eth eth.Config - Shh whisper.Config - Node node.Config - Ethstats ethstatsConfig - Dashboard dashboard.Config -} - -func loadConfig(file string, cfg *gethConfig) error { - f, err := os.Open(file) - if err != nil { - return err - } - defer f.Close() - - err = tomlSettings.NewDecoder(bufio.NewReader(f)).Decode(cfg) - // Add file name to errors that have a line number. - if _, ok := err.(*toml.LineError); ok { - err = errors.New(file + ", " + err.Error()) - } - return err -} - -func defaultNodeConfig() node.Config { - cfg := node.DefaultConfig - cfg.Name = clientIdentifier - cfg.Version = params.VersionWithCommit(gitCommit, gitDate) - cfg.HTTPModules = append(cfg.HTTPModules, "eth", "shh") - cfg.WSModules = append(cfg.WSModules, "eth", "shh") - cfg.IPCPath = "geth.ipc" - return cfg -} - -func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { - // Load defaults. - cfg := gethConfig{ - Eth: eth.MyDefaultConfig(), - Shh: whisper.DefaultConfig, - Node: defaultNodeConfig(), - Dashboard: dashboard.DefaultConfig, - } - - // Load config file. - if file := ctx.GlobalString(configFileFlag.Name); file != "" { - if err := loadConfig(file, &cfg); err != nil { - utils.Fatalf("%v", err) - } - } - - // Apply flags. - utils.SetNodeConfig(ctx, &cfg.Node) - stack, err := node.New(&cfg.Node) - if err != nil { - utils.Fatalf("Failed to create the protocol stack: %v", err) - } - utils.SetEthConfig(ctx, stack, &cfg.Eth) - if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) { - cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name) - } - utils.SetShhConfig(ctx, stack, &cfg.Shh) - utils.SetDashboardConfig(ctx, &cfg.Dashboard) - - return stack, cfg -} - -// enableWhisper returns true in case one of the whisper flags is set. -func enableWhisper(ctx *cli.Context) bool { - for _, flag := range whisperFlags { - if ctx.GlobalIsSet(flag.GetName()) { - return true - } - } - return false -} - -func makeFullNode(ctx *cli.Context) *node.Node { - stack, cfg := makeConfigNode(ctx) - utils.RegisterEthService(stack, &cfg.Eth) - - if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) { - utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit) - } - // Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode - shhEnabled := enableWhisper(ctx) - shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name) - if shhEnabled || shhAutoEnabled { - if ctx.GlobalIsSet(utils.WhisperMaxMessageSizeFlag.Name) { - cfg.Shh.MaxMessageSize = uint32(ctx.Int(utils.WhisperMaxMessageSizeFlag.Name)) - } - if ctx.GlobalIsSet(utils.WhisperMinPOWFlag.Name) { - cfg.Shh.MinimumAcceptedPOW = ctx.Float64(utils.WhisperMinPOWFlag.Name) - } - if ctx.GlobalIsSet(utils.WhisperRestrictConnectionBetweenLightClientsFlag.Name) { - cfg.Shh.RestrictConnectionBetweenLightClients = true - } - utils.RegisterShhService(stack, &cfg.Shh) - } - // Configure GraphQL if requested - if ctx.GlobalIsSet(utils.GraphQLEnabledFlag.Name) { - utils.RegisterGraphQLService(stack, cfg.Node.GraphQLEndpoint(), cfg.Node.GraphQLCors, cfg.Node.GraphQLVirtualHosts, cfg.Node.HTTPTimeouts) - } - // Add the Ethereum Stats daemon if requested. - if cfg.Ethstats.URL != "" { - utils.RegisterEthStatsService(stack, cfg.Ethstats.URL) - } - return stack -} - -// dumpConfig is the dumpconfig command. -func dumpConfig(ctx *cli.Context) error { - _, cfg := makeConfigNode(ctx) - comment := "" - - if cfg.Eth.Genesis != nil { - cfg.Eth.Genesis = nil - comment += "# Note: this config doesn't contain the genesis block.\n\n" - } - - out, err := tomlSettings.Marshal(&cfg) - if err != nil { - return err - } - - dump := os.Stdout - if ctx.NArg() > 0 { - dump, err = os.OpenFile(ctx.Args().Get(0), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - return err - } - defer dump.Close() - } - dump.WriteString(comment) - dump.Write(out) - - return nil -} diff --git a/cmd/geth/consolecmd.go b/cmd/geth/consolecmd.go deleted file mode 100644 index 57ea2c9..0000000 --- a/cmd/geth/consolecmd.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2016 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/>. - -package geth - -import ( - "fmt" - "os" - "os/signal" - "path/filepath" - "strings" - "syscall" - - "github.com/ava-labs/coreth/cmd/utils" - "github.com/ava-labs/go-ethereum/console" - "github.com/ava-labs/coreth/node" - "github.com/ava-labs/go-ethereum/rpc" - "gopkg.in/urfave/cli.v1" -) - -var ( - consoleFlags = []cli.Flag{utils.JSpathFlag, utils.ExecFlag, utils.PreloadJSFlag} - - consoleCommand = cli.Command{ - Action: utils.MigrateFlags(localConsole), - Name: "console", - Usage: "Start an interactive JavaScript environment", - Flags: append(append(append(nodeFlags, rpcFlags...), consoleFlags...), whisperFlags...), - Category: "CONSOLE COMMANDS", - Description: ` -The Geth console is an interactive shell for the JavaScript runtime environment -which exposes a node admin interface as well as the Ðapp JavaScript API. -See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console.`, - } - - attachCommand = cli.Command{ - Action: utils.MigrateFlags(remoteConsole), - Name: "attach", - Usage: "Start an interactive JavaScript environment (connect to node)", - ArgsUsage: "[endpoint]", - Flags: append(consoleFlags, utils.DataDirFlag), - Category: "CONSOLE COMMANDS", - Description: ` -The Geth console is an interactive shell for the JavaScript runtime environment -which exposes a node admin interface as well as the Ðapp JavaScript API. -See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console. -This command allows to open a console on a running geth node.`, - } - - javascriptCommand = cli.Command{ - Action: utils.MigrateFlags(ephemeralConsole), - Name: "js", - Usage: "Execute the specified JavaScript files", - ArgsUsage: "<jsfile> [jsfile...]", - Flags: append(nodeFlags, consoleFlags...), - Category: "CONSOLE COMMANDS", - Description: ` -The JavaScript VM exposes a node admin interface as well as the Ðapp -JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console`, - } -) - -// localConsole starts a new geth node, attaching a JavaScript console to it at the -// same time. -func localConsole(ctx *cli.Context) error { - // Create and start the node based on the CLI flags - node := makeFullNode(ctx) - startNode(ctx, node) - defer node.Close() - - // Attach to the newly started node and start the JavaScript console - client, err := node.Attach() - if err != nil { - utils.Fatalf("Failed to attach to the inproc geth: %v", err) - } - config := console.Config{ - DataDir: utils.MakeDataDir(ctx), - DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), - Client: client, - Preload: utils.MakeConsolePreloads(ctx), - } - - console, err := console.New(config) - if err != nil { - utils.Fatalf("Failed to start the JavaScript console: %v", err) - } - defer console.Stop(false) - - // If only a short execution was requested, evaluate and return - if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" { - console.Evaluate(script) - return nil - } - // Otherwise print the welcome screen and enter interactive mode - console.Welcome() - console.Interactive() - - return nil -} - -// remoteConsole will connect to a remote geth instance, attaching a JavaScript -// console to it. -func remoteConsole(ctx *cli.Context) error { - // Attach to a remotely running geth instance and start the JavaScript console - endpoint := ctx.Args().First() - if endpoint == "" { - path := node.DefaultDataDir() - if ctx.GlobalIsSet(utils.DataDirFlag.Name) { - path = ctx.GlobalString(utils.DataDirFlag.Name) - } - if path != "" { - if ctx.GlobalBool(utils.TestnetFlag.Name) { - path = filepath.Join(path, "testnet") - } else if ctx.GlobalBool(utils.RinkebyFlag.Name) { - path = filepath.Join(path, "rinkeby") - } - } - endpoint = fmt.Sprintf("%s/geth.ipc", path) - } - client, err := dialRPC(endpoint) - if err != nil { - utils.Fatalf("Unable to attach to remote geth: %v", err) - } - config := console.Config{ - DataDir: utils.MakeDataDir(ctx), - DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), - Client: client, - Preload: utils.MakeConsolePreloads(ctx), - } - - console, err := console.New(config) - if err != nil { - utils.Fatalf("Failed to start the JavaScript console: %v", err) - } - defer console.Stop(false) - - if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" { - console.Evaluate(script) - return nil - } - - // Otherwise print the welcome screen and enter interactive mode - console.Welcome() - console.Interactive() - - return nil -} - -// dialRPC returns a RPC client which connects to the given endpoint. -// The check for empty endpoint implements the defaulting logic -// for "geth attach" and "geth monitor" with no argument. -func dialRPC(endpoint string) (*rpc.Client, error) { - if endpoint == "" { - endpoint = node.DefaultIPCEndpoint(clientIdentifier) - } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { - // Backwards compatibility with geth < 1.5 which required - // these prefixes. - endpoint = endpoint[4:] - } - return rpc.Dial(endpoint) -} - -// ephemeralConsole starts a new geth node, attaches an ephemeral JavaScript -// console to it, executes each of the files specified as arguments and tears -// everything down. -func ephemeralConsole(ctx *cli.Context) error { - // Create and start the node based on the CLI flags - node := makeFullNode(ctx) - startNode(ctx, node) - defer node.Close() - - // Attach to the newly started node and start the JavaScript console - client, err := node.Attach() - if err != nil { - utils.Fatalf("Failed to attach to the inproc geth: %v", err) - } - config := console.Config{ - DataDir: utils.MakeDataDir(ctx), - DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), - Client: client, - Preload: utils.MakeConsolePreloads(ctx), - } - - console, err := console.New(config) - if err != nil { - utils.Fatalf("Failed to start the JavaScript console: %v", err) - } - defer console.Stop(false) - - // Evaluate each of the specified JavaScript files - for _, file := range ctx.Args() { - if err = console.Execute(file); err != nil { - utils.Fatalf("Failed to execute %s: %v", file, err) - } - } - // Wait for pending callbacks, but stop for Ctrl-C. - abort := make(chan os.Signal, 1) - signal.Notify(abort, syscall.SIGINT, syscall.SIGTERM) - - go func() { - <-abort - os.Exit(0) - }() - console.Stop(true) - - return nil -} diff --git a/cmd/geth/main.go b/cmd/geth/main.go deleted file mode 100644 index 82ad47e..0000000 --- a/cmd/geth/main.go +++ /dev/null @@ -1,403 +0,0 @@ -// 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/>. - -// geth is the official command-line client for Ethereum. -package geth - -import ( - "fmt" - "math" - "os" - "runtime" - godebug "runtime/debug" - "sort" - "strconv" - "time" - - "github.com/elastic/gosigar" - "github.com/ava-labs/coreth/cmd/utils" - "github.com/ava-labs/go-ethereum/common" - "github.com/ava-labs/go-ethereum/console" - "github.com/ava-labs/coreth/eth" - "github.com/ava-labs/go-ethereum/eth/downloader" - "github.com/ava-labs/go-ethereum/ethclient" - "github.com/ava-labs/coreth/internal/debug" - "github.com/ava-labs/go-ethereum/les" - "github.com/ava-labs/go-ethereum/log" - "github.com/ava-labs/go-ethereum/metrics" - "github.com/ava-labs/coreth/node" - cli "gopkg.in/urfave/cli.v1" -) - -const ( - clientIdentifier = "geth" // Client identifier to advertise over the network -) - -var ( - // Git SHA1 commit hash of the release (set via linker flags) - gitCommit = "" - gitDate = "" - // The App that holds all commands and flags. - App = utils.NewApp(gitCommit, gitDate, "the go-ethereum command line interface") - // flags that configure the node - nodeFlags = []cli.Flag{ - utils.IdentityFlag, - utils.PasswordFileFlag, - utils.BootnodesFlag, - utils.BootnodesV4Flag, - utils.BootnodesV5Flag, - utils.DataDirFlag, - utils.AncientFlag, - utils.KeyStoreDirFlag, - utils.ExternalSignerFlag, - utils.NoUSBFlag, - utils.SmartCardDaemonPathFlag, - 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.ExitWhenSyncedFlag, - utils.GCModeFlag, - utils.LightServeFlag, - utils.LightLegacyServFlag, - utils.LightIngressFlag, - utils.LightEgressFlag, - utils.LightMaxPeersFlag, - utils.LightLegacyPeersFlag, - utils.LightKDFFlag, - utils.UltraLightServersFlag, - utils.UltraLightFractionFlag, - utils.UltraLightOnlyAnnounceFlag, - utils.WhitelistFlag, - utils.CacheFlag, - utils.CacheDatabaseFlag, - utils.CacheTrieFlag, - utils.CacheGCFlag, - utils.CacheNoPrefetchFlag, - utils.ListenPortFlag, - utils.MaxPeersFlag, - utils.MaxPendingPeersFlag, - 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.RinkebyFlag, - utils.GoerliFlag, - utils.VMEnableDebugFlag, - utils.NetworkIdFlag, - utils.EthStatsURLFlag, - utils.FakePoWFlag, - utils.NoCompactionFlag, - utils.GpoBlocksFlag, - utils.GpoPercentileFlag, - utils.EWASMInterpreterFlag, - utils.EVMInterpreterFlag, - configFileFlag, - } - - rpcFlags = []cli.Flag{ - utils.RPCEnabledFlag, - utils.RPCListenAddrFlag, - utils.RPCPortFlag, - utils.RPCCORSDomainFlag, - utils.RPCVirtualHostsFlag, - utils.GraphQLEnabledFlag, - utils.GraphQLListenAddrFlag, - utils.GraphQLPortFlag, - utils.GraphQLCORSDomainFlag, - utils.GraphQLVirtualHostsFlag, - utils.RPCApiFlag, - utils.WSEnabledFlag, - utils.WSListenAddrFlag, - utils.WSPortFlag, - utils.WSApiFlag, - utils.WSAllowedOriginsFlag, - utils.IPCDisabledFlag, - utils.IPCPathFlag, - utils.InsecureUnlockAllowedFlag, - utils.RPCGlobalGasCap, - } - - whisperFlags = []cli.Flag{ - utils.WhisperEnabledFlag, - utils.WhisperMaxMessageSizeFlag, - utils.WhisperMinPOWFlag, - utils.WhisperRestrictConnectionBetweenLightClientsFlag, - } - - metricsFlags = []cli.Flag{ - utils.MetricsEnabledFlag, - utils.MetricsEnabledExpensiveFlag, - utils.MetricsEnableInfluxDBFlag, - utils.MetricsInfluxDBEndpointFlag, - utils.MetricsInfluxDBDatabaseFlag, - utils.MetricsInfluxDBUsernameFlag, - utils.MetricsInfluxDBPasswordFlag, - utils.MetricsInfluxDBTagsFlag, - } -) - -func init() { - // Initialize the CLI App and start Geth - App.Action = geth - App.HideVersion = true // we have a command to print the version - App.Copyright = "Copyright 2013-2019 The go-ethereum Authors" - App.Commands = []cli.Command{ - // See chaincmd.go: - initCommand, - importCommand, - exportCommand, - importPreimagesCommand, - exportPreimagesCommand, - copydbCommand, - removedbCommand, - dumpCommand, - inspectCommand, - // See accountcmd.go: - // See consolecmd.go: - consoleCommand, - attachCommand, - javascriptCommand, - // See misccmd.go: - makecacheCommand, - makedagCommand, - versionCommand, - licenseCommand, - // See config.go - dumpConfigCommand, - // See retesteth.go - retestethCommand, - } - 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 - } - // If we're a full node on mainnet without --cache specified, bump default cache allowance - if ctx.GlobalString(utils.SyncModeFlag.Name) != "light" && !ctx.GlobalIsSet(utils.CacheFlag.Name) && !ctx.GlobalIsSet(utils.NetworkIdFlag.Name) { - // Make sure we're not on any supported preconfigured testnet either - if !ctx.GlobalIsSet(utils.TestnetFlag.Name) && !ctx.GlobalIsSet(utils.RinkebyFlag.Name) && !ctx.GlobalIsSet(utils.GoerliFlag.Name) && !ctx.GlobalIsSet(utils.DeveloperFlag.Name) { - // Nope, we're really on mainnet. Bump that cache up! - log.Info("Bumping default cache on mainnet", "provided", ctx.GlobalInt(utils.CacheFlag.Name), "updated", 4096) - ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(4096)) - } - } - // If we're running a light client on any network, drop the cache to some meaningfully low amount - if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" && !ctx.GlobalIsSet(utils.CacheFlag.Name) { - log.Info("Dropping default light client cache", "provided", ctx.GlobalInt(utils.CacheFlag.Name), "updated", 128) - ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(128)) - } - // Cap the cache allowance and tune the garbage collector - var mem gosigar.Mem - // Workaround until OpenBSD support lands into gosigar - // Check https://github.com/elastic/gosigar#supported-platforms - if runtime.GOOS != "openbsd" { - 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) - } -} - -// geth 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 geth(ctx *cli.Context) error { - if args := ctx.Args(); len(args) > 0 { - return fmt.Errorf("invalid command: %q", args[0]) - } - node := makeFullNode(ctx) - defer node.Close() - 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 - - // Register wallet event handlers to open and auto-derive wallets - - // Create a client to interact with local geth node. - rpcClient, err := stack.Attach() - if err != nil { - utils.Fatalf("Failed to attach to self: %v", err) - } - ethClient := ethclient.NewClient(rpcClient) - - // Set contract backend for ethereum service if local node - // is serving LES requests. - if ctx.GlobalInt(utils.LightLegacyServFlag.Name) > 0 || ctx.GlobalInt(utils.LightServeFlag.Name) > 0 { - var ethService *eth.Ethereum - if err := stack.Service(ðService); err != nil { - utils.Fatalf("Failed to retrieve ethereum service: %v", err) - } - ethService.SetContractBackend(ethClient) - } - // Set contract backend for les service if local node is - // running as a light client. - if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { - var lesService *les.LightEthereum - if err := stack.Service(&lesService); err != nil { - utils.Fatalf("Failed to retrieve light ethereum service: %v", err) - } - lesService.SetContractBackend(ethClient) - } - - // Spawn a standalone goroutine for status synchronization monitoring, - // close the node when synchronization is complete if user required. - if ctx.GlobalBool(utils.ExitWhenSyncedFlag.Name) { - go func() { - sub := stack.EventMux().Subscribe(downloader.DoneEvent{}) - defer sub.Unsubscribe() - for { - event := <-sub.Chan() - if event == 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(), - "age", common.PrettyAge(timestamp)) - stack.Stop() - } - } - }() - } - - // 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) - } - etherBase := &common.Address { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - } - ethereum.SetEtherbase(*etherBase) - // 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) - } - } -} diff --git a/cmd/geth/misccmd.go b/cmd/geth/misccmd.go deleted file mode 100644 index a49f2ba..0000000 --- a/cmd/geth/misccmd.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2016 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/>. - -package geth - -import ( - "fmt" - "os" - "runtime" - "strconv" - "strings" - - "github.com/ava-labs/coreth/cmd/utils" - "github.com/ava-labs/go-ethereum/consensus/ethash" - "github.com/ava-labs/go-ethereum/eth" - "github.com/ava-labs/go-ethereum/params" - "gopkg.in/urfave/cli.v1" -) - -var ( - makecacheCommand = cli.Command{ - Action: utils.MigrateFlags(makecache), - Name: "makecache", - Usage: "Generate ethash verification cache (for testing)", - ArgsUsage: "<blockNum> <outputDir>", - Category: "MISCELLANEOUS COMMANDS", - Description: ` -The makecache command generates an ethash cache in <outputDir>. - -This command exists to support the system testing project. -Regular users do not need to execute it. -`, - } - makedagCommand = cli.Command{ - Action: utils.MigrateFlags(makedag), - Name: "makedag", - Usage: "Generate ethash mining DAG (for testing)", - ArgsUsage: "<blockNum> <outputDir>", - Category: "MISCELLANEOUS COMMANDS", - Description: ` -The makedag command generates an ethash DAG in <outputDir>. - -This command exists to support the system testing project. -Regular users do not need to execute it. -`, - } - versionCommand = cli.Command{ - Action: utils.MigrateFlags(version), - Name: "version", - Usage: "Print version numbers", - ArgsUsage: " ", - Category: "MISCELLANEOUS COMMANDS", - Description: ` -The output of this command is supposed to be machine-readable. -`, - } - licenseCommand = cli.Command{ - Action: utils.MigrateFlags(license), - Name: "license", - Usage: "Display license information", - ArgsUsage: " ", - Category: "MISCELLANEOUS COMMANDS", - } -) - -// makecache generates an ethash verification cache into the provided folder. -func makecache(ctx *cli.Context) error { - args := ctx.Args() - if len(args) != 2 { - utils.Fatalf(`Usage: geth makecache <block number> <outputdir>`) - } - block, err := strconv.ParseUint(args[0], 0, 64) - if err != nil { - utils.Fatalf("Invalid block number: %v", err) - } - ethash.MakeCache(block, args[1]) - - return nil -} - -// makedag generates an ethash mining DAG into the provided folder. -func makedag(ctx *cli.Context) error { - args := ctx.Args() - if len(args) != 2 { - utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`) - } - block, err := strconv.ParseUint(args[0], 0, 64) - if err != nil { - utils.Fatalf("Invalid block number: %v", err) - } - ethash.MakeDataset(block, args[1]) - - return nil -} - -func version(ctx *cli.Context) error { - fmt.Println(strings.Title(clientIdentifier)) - fmt.Println("Version:", params.VersionWithMeta) - if gitCommit != "" { - fmt.Println("Git Commit:", gitCommit) - } - if gitDate != "" { - fmt.Println("Git Commit Date:", gitDate) - } - fmt.Println("Architecture:", runtime.GOARCH) - fmt.Println("Protocol Versions:", eth.ProtocolVersions) - fmt.Println("Network Id:", eth.DefaultConfig.NetworkId) - fmt.Println("Go Version:", runtime.Version()) - fmt.Println("Operating System:", runtime.GOOS) - fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH")) - fmt.Printf("GOROOT=%s\n", runtime.GOROOT()) - return nil -} - -func license(_ *cli.Context) error { - fmt.Println(`Geth 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. - -Geth 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 geth. If not, see <http://www.gnu.org/licenses/>.`) - return nil -} diff --git a/cmd/geth/retesteth.go b/cmd/geth/retesteth.go deleted file mode 100644 index a5bebb0..0000000 --- a/cmd/geth/retesteth.go +++ /dev/null @@ -1,891 +0,0 @@ -// Copyright 2019 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/>. - -package geth - -import ( - "bytes" - "context" - "fmt" - "math/big" - "os" - "os/signal" - "strings" - "time" - - "github.com/ava-labs/coreth/cmd/utils" - "github.com/ava-labs/go-ethereum/common" - "github.com/ava-labs/go-ethereum/common/hexutil" - "github.com/ava-labs/go-ethereum/common/math" - "github.com/ava-labs/go-ethereum/consensus" - "github.com/ava-labs/go-ethereum/consensus/ethash" - "github.com/ava-labs/go-ethereum/consensus/misc" - "github.com/ava-labs/go-ethereum/core" - "github.com/ava-labs/go-ethereum/core/rawdb" - "github.com/ava-labs/go-ethereum/core/state" - "github.com/ava-labs/go-ethereum/core/types" - "github.com/ava-labs/go-ethereum/core/vm" - "github.com/ava-labs/go-ethereum/crypto" - "github.com/ava-labs/go-ethereum/ethdb" - "github.com/ava-labs/go-ethereum/log" - "github.com/ava-labs/go-ethereum/node" - "github.com/ava-labs/go-ethereum/params" - "github.com/ava-labs/go-ethereum/rlp" - "github.com/ava-labs/go-ethereum/rpc" - "github.com/ava-labs/go-ethereum/trie" - - cli "gopkg.in/urfave/cli.v1" -) - -var ( - rpcPortFlag = cli.IntFlag{ - Name: "rpcport", - Usage: "HTTP-RPC server listening port", - Value: node.DefaultHTTPPort, - } - retestethCommand = cli.Command{ - Action: utils.MigrateFlags(retesteth), - Name: "retesteth", - Usage: "Launches geth in retesteth mode", - ArgsUsage: "", - Flags: []cli.Flag{rpcPortFlag}, - Category: "MISCELLANEOUS COMMANDS", - Description: `Launches geth in retesteth mode (no database, no network, only retesteth RPC interface)`, - } -) - -type RetestethTestAPI interface { - SetChainParams(ctx context.Context, chainParams ChainParams) (bool, error) - MineBlocks(ctx context.Context, number uint64) (bool, error) - ModifyTimestamp(ctx context.Context, interval uint64) (bool, error) - ImportRawBlock(ctx context.Context, rawBlock hexutil.Bytes) (common.Hash, error) - RewindToBlock(ctx context.Context, number uint64) (bool, error) - GetLogHash(ctx context.Context, txHash common.Hash) (common.Hash, error) -} - -type RetestethEthAPI interface { - SendRawTransaction(ctx context.Context, rawTx hexutil.Bytes) (common.Hash, error) - BlockNumber(ctx context.Context) (uint64, error) - GetBlockByNumber(ctx context.Context, blockNr math.HexOrDecimal64, fullTx bool) (map[string]interface{}, error) - GetBalance(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (*math.HexOrDecimal256, error) - GetCode(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (hexutil.Bytes, error) - GetTransactionCount(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (uint64, error) -} - -type RetestethDebugAPI interface { - AccountRange(ctx context.Context, - blockHashOrNumber *math.HexOrDecimal256, txIndex uint64, - addressHash *math.HexOrDecimal256, maxResults uint64, - ) (AccountRangeResult, error) - StorageRangeAt(ctx context.Context, - blockHashOrNumber *math.HexOrDecimal256, txIndex uint64, - address common.Address, - begin *math.HexOrDecimal256, maxResults uint64, - ) (StorageRangeResult, error) -} - -type RetestWeb3API interface { - ClientVersion(ctx context.Context) (string, error) -} - -type RetestethAPI struct { - ethDb ethdb.Database - db state.Database - chainConfig *params.ChainConfig - author common.Address - extraData []byte - genesisHash common.Hash - engine *NoRewardEngine - blockchain *core.BlockChain - blockNumber uint64 - txMap map[common.Address]map[uint64]*types.Transaction // Sender -> Nonce -> Transaction - txSenders map[common.Address]struct{} // Set of transaction senders - blockInterval uint64 -} - -type ChainParams struct { - SealEngine string `json:"sealEngine"` - Params CParamsParams `json:"params"` - Genesis CParamsGenesis `json:"genesis"` - Accounts map[common.Address]CParamsAccount `json:"accounts"` -} - -type CParamsParams struct { - AccountStartNonce math.HexOrDecimal64 `json:"accountStartNonce"` - HomesteadForkBlock *math.HexOrDecimal64 `json:"homesteadForkBlock"` - EIP150ForkBlock *math.HexOrDecimal64 `json:"EIP150ForkBlock"` - EIP158ForkBlock *math.HexOrDecimal64 `json:"EIP158ForkBlock"` - DaoHardforkBlock *math.HexOrDecimal64 `json:"daoHardforkBlock"` - ByzantiumForkBlock *math.HexOrDecimal64 `json:"byzantiumForkBlock"` - ConstantinopleForkBlock *math.HexOrDecimal64 `json:"constantinopleForkBlock"` - ConstantinopleFixForkBlock *math.HexOrDecimal64 `json:"constantinopleFixForkBlock"` - ChainID *math.HexOrDecimal256 `json:"chainID"` - MaximumExtraDataSize math.HexOrDecimal64 `json:"maximumExtraDataSize"` - TieBreakingGas bool `json:"tieBreakingGas"` - MinGasLimit math.HexOrDecimal64 `json:"minGasLimit"` - MaxGasLimit math.HexOrDecimal64 `json:"maxGasLimit"` - GasLimitBoundDivisor math.HexOrDecimal64 `json:"gasLimitBoundDivisor"` - MinimumDifficulty math.HexOrDecimal256 `json:"minimumDifficulty"` - DifficultyBoundDivisor math.HexOrDecimal256 `json:"difficultyBoundDivisor"` - DurationLimit math.HexOrDecimal256 `json:"durationLimit"` - BlockReward math.HexOrDecimal256 `json:"blockReward"` - NetworkID math.HexOrDecimal256 `json:"networkID"` -} - -type CParamsGenesis struct { - Nonce math.HexOrDecimal64 `json:"nonce"` - Difficulty *math.HexOrDecimal256 `json:"difficulty"` - MixHash *math.HexOrDecimal256 `json:"mixHash"` - Author common.Address `json:"author"` - Timestamp math.HexOrDecimal64 `json:"timestamp"` - ParentHash common.Hash `json:"parentHash"` - ExtraData hexutil.Bytes `json:"extraData"` - GasLimit math.HexOrDecimal64 `json:"gasLimit"` -} - -type CParamsAccount struct { - Balance *math.HexOrDecimal256 `json:"balance"` - Precompiled *CPAccountPrecompiled `json:"precompiled"` - Code hexutil.Bytes `json:"code"` - Storage map[string]string `json:"storage"` - Nonce *math.HexOrDecimal64 `json:"nonce"` -} - -type CPAccountPrecompiled struct { - Name string `json:"name"` - StartingBlock math.HexOrDecimal64 `json:"startingBlock"` - Linear *CPAPrecompiledLinear `json:"linear"` -} - -type CPAPrecompiledLinear struct { - Base uint64 `json:"base"` - Word uint64 `json:"word"` -} - -type AccountRangeResult struct { - AddressMap map[common.Hash]common.Address `json:"addressMap"` - NextKey common.Hash `json:"nextKey"` -} - -type StorageRangeResult struct { - Complete bool `json:"complete"` - Storage map[common.Hash]SRItem `json:"storage"` -} - -type SRItem struct { - Key string `json:"key"` - Value string `json:"value"` -} - -type NoRewardEngine struct { - inner consensus.Engine - rewardsOn bool -} - -func (e *NoRewardEngine) Author(header *types.Header) (common.Address, error) { - return e.inner.Author(header) -} - -func (e *NoRewardEngine) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { - return e.inner.VerifyHeader(chain, header, seal) -} - -func (e *NoRewardEngine) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { - return e.inner.VerifyHeaders(chain, headers, seals) -} - -func (e *NoRewardEngine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { - return e.inner.VerifyUncles(chain, block) -} - -func (e *NoRewardEngine) VerifySeal(chain consensus.ChainReader, header *types.Header) error { - return e.inner.VerifySeal(chain, header) -} - -func (e *NoRewardEngine) Prepare(chain consensus.ChainReader, header *types.Header) error { - return e.inner.Prepare(chain, header) -} - -func (e *NoRewardEngine) accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { - // Simply touch miner and uncle coinbase accounts - reward := big.NewInt(0) - for _, uncle := range uncles { - state.AddBalance(uncle.Coinbase, reward) - } - state.AddBalance(header.Coinbase, reward) -} - -func (e *NoRewardEngine) Finalize(chain consensus.ChainReader, header *types.Header, statedb *state.StateDB, txs []*types.Transaction, - uncles []*types.Header) { - if e.rewardsOn { - e.inner.Finalize(chain, header, statedb, txs, uncles) - } else { - e.accumulateRewards(chain.Config(), statedb, header, uncles) - header.Root = statedb.IntermediateRoot(chain.Config().IsEIP158(header.Number)) - } -} - -func (e *NoRewardEngine) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, statedb *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { - if e.rewardsOn { - return e.inner.FinalizeAndAssemble(chain, header, statedb, txs, uncles, receipts) - } else { - e.accumulateRewards(chain.Config(), statedb, header, uncles) - header.Root = statedb.IntermediateRoot(chain.Config().IsEIP158(header.Number)) - - // Header seems complete, assemble into a block and return - return types.NewBlock(header, txs, uncles, receipts), nil - } -} - -func (e *NoRewardEngine) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - return e.inner.Seal(chain, block, results, stop) -} - -func (e *NoRewardEngine) SealHash(header *types.Header) common.Hash { - return e.inner.SealHash(header) -} - -func (e *NoRewardEngine) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { - return e.inner.CalcDifficulty(chain, time, parent) -} - -func (e *NoRewardEngine) APIs(chain consensus.ChainReader) []rpc.API { - return e.inner.APIs(chain) -} - -func (e *NoRewardEngine) Close() error { - return e.inner.Close() -} - -func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainParams) (bool, error) { - // Clean up - if api.blockchain != nil { - api.blockchain.Stop() - } - if api.engine != nil { - api.engine.Close() - } - if api.ethDb != nil { - api.ethDb.Close() - } - ethDb := rawdb.NewMemoryDatabase() - accounts := make(core.GenesisAlloc) - for address, account := range chainParams.Accounts { - balance := big.NewInt(0) - if account.Balance != nil { - balance.Set((*big.Int)(account.Balance)) - } - var nonce uint64 - if account.Nonce != nil { - nonce = uint64(*account.Nonce) - } - if account.Precompiled == nil || account.Balance != nil { - storage := make(map[common.Hash]common.Hash) - for k, v := range account.Storage { - storage[common.HexToHash(k)] = common.HexToHash(v) - } - accounts[address] = core.GenesisAccount{ - Balance: balance, - Code: account.Code, - Nonce: nonce, - Storage: storage, - } - } - } - chainId := big.NewInt(1) - if chainParams.Params.ChainID != nil { - chainId.Set((*big.Int)(chainParams.Params.ChainID)) - } - var ( - homesteadBlock *big.Int - daoForkBlock *big.Int - eip150Block *big.Int - eip155Block *big.Int - eip158Block *big.Int - byzantiumBlock *big.Int - constantinopleBlock *big.Int - petersburgBlock *big.Int - ) - if chainParams.Params.HomesteadForkBlock != nil { - homesteadBlock = big.NewInt(int64(*chainParams.Params.HomesteadForkBlock)) - } - if chainParams.Params.DaoHardforkBlock != nil { - daoForkBlock = big.NewInt(int64(*chainParams.Params.DaoHardforkBlock)) - } - if chainParams.Params.EIP150ForkBlock != nil { - eip150Block = big.NewInt(int64(*chainParams.Params.EIP150ForkBlock)) - } - if chainParams.Params.EIP158ForkBlock != nil { - eip158Block = big.NewInt(int64(*chainParams.Params.EIP158ForkBlock)) - eip155Block = eip158Block - } - if chainParams.Params.ByzantiumForkBlock != nil { - byzantiumBlock = big.NewInt(int64(*chainParams.Params.ByzantiumForkBlock)) - } - if chainParams.Params.ConstantinopleForkBlock != nil { - constantinopleBlock = big.NewInt(int64(*chainParams.Params.ConstantinopleForkBlock)) - } - if chainParams.Params.ConstantinopleFixForkBlock != nil { - petersburgBlock = big.NewInt(int64(*chainParams.Params.ConstantinopleFixForkBlock)) - } - if constantinopleBlock != nil && petersburgBlock == nil { - petersburgBlock = big.NewInt(100000000000) - } - genesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: chainId, - HomesteadBlock: homesteadBlock, - DAOForkBlock: daoForkBlock, - DAOForkSupport: false, - EIP150Block: eip150Block, - EIP155Block: eip155Block, - EIP158Block: eip158Block, - ByzantiumBlock: byzantiumBlock, - ConstantinopleBlock: constantinopleBlock, - PetersburgBlock: petersburgBlock, - }, - Nonce: uint64(chainParams.Genesis.Nonce), - Timestamp: uint64(chainParams.Genesis.Timestamp), - ExtraData: chainParams.Genesis.ExtraData, - GasLimit: uint64(chainParams.Genesis.GasLimit), - Difficulty: big.NewInt(0).Set((*big.Int)(chainParams.Genesis.Difficulty)), - Mixhash: common.BigToHash((*big.Int)(chainParams.Genesis.MixHash)), - Coinbase: chainParams.Genesis.Author, - ParentHash: chainParams.Genesis.ParentHash, - Alloc: accounts, - } - chainConfig, genesisHash, err := core.SetupGenesisBlock(ethDb, genesis) - if err != nil { - return false, err - } - fmt.Printf("Chain config: %v\n", chainConfig) - - var inner consensus.Engine - switch chainParams.SealEngine { - case "NoProof", "NoReward": - inner = ethash.NewFaker() - case "Ethash": - inner = ethash.New(ethash.Config{ - CacheDir: "ethash", - CachesInMem: 2, - CachesOnDisk: 3, - DatasetsInMem: 1, - DatasetsOnDisk: 2, - }, nil, false) - default: - return false, fmt.Errorf("unrecognised seal engine: %s", chainParams.SealEngine) - } - engine := &NoRewardEngine{inner: inner, rewardsOn: chainParams.SealEngine != "NoReward"} - - blockchain, err := core.NewBlockChain(ethDb, nil, chainConfig, engine, vm.Config{}, nil) - if err != nil { - return false, err - } - - api.chainConfig = chainConfig - api.genesisHash = genesisHash - api.author = chainParams.Genesis.Author - api.extraData = chainParams.Genesis.ExtraData - api.ethDb = ethDb - api.engine = engine - api.blockchain = blockchain - api.db = state.NewDatabase(api.ethDb) - api.blockNumber = 0 - api.txMap = make(map[common.Address]map[uint64]*types.Transaction) - api.txSenders = make(map[common.Address]struct{}) - api.blockInterval = 0 - return true, nil -} - -func (api *RetestethAPI) SendRawTransaction(ctx context.Context, rawTx hexutil.Bytes) (common.Hash, error) { - tx := new(types.Transaction) - if err := rlp.DecodeBytes(rawTx, tx); err != nil { - // Return nil is not by mistake - some tests include sending transaction where gasLimit overflows uint64 - return common.Hash{}, nil - } - signer := types.MakeSigner(api.chainConfig, big.NewInt(int64(api.blockNumber))) - sender, err := types.Sender(signer, tx) - if err != nil { - return common.Hash{}, err - } - if nonceMap, ok := api.txMap[sender]; ok { - nonceMap[tx.Nonce()] = tx - } else { - nonceMap = make(map[uint64]*types.Transaction) - nonceMap[tx.Nonce()] = tx - api.txMap[sender] = nonceMap - } - api.txSenders[sender] = struct{}{} - return tx.Hash(), nil -} - -func (api *RetestethAPI) MineBlocks(ctx context.Context, number uint64) (bool, error) { - for i := 0; i < int(number); i++ { - if err := api.mineBlock(); err != nil { - return false, err - } - } - fmt.Printf("Mined %d blocks\n", number) - return true, nil -} - -func (api *RetestethAPI) mineBlock() error { - parentHash := rawdb.ReadCanonicalHash(api.ethDb, api.blockNumber) - parent := rawdb.ReadBlock(api.ethDb, parentHash, api.blockNumber) - var timestamp uint64 - if api.blockInterval == 0 { - timestamp = uint64(time.Now().Unix()) - } else { - timestamp = parent.Time() + api.blockInterval - } - gasLimit := core.CalcGasLimit(parent, 9223372036854775807, 9223372036854775807) - header := &types.Header{ - ParentHash: parent.Hash(), - Number: big.NewInt(int64(api.blockNumber + 1)), - GasLimit: gasLimit, - Extra: api.extraData, - Time: timestamp, - } - header.Coinbase = api.author - if api.engine != nil { - api.engine.Prepare(api.blockchain, header) - } - // If we are care about TheDAO hard-fork check whether to override the extra-data or not - if daoBlock := api.chainConfig.DAOForkBlock; daoBlock != nil { - // Check whether the block is among the fork extra-override range - limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange) - if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 { - // Depending whether we support or oppose the fork, override differently - if api.chainConfig.DAOForkSupport { - header.Extra = common.CopyBytes(params.DAOForkBlockExtra) - } else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) { - header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data - } - } - } - statedb, err := api.blockchain.StateAt(parent.Root()) - if err != nil { - return err - } - if api.chainConfig.DAOForkSupport && api.chainConfig.DAOForkBlock != nil && api.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 { - misc.ApplyDAOHardFork(statedb) - } - gasPool := new(core.GasPool).AddGas(header.GasLimit) - txCount := 0 - var txs []*types.Transaction - var receipts []*types.Receipt - var coalescedLogs []*types.Log - var blockFull = gasPool.Gas() < params.TxGas - for address := range api.txSenders { - if blockFull { - break - } - m := api.txMap[address] - for nonce := statedb.GetNonce(address); ; nonce++ { - if tx, ok := m[nonce]; ok { - // Try to apply transactions to the state - statedb.Prepare(tx.Hash(), common.Hash{}, txCount) - snap := statedb.Snapshot() - - receipt, _, err := core.ApplyTransaction( - api.chainConfig, - api.blockchain, - &api.author, - gasPool, - statedb, - header, tx, &header.GasUsed, *api.blockchain.GetVMConfig(), - ) - if err != nil { - statedb.RevertToSnapshot(snap) - break - } - txs = append(txs, tx) - receipts = append(receipts, receipt) - coalescedLogs = append(coalescedLogs, receipt.Logs...) - delete(m, nonce) - if len(m) == 0 { - // Last tx for the sender - delete(api.txMap, address) - delete(api.txSenders, address) - } - txCount++ - if gasPool.Gas() < params.TxGas { - blockFull = true - break - } - } else { - break // Gap in the nonces - } - } - } - block, err := api.engine.FinalizeAndAssemble(api.blockchain, header, statedb, txs, []*types.Header{}, receipts) - if err != nil { - return err - } - return api.importBlock(block) -} - -func (api *RetestethAPI) importBlock(block *types.Block) error { - if _, err := api.blockchain.InsertChain([]*types.Block{block}); err != nil { - return err - } - api.blockNumber = block.NumberU64() - fmt.Printf("Imported block %d\n", block.NumberU64()) - return nil -} - -func (api *RetestethAPI) ModifyTimestamp(ctx context.Context, interval uint64) (bool, error) { - api.blockInterval = interval - return true, nil -} - -func (api *RetestethAPI) ImportRawBlock(ctx context.Context, rawBlock hexutil.Bytes) (common.Hash, error) { - block := new(types.Block) - if err := rlp.DecodeBytes(rawBlock, block); err != nil { - return common.Hash{}, err - } - fmt.Printf("Importing block %d with parent hash: %x, genesisHash: %x\n", block.NumberU64(), block.ParentHash(), api.genesisHash) - if err := api.importBlock(block); err != nil { - return common.Hash{}, err - } - return block.Hash(), nil -} - -func (api *RetestethAPI) RewindToBlock(ctx context.Context, newHead uint64) (bool, error) { - if err := api.blockchain.SetHead(newHead); err != nil { - return false, err - } - api.blockNumber = newHead - return true, nil -} - -var emptyListHash common.Hash = common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") - -func (api *RetestethAPI) GetLogHash(ctx context.Context, txHash common.Hash) (common.Hash, error) { - receipt, _, _, _ := rawdb.ReadReceipt(api.ethDb, txHash, api.chainConfig) - if receipt == nil { - return emptyListHash, nil - } else { - if logListRlp, err := rlp.EncodeToBytes(receipt.Logs); err != nil { - return common.Hash{}, err - } else { - return common.BytesToHash(crypto.Keccak256(logListRlp)), nil - } - } -} - -func (api *RetestethAPI) BlockNumber(ctx context.Context) (uint64, error) { - //fmt.Printf("BlockNumber, response: %d\n", api.blockNumber) - return api.blockNumber, nil -} - -func (api *RetestethAPI) GetBlockByNumber(ctx context.Context, blockNr math.HexOrDecimal64, fullTx bool) (map[string]interface{}, error) { - block := api.blockchain.GetBlockByNumber(uint64(blockNr)) - if block != nil { - response, err := RPCMarshalBlock(block, true, fullTx) - if err != nil { - return nil, err - } - response["author"] = response["miner"] - response["totalDifficulty"] = (*hexutil.Big)(api.blockchain.GetTd(block.Hash(), uint64(blockNr))) - return response, err - } - return nil, fmt.Errorf("block %d not found", blockNr) -} - -func (api *RetestethAPI) AccountRange(ctx context.Context, - blockHashOrNumber *math.HexOrDecimal256, txIndex uint64, - addressHash *math.HexOrDecimal256, maxResults uint64, -) (AccountRangeResult, error) { - var ( - header *types.Header - block *types.Block - ) - if (*big.Int)(blockHashOrNumber).Cmp(big.NewInt(math.MaxInt64)) > 0 { - blockHash := common.BigToHash((*big.Int)(blockHashOrNumber)) - header = api.blockchain.GetHeaderByHash(blockHash) - block = api.blockchain.GetBlockByHash(blockHash) - //fmt.Printf("Account range: %x, txIndex %d, start: %x, maxResults: %d\n", blockHash, txIndex, common.BigToHash((*big.Int)(addressHash)), maxResults) - } else { - blockNumber := (*big.Int)(blockHashOrNumber).Uint64() - header = api.blockchain.GetHeaderByNumber(blockNumber) - block = api.blockchain.GetBlockByNumber(blockNumber) - //fmt.Printf("Account range: %d, txIndex %d, start: %x, maxResults: %d\n", blockNumber, txIndex, common.BigToHash((*big.Int)(addressHash)), maxResults) - } - parentHeader := api.blockchain.GetHeaderByHash(header.ParentHash) - var root common.Hash - var statedb *state.StateDB - var err error - if parentHeader == nil || int(txIndex) >= len(block.Transactions()) { - root = header.Root - statedb, err = api.blockchain.StateAt(root) - if err != nil { - return AccountRangeResult{}, err - } - } else { - root = parentHeader.Root - statedb, err = api.blockchain.StateAt(root) - if err != nil { - return AccountRangeResult{}, err - } - // Recompute transactions up to the target index. - signer := types.MakeSigner(api.blockchain.Config(), block.Number()) - for idx, tx := range block.Transactions() { - // Assemble the transaction call message and return if the requested offset - msg, _ := tx.AsMessage(signer) - context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil) - // Not yet the searched for transaction, execute on top of the current state - vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{}) - if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { - return AccountRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) - } - // Ensure any modifications are committed to the state - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - root = statedb.IntermediateRoot(vmenv.ChainConfig().IsEIP158(block.Number())) - if idx == int(txIndex) { - // This is to make sure root can be opened by OpenTrie - root, err = statedb.Commit(api.chainConfig.IsEIP158(block.Number())) - if err != nil { - return AccountRangeResult{}, err - } - break - } - } - } - accountTrie, err := statedb.Database().OpenTrie(root) - if err != nil { - return AccountRangeResult{}, err - } - it := trie.NewIterator(accountTrie.NodeIterator(common.BigToHash((*big.Int)(addressHash)).Bytes())) - result := AccountRangeResult{AddressMap: make(map[common.Hash]common.Address)} - for i := 0; /*i < int(maxResults) && */ it.Next(); i++ { - if preimage := accountTrie.GetKey(it.Key); preimage != nil { - result.AddressMap[common.BytesToHash(it.Key)] = common.BytesToAddress(preimage) - //fmt.Printf("%x: %x\n", it.Key, preimage) - } else { - //fmt.Printf("could not find preimage for %x\n", it.Key) - } - } - //fmt.Printf("Number of entries returned: %d\n", len(result.AddressMap)) - // Add the 'next key' so clients can continue downloading. - if it.Next() { - next := common.BytesToHash(it.Key) - result.NextKey = next - } - return result, nil -} - -func (api *RetestethAPI) GetBalance(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (*math.HexOrDecimal256, error) { - //fmt.Printf("GetBalance %x, block %d\n", address, blockNr) - header := api.blockchain.GetHeaderByNumber(uint64(blockNr)) - statedb, err := api.blockchain.StateAt(header.Root) - if err != nil { - return nil, err - } - return (*math.HexOrDecimal256)(statedb.GetBalance(address)), nil -} - -func (api *RetestethAPI) GetCode(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (hexutil.Bytes, error) { - header := api.blockchain.GetHeaderByNumber(uint64(blockNr)) - statedb, err := api.blockchain.StateAt(header.Root) - if err != nil { - return nil, err - } - return statedb.GetCode(address), nil -} - -func (api *RetestethAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (uint64, error) { - header := api.blockchain.GetHeaderByNumber(uint64(blockNr)) - statedb, err := api.blockchain.StateAt(header.Root) - if err != nil { - return 0, err - } - return statedb.GetNonce(address), nil -} - -func (api *RetestethAPI) StorageRangeAt(ctx context.Context, - blockHashOrNumber *math.HexOrDecimal256, txIndex uint64, - address common.Address, - begin *math.HexOrDecimal256, maxResults uint64, -) (StorageRangeResult, error) { - var ( - header *types.Header - block *types.Block - ) - if (*big.Int)(blockHashOrNumber).Cmp(big.NewInt(math.MaxInt64)) > 0 { - blockHash := common.BigToHash((*big.Int)(blockHashOrNumber)) - header = api.blockchain.GetHeaderByHash(blockHash) - block = api.blockchain.GetBlockByHash(blockHash) - //fmt.Printf("Storage range: %x, txIndex %d, addr: %x, start: %x, maxResults: %d\n", - // blockHash, txIndex, address, common.BigToHash((*big.Int)(begin)), maxResults) - } else { - blockNumber := (*big.Int)(blockHashOrNumber).Uint64() - header = api.blockchain.GetHeaderByNumber(blockNumber) - block = api.blockchain.GetBlockByNumber(blockNumber) - //fmt.Printf("Storage range: %d, txIndex %d, addr: %x, start: %x, maxResults: %d\n", - // blockNumber, txIndex, address, common.BigToHash((*big.Int)(begin)), maxResults) - } - parentHeader := api.blockchain.GetHeaderByHash(header.ParentHash) - var root common.Hash - var statedb *state.StateDB - var err error - if parentHeader == nil || int(txIndex) >= len(block.Transactions()) { - root = header.Root - statedb, err = api.blockchain.StateAt(root) - if err != nil { - return StorageRangeResult{}, err - } - } else { - root = parentHeader.Root - statedb, err = api.blockchain.StateAt(root) - if err != nil { - return StorageRangeResult{}, err - } - // Recompute transactions up to the target index. - signer := types.MakeSigner(api.blockchain.Config(), block.Number()) - for idx, tx := range block.Transactions() { - // Assemble the transaction call message and return if the requested offset - msg, _ := tx.AsMessage(signer) - context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil) - // Not yet the searched for transaction, execute on top of the current state - vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{}) - if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { - return StorageRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) - } - // Ensure any modifications are committed to the state - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - _ = statedb.IntermediateRoot(vmenv.ChainConfig().IsEIP158(block.Number())) - if idx == int(txIndex) { - // This is to make sure root can be opened by OpenTrie - _, err = statedb.Commit(vmenv.ChainConfig().IsEIP158(block.Number())) - if err != nil { - return StorageRangeResult{}, err - } - } - } - } - storageTrie := statedb.StorageTrie(address) - it := trie.NewIterator(storageTrie.NodeIterator(common.BigToHash((*big.Int)(begin)).Bytes())) - result := StorageRangeResult{Storage: make(map[common.Hash]SRItem)} - for i := 0; /*i < int(maxResults) && */ it.Next(); i++ { - if preimage := storageTrie.GetKey(it.Key); preimage != nil { - key := (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(preimage)) - v, _, err := rlp.SplitString(it.Value) - if err != nil { - return StorageRangeResult{}, err - } - value := (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(v)) - ks, _ := key.MarshalText() - vs, _ := value.MarshalText() - if len(ks)%2 != 0 { - ks = append(append(append([]byte{}, ks[:2]...), byte('0')), ks[2:]...) - } - if len(vs)%2 != 0 { - vs = append(append(append([]byte{}, vs[:2]...), byte('0')), vs[2:]...) - } - result.Storage[common.BytesToHash(it.Key)] = SRItem{ - Key: string(ks), - Value: string(vs), - } - //fmt.Printf("Key: %s, Value: %s\n", ks, vs) - } else { - //fmt.Printf("Did not find preimage for %x\n", it.Key) - } - } - if it.Next() { - result.Complete = false - } else { - result.Complete = true - } - return result, nil -} - -func (api *RetestethAPI) ClientVersion(ctx context.Context) (string, error) { - return "Geth-" + params.VersionWithCommit(gitCommit, gitDate), nil -} - -// splitAndTrim splits input separated by a comma -// and trims excessive white space from the substrings. -func splitAndTrim(input string) []string { - result := strings.Split(input, ",") - for i, r := range result { - result[i] = strings.TrimSpace(r) - } - return result -} - -func retesteth(ctx *cli.Context) error { - log.Info("Welcome to retesteth!") - // register signer API with server - var ( - extapiURL string - ) - apiImpl := &RetestethAPI{} - var testApi RetestethTestAPI = apiImpl - var ethApi RetestethEthAPI = apiImpl - var debugApi RetestethDebugAPI = apiImpl - var web3Api RetestWeb3API = apiImpl - rpcAPI := []rpc.API{ - { - Namespace: "test", - Public: true, - Service: testApi, - Version: "1.0", - }, - { - Namespace: "eth", - Public: true, - Service: ethApi, - Version: "1.0", - }, - { - Namespace: "debug", - Public: true, - Service: debugApi, - Version: "1.0", - }, - { - Namespace: "web3", - Public: true, - Service: web3Api, - Version: "1.0", - }, - } - vhosts := splitAndTrim(ctx.GlobalString(utils.RPCVirtualHostsFlag.Name)) - cors := splitAndTrim(ctx.GlobalString(utils.RPCCORSDomainFlag.Name)) - - // start http server - httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name)) - listener, _, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, cors, vhosts, rpc.DefaultHTTPTimeouts) - if err != nil { - utils.Fatalf("Could not start RPC api: %v", err) - } - extapiURL = fmt.Sprintf("http://%s", httpEndpoint) - log.Info("HTTP endpoint opened", "url", extapiURL) - - defer func() { - listener.Close() - log.Info("HTTP endpoint closed", "url", httpEndpoint) - }() - - abortChan := make(chan os.Signal) - signal.Notify(abortChan, os.Interrupt) - - sig := <-abortChan - log.Info("Exiting...", "signal", sig) - return nil -} diff --git a/cmd/geth/retesteth_copypaste.go b/cmd/geth/retesteth_copypaste.go deleted file mode 100644 index b48b007..0000000 --- a/cmd/geth/retesteth_copypaste.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2019 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/>. - -package geth - -import ( - "math/big" - - "github.com/ava-labs/go-ethereum/common" - "github.com/ava-labs/go-ethereum/common/hexutil" - "github.com/ava-labs/go-ethereum/core/types" -) - -// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction -type RPCTransaction struct { - BlockHash common.Hash `json:"blockHash"` - BlockNumber *hexutil.Big `json:"blockNumber"` - From common.Address `json:"from"` - Gas hexutil.Uint64 `json:"gas"` - GasPrice *hexutil.Big `json:"gasPrice"` - Hash common.Hash `json:"hash"` - Input hexutil.Bytes `json:"input"` - Nonce hexutil.Uint64 `json:"nonce"` - To *common.Address `json:"to"` - TransactionIndex hexutil.Uint `json:"transactionIndex"` - Value *hexutil.Big `json:"value"` - V *hexutil.Big `json:"v"` - R *hexutil.Big `json:"r"` - S *hexutil.Big `json:"s"` -} - -// newRPCTransaction returns a transaction that will serialize to the RPC -// representation, with the given location metadata set (if available). -func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64) *RPCTransaction { - var signer types.Signer = types.FrontierSigner{} - if tx.Protected() { - signer = types.NewEIP155Signer(tx.ChainId()) - } - from, _ := types.Sender(signer, tx) - v, r, s := tx.RawSignatureValues() - - result := &RPCTransaction{ - From: from, - Gas: hexutil.Uint64(tx.Gas()), - GasPrice: (*hexutil.Big)(tx.GasPrice()), - Hash: tx.Hash(), - Input: hexutil.Bytes(tx.Data()), - Nonce: hexutil.Uint64(tx.Nonce()), - To: tx.To(), - Value: (*hexutil.Big)(tx.Value()), - V: (*hexutil.Big)(v), - R: (*hexutil.Big)(r), - S: (*hexutil.Big)(s), - } - if blockHash != (common.Hash{}) { - result.BlockHash = blockHash - result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber)) - result.TransactionIndex = hexutil.Uint(index) - } - return result -} - -// newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation. -func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransaction { - txs := b.Transactions() - if index >= uint64(len(txs)) { - return nil - } - return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index) -} - -// newRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation. -func newRPCTransactionFromBlockHash(b *types.Block, hash common.Hash) *RPCTransaction { - for idx, tx := range b.Transactions() { - if tx.Hash() == hash { - return newRPCTransactionFromBlockIndex(b, uint64(idx)) - } - } - return nil -} - -// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are -// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain -// transaction hashes. -func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { - head := b.Header() // copies the header once - fields := map[string]interface{}{ - "number": (*hexutil.Big)(head.Number), - "hash": b.Hash(), - "parentHash": head.ParentHash, - "nonce": head.Nonce, - "mixHash": head.MixDigest, - "sha3Uncles": head.UncleHash, - "logsBloom": head.Bloom, - "stateRoot": head.Root, - "miner": head.Coinbase, - "difficulty": (*hexutil.Big)(head.Difficulty), - "extraData": hexutil.Bytes(head.Extra), - "size": hexutil.Uint64(b.Size()), - "gasLimit": hexutil.Uint64(head.GasLimit), - "gasUsed": hexutil.Uint64(head.GasUsed), - "timestamp": hexutil.Uint64(head.Time), - "transactionsRoot": head.TxHash, - "receiptsRoot": head.ReceiptHash, - } - - if inclTx { - formatTx := func(tx *types.Transaction) (interface{}, error) { - return tx.Hash(), nil - } - if fullTx { - formatTx = func(tx *types.Transaction) (interface{}, error) { - return newRPCTransactionFromBlockHash(b, tx.Hash()), nil - } - } - txs := b.Transactions() - transactions := make([]interface{}, len(txs)) - var err error - for i, tx := range txs { - if transactions[i], err = formatTx(tx); err != nil { - return nil, err - } - } - fields["transactions"] = transactions - } - - uncles := b.Uncles() - uncleHashes := make([]common.Hash, len(uncles)) - for i, uncle := range uncles { - uncleHashes[i] = uncle.Hash() - } - fields["uncles"] = uncleHashes - - return fields, nil -} diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go deleted file mode 100644 index 2eb822d..0000000 --- a/cmd/geth/usage.go +++ /dev/null @@ -1,370 +0,0 @@ -// Copyright 2015 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/>. - -// Contains the geth command usage template and generator. - -package geth - -import ( - "io" - "sort" - - "strings" - - "github.com/ava-labs/coreth/cmd/utils" - "github.com/ava-labs/coreth/internal/debug" - cli "gopkg.in/urfave/cli.v1" -) - -// AppHelpTemplate is the test template for the default, global app help topic. -var AppHelpTemplate = `NAME: - {{.App.Name}} - {{.App.Usage}} - - Copyright 2013-2019 The go-ethereum Authors - -USAGE: - {{.App.HelpName}} [options]{{if .App.Commands}} command [command options]{{end}} {{if .App.ArgsUsage}}{{.App.ArgsUsage}}{{else}}[arguments...]{{end}} - {{if .App.Version}} -VERSION: - {{.App.Version}} - {{end}}{{if len .App.Authors}} -AUTHOR(S): - {{range .App.Authors}}{{ . }}{{end}} - {{end}}{{if .App.Commands}} -COMMANDS: - {{range .App.Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} - {{end}}{{end}}{{if .FlagGroups}} -{{range .FlagGroups}}{{.Name}} OPTIONS: - {{range .Flags}}{{.}} - {{end}} -{{end}}{{end}}{{if .App.Copyright }} -COPYRIGHT: - {{.App.Copyright}} - {{end}} -` - -// flagGroup is a collection of flags belonging to a single topic. -type flagGroup struct { - Name string - Flags []cli.Flag -} - -// AppHelpFlagGroups is the application flags, grouped by functionality. -var AppHelpFlagGroups = []flagGroup{ - { - Name: "ETHEREUM", - Flags: []cli.Flag{ - configFileFlag, - utils.DataDirFlag, - utils.AncientFlag, - utils.KeyStoreDirFlag, - utils.NoUSBFlag, - utils.SmartCardDaemonPathFlag, - utils.NetworkIdFlag, - utils.TestnetFlag, - utils.RinkebyFlag, - utils.GoerliFlag, - utils.SyncModeFlag, - utils.ExitWhenSyncedFlag, - utils.GCModeFlag, - utils.EthStatsURLFlag, - utils.IdentityFlag, - utils.LightKDFFlag, - utils.WhitelistFlag, - }, - }, - { - Name: "LIGHT CLIENT", - Flags: []cli.Flag{ - utils.LightServeFlag, - utils.LightIngressFlag, - utils.LightEgressFlag, - utils.LightMaxPeersFlag, - utils.UltraLightServersFlag, - utils.UltraLightFractionFlag, - utils.UltraLightOnlyAnnounceFlag, - }, - }, - { - Name: "DEVELOPER CHAIN", - Flags: []cli.Flag{ - utils.DeveloperFlag, - utils.DeveloperPeriodFlag, - }, - }, - { - Name: "ETHASH", - Flags: []cli.Flag{ - utils.EthashCacheDirFlag, - utils.EthashCachesInMemoryFlag, - utils.EthashCachesOnDiskFlag, - utils.EthashDatasetDirFlag, - utils.EthashDatasetsInMemoryFlag, - utils.EthashDatasetsOnDiskFlag, - }, - }, - //{ - // Name: "DASHBOARD", - // Flags: []cli.Flag{ - // utils.DashboardEnabledFlag, - // utils.DashboardAddrFlag, - // utils.DashboardPortFlag, - // utils.DashboardRefreshFlag, - // utils.DashboardAssetsFlag, - // }, - //}, - { - Name: "TRANSACTION POOL", - Flags: []cli.Flag{ - utils.TxPoolLocalsFlag, - utils.TxPoolNoLocalsFlag, - utils.TxPoolJournalFlag, - utils.TxPoolRejournalFlag, - utils.TxPoolPriceLimitFlag, - utils.TxPoolPriceBumpFlag, - utils.TxPoolAccountSlotsFlag, - utils.TxPoolGlobalSlotsFlag, - utils.TxPoolAccountQueueFlag, - utils.TxPoolGlobalQueueFlag, - utils.TxPoolLifetimeFlag, - }, - }, - { - Name: "PERFORMANCE TUNING", - Flags: []cli.Flag{ - utils.CacheFlag, - utils.CacheDatabaseFlag, - utils.CacheTrieFlag, - utils.CacheGCFlag, - utils.CacheNoPrefetchFlag, - }, - }, - { - Name: "ACCOUNT", - Flags: []cli.Flag{ - utils.UnlockedAccountFlag, - utils.PasswordFileFlag, - utils.ExternalSignerFlag, - utils.InsecureUnlockAllowedFlag, - }, - }, - { - Name: "API AND CONSOLE", - Flags: []cli.Flag{ - utils.IPCDisabledFlag, - utils.IPCPathFlag, - utils.RPCEnabledFlag, - utils.RPCListenAddrFlag, - utils.RPCPortFlag, - utils.RPCApiFlag, - utils.RPCGlobalGasCap, - utils.RPCCORSDomainFlag, - utils.RPCVirtualHostsFlag, - utils.WSEnabledFlag, - utils.WSListenAddrFlag, - utils.WSPortFlag, - utils.WSApiFlag, - utils.WSAllowedOriginsFlag, - utils.GraphQLEnabledFlag, - utils.GraphQLListenAddrFlag, - utils.GraphQLPortFlag, - utils.GraphQLCORSDomainFlag, - utils.GraphQLVirtualHostsFlag, - utils.JSpathFlag, - utils.ExecFlag, - utils.PreloadJSFlag, - }, - }, - { - Name: "NETWORKING", - Flags: []cli.Flag{ - utils.BootnodesFlag, - utils.BootnodesV4Flag, - utils.BootnodesV5Flag, - utils.ListenPortFlag, - utils.MaxPeersFlag, - utils.MaxPendingPeersFlag, - utils.NATFlag, - utils.NoDiscoverFlag, - utils.DiscoveryV5Flag, - utils.NetrestrictFlag, - utils.NodeKeyFileFlag, - utils.NodeKeyHexFlag, - }, - }, - { - Name: "MINER", - Flags: []cli.Flag{ - utils.MiningEnabledFlag, - utils.MinerThreadsFlag, - utils.MinerNotifyFlag, - utils.MinerGasPriceFlag, - utils.MinerGasTargetFlag, - utils.MinerGasLimitFlag, - utils.MinerEtherbaseFlag, - utils.MinerExtraDataFlag, - utils.MinerRecommitIntervalFlag, - utils.MinerNoVerfiyFlag, - }, - }, - { - Name: "GAS PRICE ORACLE", - Flags: []cli.Flag{ - utils.GpoBlocksFlag, - utils.GpoPercentileFlag, - }, - }, - { - Name: "VIRTUAL MACHINE", - Flags: []cli.Flag{ - utils.VMEnableDebugFlag, - utils.EVMInterpreterFlag, - utils.EWASMInterpreterFlag, - }, - }, - { - Name: "LOGGING AND DEBUGGING", - Flags: append([]cli.Flag{ - utils.FakePoWFlag, - utils.NoCompactionFlag, - }, debug.Flags...), - }, - { - Name: "METRICS AND STATS", - Flags: metricsFlags, - }, - { - Name: "WHISPER (EXPERIMENTAL)", - Flags: whisperFlags, - }, - { - Name: "DEPRECATED", - Flags: []cli.Flag{ - utils.LightLegacyServFlag, - utils.LightLegacyPeersFlag, - utils.MinerLegacyThreadsFlag, - utils.MinerLegacyGasTargetFlag, - utils.MinerLegacyGasPriceFlag, - utils.MinerLegacyEtherbaseFlag, - utils.MinerLegacyExtraDataFlag, - }, - }, - { - Name: "MISC", - }, -} - -// byCategory sorts an array of flagGroup by Name in the order -// defined in AppHelpFlagGroups. -type byCategory []flagGroup - -func (a byCategory) Len() int { return len(a) } -func (a byCategory) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byCategory) Less(i, j int) bool { - iCat, jCat := a[i].Name, a[j].Name - iIdx, jIdx := len(AppHelpFlagGroups), len(AppHelpFlagGroups) // ensure non categorized flags come last - - for i, group := range AppHelpFlagGroups { - if iCat == group.Name { - iIdx = i - } - if jCat == group.Name { - jIdx = i - } - } - - return iIdx < jIdx -} - -func flagCategory(flag cli.Flag) string { - for _, category := range AppHelpFlagGroups { - for _, flg := range category.Flags { - if flg.GetName() == flag.GetName() { - return category.Name - } - } - } - return "MISC" -} - -func init() { - // Override the default app help template - cli.AppHelpTemplate = AppHelpTemplate - - // Define a one shot struct to pass to the usage template - type helpData struct { - App interface{} - FlagGroups []flagGroup - } - - // Override the default app help printer, but only for the global app help - originalHelpPrinter := cli.HelpPrinter - cli.HelpPrinter = func(w io.Writer, tmpl string, data interface{}) { - if tmpl == AppHelpTemplate { - // Iterate over all the flags and add any uncategorized ones - categorized := make(map[string]struct{}) - for _, group := range AppHelpFlagGroups { - for _, flag := range group.Flags { - categorized[flag.String()] = struct{}{} - } - } - var uncategorized []cli.Flag - for _, flag := range data.(*cli.App).Flags { - if _, ok := categorized[flag.String()]; !ok { - if strings.HasPrefix(flag.GetName(), "dashboard") { - continue - } - uncategorized = append(uncategorized, flag) - } - } - if len(uncategorized) > 0 { - // Append all ungategorized options to the misc group - miscs := len(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags) - AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = append(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags, uncategorized...) - - // Make sure they are removed afterwards - defer func() { - AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags[:miscs] - }() - } - // Render out custom usage screen - originalHelpPrinter(w, tmpl, helpData{data, AppHelpFlagGroups}) - } else if tmpl == utils.CommandHelpTemplate { - // Iterate over all command specific flags and categorize them - categorized := make(map[string][]cli.Flag) - for _, flag := range data.(cli.Command).Flags { - if _, ok := categorized[flag.String()]; !ok { - categorized[flagCategory(flag)] = append(categorized[flagCategory(flag)], flag) - } - } - - // sort to get a stable ordering - sorted := make([]flagGroup, 0, len(categorized)) - for cat, flgs := range categorized { - sorted = append(sorted, flagGroup{cat, flgs}) - } - sort.Sort(byCategory(sorted)) - - // add sorted array to data and render with default printer - originalHelpPrinter(w, tmpl, map[string]interface{}{ - "cmd": data, - "categorizedFlags": sorted, - }) - } else { - originalHelpPrinter(w, tmpl, data) - } - } -} |