diff --git a/cmd/XDC/accountcmd.go b/cmd/XDC/accountcmd.go index d54828ab8e273..46909bdf9409c 100644 --- a/cmd/XDC/accountcmd.go +++ b/cmd/XDC/accountcmd.go @@ -26,31 +26,31 @@ import ( "github.com/XinFinOrg/XDPoSChain/console" "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/log" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) var ( - walletCommand = cli.Command{ + walletCommand = &cli.Command{ Name: "wallet", Usage: "Manage XDPoSChain presale wallets", ArgsUsage: "", - Category: "ACCOUNT COMMANDS", Description: ` XDC wallet import /path/to/my/presale.wallet will prompt for your password and imports your ether presale account. It can be used non-interactively with the --password option taking a passwordfile as argument containing the wallet password in plaintext.`, - Subcommands: []cli.Command{ + Subcommands: []*cli.Command{ { Name: "import", Usage: "Import XDPoSChain presale wallet", ArgsUsage: "", - Action: utils.MigrateFlags(importWallet), + Action: importWallet, Category: "ACCOUNT COMMANDS", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.KeyStoreDirFlag, utils.PasswordFileFlag, utils.LightKDFFlag, @@ -65,10 +65,9 @@ passwordfile as argument containing the wallet password in plaintext.`, }, } - accountCommand = cli.Command{ - Name: "account", - Usage: "Manage accounts", - Category: "ACCOUNT COMMANDS", + accountCommand = &cli.Command{ + Name: "account", + Usage: "Manage accounts", Description: ` Manage accounts, list all existing accounts, import a private key into a new @@ -89,13 +88,14 @@ It is safe to transfer the entire directory or the individual keys therein between ethereum nodes by simply copying. Make sure you backup your keys regularly.`, - Subcommands: []cli.Command{ + Subcommands: []*cli.Command{ { Name: "list", Usage: "Print summary of existing accounts", - Action: utils.MigrateFlags(accountList), + Action: accountList, Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.KeyStoreDirFlag, }, Description: ` @@ -104,9 +104,10 @@ Print a short summary of all accounts`, { Name: "new", Usage: "Create a new account", - Action: utils.MigrateFlags(accountCreate), + Action: accountCreate, Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.KeyStoreDirFlag, utils.PasswordFileFlag, utils.LightKDFFlag, @@ -129,10 +130,11 @@ password to file or expose in any other way. { Name: "update", Usage: "Update an existing account", - Action: utils.MigrateFlags(accountUpdate), + Action: accountUpdate, ArgsUsage: "
", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.KeyStoreDirFlag, utils.LightKDFFlag, }, @@ -158,9 +160,10 @@ changing your password is only possible interactively. { Name: "import", Usage: "Import a private key into a new account", - Action: utils.MigrateFlags(accountImport), + Action: accountImport, Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.KeyStoreDirFlag, utils.PasswordFileFlag, utils.LightKDFFlag, @@ -293,7 +296,7 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr func accountCreate(ctx *cli.Context) error { cfg := XDCConfig{Node: defaultNodeConfig()} // Load config file. - if file := ctx.GlobalString(configFileFlag.Name); file != "" { + if file := ctx.String(configFileFlag.Name); file != "" { if err := loadConfig(file, &cfg); err != nil { utils.Fatalf("%v", err) } @@ -319,13 +322,13 @@ func accountCreate(ctx *cli.Context) error { // accountUpdate transitions an account from a previous format to the current // one, also providing the possibility to change the pass-phrase. func accountUpdate(ctx *cli.Context) error { - if len(ctx.Args()) == 0 { + if ctx.Args().Len() == 0 { utils.Fatalf("No accounts specified to update") } stack, _ := makeConfigNode(ctx) ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - for _, addr := range ctx.Args() { + for _, addr := range ctx.Args().Slice() { account, oldPassword := unlockAccount(ctx, ks, addr, 0, nil) newPassword := getPassPhrase("Please give a new password. Do not forget this password.", true, 0, nil) if err := ks.Update(account, oldPassword, newPassword); err != nil { @@ -336,10 +339,10 @@ func accountUpdate(ctx *cli.Context) error { } func importWallet(ctx *cli.Context) error { - keyfile := ctx.Args().First() - if len(keyfile) == 0 { - utils.Fatalf("keyfile must be given as argument") + if ctx.Args().Len() != 1 { + utils.Fatalf("keyfile must be given as the only argument") } + keyfile := ctx.Args().First() keyJson, err := os.ReadFile(keyfile) if err != nil { utils.Fatalf("Could not read wallet file: %v", err) @@ -358,10 +361,10 @@ func importWallet(ctx *cli.Context) error { } func accountImport(ctx *cli.Context) error { - keyfile := ctx.Args().First() - if len(keyfile) == 0 { - utils.Fatalf("keyfile must be given as argument") + if ctx.Args().Len() != 1 { + utils.Fatalf("keyfile must be given as the only argument") } + keyfile := ctx.Args().First() key, err := crypto.LoadECDSA(keyfile) if err != nil { utils.Fatalf("Failed to load the private key: %v", err) diff --git a/cmd/XDC/accountcmd_test.go b/cmd/XDC/accountcmd_test.go index 4577ce5d65b63..668739594d956 100644 --- a/cmd/XDC/accountcmd_test.go +++ b/cmd/XDC/accountcmd_test.go @@ -43,26 +43,31 @@ func tmpDatadirWithKeystore(t *testing.T) string { } func TestAccountListEmpty(t *testing.T) { - XDC := runXDC(t, "account", "list") + datadir := tmpdir(t) + defer os.RemoveAll(datadir) + XDC := runXDC(t, "account", "list", "--datadir", datadir) XDC.ExpectExit() } func TestAccountList(t *testing.T) { datadir := tmpDatadirWithKeystore(t) - XDC := runXDC(t, "account", "list", "--datadir", datadir) - defer XDC.ExpectExit() + defer os.RemoveAll(datadir) + var want = ` +Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 +Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa +Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}/keystore/zzz +` if runtime.GOOS == "windows" { - XDC.Expect(` + want = ` Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}\keystore\UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}\keystore\aaa Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}\keystore\zzz -`) - } else { - XDC.Expect(` -Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 -Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa -Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}/keystore/zzz -`) +` + } + { + geth := runXDC(t, "account", "list", "--datadir", datadir) + geth.Expect(want) + geth.ExpectExit() } } @@ -92,9 +97,8 @@ Fatal: Passphrases do not match func TestAccountUpdate(t *testing.T) { datadir := tmpDatadirWithKeystore(t) - XDC := runXDC(t, "account", "update", - "--datadir", datadir, "--lightkdf", - "f466859ead1932d743d622cb74fc058882e8648a") + defer os.RemoveAll(datadir) + XDC := runXDC(t, "account", "update", "--datadir", datadir, "--lightkdf", "f466859ead1932d743d622cb74fc058882e8648a") defer XDC.ExpectExit() XDC.Expect(` Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3 @@ -107,7 +111,9 @@ Repeat passphrase: {{.InputLine "foobar2"}} } func TestWalletImport(t *testing.T) { - XDC := runXDC(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json") + datadir := tmpdir(t) + defer os.RemoveAll(datadir) + XDC := runXDC(t, "wallet", "import", "--datadir", datadir, "--lightkdf", "testdata/guswallet.json") defer XDC.ExpectExit() XDC.Expect(` !! Unsupported terminal, password will be echoed. @@ -121,6 +127,36 @@ Address: {xdcd4584b5f6229b7be90727b0fc8c6b91bb427821f} } } +func TestAccountHelp(t *testing.T) { + geth := runXDC(t, "account", "-h") + geth.WaitExit() + if have, want := geth.ExitStatus(), 0; have != want { + t.Errorf("exit error, have %d want %d", have, want) + } + + geth = runXDC(t, "account", "import", "-h") + geth.WaitExit() + if have, want := geth.ExitStatus(), 0; have != want { + t.Errorf("exit error, have %d want %d", have, want) + } +} + +func importAccountWithExpect(t *testing.T, key string, expected string) { + dir := t.TempDir() + defer os.RemoveAll(dir) + keyfile := filepath.Join(dir, "key.prv") + if err := os.WriteFile(keyfile, []byte(key), 0600); err != nil { + t.Error(err) + } + passwordFile := filepath.Join(dir, "password.txt") + if err := os.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil { + t.Error(err) + } + geth := runXDC(t, "account", "import", "--lightkdf", "-password", passwordFile, keyfile) + defer geth.ExpectExit() + geth.Expect(expected) +} + func TestWalletImportBadPassword(t *testing.T) { XDC := runXDC(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json") defer XDC.ExpectExit() @@ -133,10 +169,11 @@ Fatal: could not decrypt key with given passphrase func TestUnlockFlag(t *testing.T) { datadir := tmpDatadirWithKeystore(t) + defer os.RemoveAll(datadir) XDC := runXDC(t, - "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", - "js", "testdata/empty.js") + "js", "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", + "--port", "0", "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", + "testdata/empty.js") XDC.Expect(` Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3 !! Unsupported terminal, password will be echoed. @@ -157,6 +194,7 @@ Passphrase: {{.InputLine "foobar"}} func TestUnlockFlagWrongPassword(t *testing.T) { datadir := tmpDatadirWithKeystore(t) + defer os.RemoveAll(datadir) XDC := runXDC(t, "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", "--unlock", "f466859ead1932d743d622cb74fc058882e8648a") @@ -176,10 +214,11 @@ Fatal: Failed to unlock account f466859ead1932d743d622cb74fc058882e8648a (could // https://github.com/XinFinOrg/XDPoSChain/issues/1785 func TestUnlockFlagMultiIndex(t *testing.T) { datadir := tmpDatadirWithKeystore(t) + defer os.RemoveAll(datadir) XDC := runXDC(t, - "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", - "--unlock", "0,2", - "js", "testdata/empty.js") + "js", "--datadir", datadir, "--nat", "none", "--nodiscover", + "--maxpeers", "0", "--port", "0", "--unlock", "0,2", + "testdata/empty.js") XDC.Expect(` Unlocking account 0 | Attempt 1/3 !! Unsupported terminal, password will be echoed. @@ -203,10 +242,11 @@ Passphrase: {{.InputLine "foobar"}} func TestUnlockFlagPasswordFile(t *testing.T) { datadir := tmpDatadirWithKeystore(t) + defer os.RemoveAll(datadir) XDC := runXDC(t, - "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", - "--password", "testdata/passwords.txt", "--unlock", "0,2", - "js", "testdata/empty.js") + "js", "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", + "--port", "0", "--password", "testdata/passwords.txt", "--unlock", "0,2", + "testdata/empty.js") XDC.ExpectExit() wantMessages := []string{ @@ -223,6 +263,7 @@ func TestUnlockFlagPasswordFile(t *testing.T) { func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) { datadir := tmpDatadirWithKeystore(t) + defer os.RemoveAll(datadir) XDC := runXDC(t, "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", "--password", "testdata/wrong-passwords.txt", "--unlock", "0,2") @@ -235,9 +276,9 @@ Fatal: Failed to unlock account 0 (could not decrypt key with given passphrase) func TestUnlockFlagAmbiguous(t *testing.T) { store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes") XDC := runXDC(t, - "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", - "js", "testdata/empty.js") + "js", "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "0", + "--port", "0", "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", + "testdata/empty.js") defer XDC.ExpectExit() // Helper for the expect template, returns absolute keystore path. diff --git a/cmd/XDC/bugcmd.go b/cmd/XDC/bugcmd.go index c4bb574946a33..201883f8c99e3 100644 --- a/cmd/XDC/bugcmd.go +++ b/cmd/XDC/bugcmd.go @@ -28,17 +28,14 @@ import ( "github.com/XinFinOrg/XDPoSChain/cmd/internal/browser" "github.com/XinFinOrg/XDPoSChain/params" - - "github.com/XinFinOrg/XDPoSChain/cmd/utils" - cli "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) -var bugCommand = cli.Command{ - Action: utils.MigrateFlags(reportBug), +var bugCommand = &cli.Command{ + Action: reportBug, Name: "bug", Usage: "opens a window to report a bug on the XDC repo", ArgsUsage: " ", - Category: "MISCELLANEOUS COMMANDS", } const issueUrl = "https://github.com/XinFinOrg/XDPoSChain/issues/new" diff --git a/cmd/XDC/chaincmd.go b/cmd/XDC/chaincmd.go index 54795af0dbb13..31603d52c1f68 100644 --- a/cmd/XDC/chaincmd.go +++ b/cmd/XDC/chaincmd.go @@ -34,23 +34,24 @@ import ( "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/eth/downloader" "github.com/XinFinOrg/XDPoSChain/event" + "github.com/XinFinOrg/XDPoSChain/internal/flags" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/metrics" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) var ( - initCommand = cli.Command{ - Action: utils.MigrateFlags(initGenesis), + initCommand = &cli.Command{ + Action: initGenesis, Name: "init", Usage: "Bootstrap and initialize a new genesis block", ArgsUsage: "", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.LightModeFlag, utils.XDCTestnetFlag, }, - 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 @@ -58,20 +59,20 @@ participating. It expects the genesis file as argument.`, } - importCommand = cli.Command{ - Action: utils.MigrateFlags(importChain), + importCommand = &cli.Command{ + Action: importChain, Name: "import", Usage: "Import a blockchain file", ArgsUsage: " ( ... ) ", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.CacheFlag, utils.LightModeFlag, 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. @@ -79,30 +80,31 @@ 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), + exportCommand = &cli.Command{ + Action: exportChain, Name: "export", Usage: "Export blockchain into file", ArgsUsage: " [ ]", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.CacheFlag, utils.LightModeFlag, }, - 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.`, } - importPreimagesCommand = cli.Command{ - Action: utils.MigrateFlags(importPreimages), + importPreimagesCommand = &cli.Command{ + Action: importPreimages, Name: "import-preimages", Usage: "Import the preimage database from an RLP stream", ArgsUsage: "", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.CacheFlag, utils.LightModeFlag, }, @@ -110,57 +112,58 @@ if already existing.`, Description: ` The import-preimages command imports hash preimages from an RLP encoded stream.`, } - exportPreimagesCommand = cli.Command{ - Action: utils.MigrateFlags(exportPreimages), + exportPreimagesCommand = &cli.Command{ + Action: exportPreimages, Name: "export-preimages", Usage: "Export the preimage database into an RLP stream", ArgsUsage: "", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.CacheFlag, utils.LightModeFlag, }, - Category: "BLOCKCHAIN COMMANDS", Description: ` The export-preimages command export hash preimages to an RLP encoded stream`, } - copydbCommand = cli.Command{ - Action: utils.MigrateFlags(copyDb), + copydbCommand = &cli.Command{ + Action: copyDb, Name: "copydb", Usage: "Create a local chain from a target chaindata folder", ArgsUsage: "", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, 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), + removedbCommand = &cli.Command{ + Action: removeDB, Name: "removedb", Usage: "Remove blockchain and state databases", ArgsUsage: " ", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.LightModeFlag, }, - Category: "BLOCKCHAIN COMMANDS", Description: ` Remove blockchain and state databases`, } - dumpCommand = cli.Command{ - Action: utils.MigrateFlags(dump), + dumpCommand = &cli.Command{ + Action: dump, Name: "dump", Usage: "Dump a specific block from storage", ArgsUsage: "[ | ]...", Flags: []cli.Flag{ utils.DataDirFlag, + utils.XDCXDataDirFlag, utils.CacheFlag, utils.LightModeFlag, }, @@ -174,12 +177,10 @@ Use "ethereum dump 0" to dump the genesis block.`, // 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() genesis := new(core.Genesis) - if ctx.GlobalBool(utils.XDCTestnetFlag.Name) { - if len(genesisPath) > 0 { + if ctx.Bool(utils.XDCTestnetFlag.Name) { + if ctx.Args().Len() > 0 { utils.Fatalf("Flags --apothem and genesis file can't be used at the same time") } err := json.Unmarshal(apothemGenesis, &genesis) @@ -187,8 +188,12 @@ func initGenesis(ctx *cli.Context) error { utils.Fatalf("invalid genesis json: %v", err) } } else { + if ctx.Args().Len() != 1 { + utils.Fatalf("need genesis.json file as the only argument") + } + genesisPath := ctx.Args().First() if len(genesisPath) == 0 { - utils.Fatalf("Must supply path to genesis JSON file") + utils.Fatalf("invalid path to genesis file") } file, err := os.Open(genesisPath) if err != nil { @@ -220,10 +225,9 @@ func initGenesis(ctx *cli.Context) error { } func importChain(ctx *cli.Context) error { - if len(ctx.Args()) < 1 { + if ctx.Args().Len() < 1 { utils.Fatalf("This command requires an argument.") } - // Start metrics export if enabled utils.SetupMetrics(ctx) // Start system runtime metrics collection @@ -253,12 +257,12 @@ func importChain(ctx *cli.Context) error { // Import the chain start := time.Now() - if len(ctx.Args()) == 1 { + if ctx.Args().Len() == 1 { if err := utils.ImportChain(chain, ctx.Args().First()); err != nil { log.Error("Import error", "err", err) } } else { - for _, arg := range ctx.Args() { + for _, arg := range ctx.Args().Slice() { if err := utils.ImportChain(chain, arg); err != nil { log.Error("Import error", "file", arg, "err", err) } @@ -291,7 +295,7 @@ func importChain(ctx *cli.Context) error { fmt.Printf("Allocations: %.3f million\n", float64(mem.Mallocs)/1000000) fmt.Printf("GC pause: %v\n\n", time.Duration(mem.PauseTotalNs)) - if ctx.GlobalIsSet(utils.NoCompactionFlag.Name) { + if ctx.IsSet(utils.NoCompactionFlag.Name) { return nil } @@ -319,9 +323,10 @@ func importChain(ctx *cli.Context) error { } func exportChain(ctx *cli.Context) error { - if len(ctx.Args()) < 1 { + if ctx.Args().Len() < 1 { utils.Fatalf("This command requires an argument.") } + stack, _ := makeFullNode(ctx) defer stack.Close() @@ -331,7 +336,7 @@ func exportChain(ctx *cli.Context) error { var err error fp := ctx.Args().First() - if len(ctx.Args()) < 3 { + if ctx.Args().Len() < 3 { err = utils.ExportChain(chain, fp) } else { // This can be improved to allow for numbers larger than 9223372036854775807 @@ -355,9 +360,10 @@ func exportChain(ctx *cli.Context) error { // importPreimages imports preimage data from the specified file. func importPreimages(ctx *cli.Context) error { - if len(ctx.Args()) < 1 { + if ctx.Args().Len() < 1 { utils.Fatalf("This command requires an argument.") } + stack, _ := makeFullNode(ctx) defer stack.Close() @@ -374,7 +380,7 @@ func importPreimages(ctx *cli.Context) error { // exportPreimages dumps the preimage data to specified json file in streaming way. func exportPreimages(ctx *cli.Context) error { - if len(ctx.Args()) < 1 { + if ctx.Args().Len() < 1 { utils.Fatalf("This command requires an argument.") } stack, _ := makeFullNode(ctx) @@ -393,21 +399,21 @@ func exportPreimages(ctx *cli.Context) error { func copyDb(ctx *cli.Context) error { // Ensure we have a source chain directory to copy - if len(ctx.Args()) != 1 { + if ctx.Args().Len() != 1 { utils.Fatalf("Source chaindata 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) defer chainDb.Close() - syncmode := *utils.GlobalTextMarshaler(ctx, utils.SyncModeFlag.Name).(*downloader.SyncMode) + syncmode := *flags.GlobalTextMarshaler(ctx, utils.SyncModeFlag.Name).(*downloader.SyncMode) dl := downloader.New(syncmode, chainDb, new(event.TypeMux), chain, nil, nil, nil) // Create a source peer to satisfy downloader requests from - db, err := rawdb.NewLevelDBDatabase(ctx.Args().First(), ctx.GlobalInt(utils.CacheFlag.Name), 256, "") + db, err := rawdb.NewLevelDBDatabase(ctx.Args().First(), ctx.Int(utils.CacheFlag.Name), 256, "") if err != nil { return err } @@ -478,7 +484,7 @@ func dump(ctx *cli.Context) error { chain, chainDb := utils.MakeChain(ctx, stack) defer chainDb.Close() - for _, arg := range ctx.Args() { + for _, arg := range ctx.Args().Slice() { var block *types.Block if hashish(arg) { block = chain.GetBlockByHash(common.HexToHash(arg)) diff --git a/cmd/XDC/config.go b/cmd/XDC/config.go index a8ceadb894a68..5f9cbab571f9e 100644 --- a/cmd/XDC/config.go +++ b/cmd/XDC/config.go @@ -27,31 +27,31 @@ import ( "strings" "unicode" - "gopkg.in/urfave/cli.v1" - "github.com/XinFinOrg/XDPoSChain/XDCx" "github.com/XinFinOrg/XDPoSChain/cmd/utils" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/eth/ethconfig" + "github.com/XinFinOrg/XDPoSChain/internal/flags" "github.com/XinFinOrg/XDPoSChain/node" "github.com/XinFinOrg/XDPoSChain/params" "github.com/naoina/toml" + "github.com/urfave/cli/v2" ) var ( - dumpConfigCommand = cli.Command{ - Action: utils.MigrateFlags(dumpConfig), + dumpConfigCommand = &cli.Command{ + Action: dumpConfig, Name: "dumpconfig", Usage: "Show configuration values", ArgsUsage: "", - Flags: append(nodeFlags, rpcFlags...), - Category: "MISCELLANEOUS COMMANDS", + Flags: utils.GroupFlags(nodeFlags, rpcFlags), Description: `The dumpconfig command shows configuration values.`, } - configFileFlag = cli.StringFlag{ - Name: "config", - Usage: "TOML configuration file", + configFileFlag = &cli.StringFlag{ + Name: "config", + Usage: "TOML configuration file", + Category: flags.EthCategory, } ) @@ -133,24 +133,24 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, XDCConfig) { NAT: "", } // Load config file. - if file := ctx.GlobalString(configFileFlag.Name); file != "" { + if file := ctx.String(configFileFlag.Name); file != "" { if err := loadConfig(file, &cfg); err != nil { utils.Fatalf("%v", err) } } - if ctx.GlobalIsSet(utils.StakingEnabledFlag.Name) { - cfg.StakeEnable = ctx.GlobalBool(utils.StakingEnabledFlag.Name) + if ctx.IsSet(utils.StakingEnabledFlag.Name) { + cfg.StakeEnable = ctx.Bool(utils.StakingEnabledFlag.Name) } - // if !ctx.GlobalIsSet(debug.VerbosityFlag.Name) { + // if !ctx.IsSet(debug.VerbosityFlag.Name) { // debug.Verbosity(log.Lvl(cfg.Verbosity)) // } - if !ctx.GlobalIsSet(utils.NATFlag.Name) && cfg.NAT != "" { + if !ctx.IsSet(utils.NATFlag.Name) && cfg.NAT != "" { ctx.Set(utils.NATFlag.Name, cfg.NAT) } // Check testnet is enable. - if ctx.GlobalBool(utils.XDCTestnetFlag.Name) { + if ctx.Bool(utils.XDCTestnetFlag.Name) { common.IsTestnet = true common.TRC21IssuerSMC = common.TRC21IssuerSMCTestNet cfg.Eth.NetworkId = 51 @@ -159,24 +159,24 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, XDCConfig) { common.TIPXDCXCancellationFee = common.TIPXDCXCancellationFeeTestnet } - if ctx.GlobalBool(utils.EnableXDCPrefixFlag.Name) { + if ctx.Bool(utils.EnableXDCPrefixFlag.Name) { common.Enable0xPrefix = false } // Rewound - if rewound := ctx.GlobalInt(utils.RewoundFlag.Name); rewound != 0 { + if rewound := ctx.Int(utils.RewoundFlag.Name); rewound != 0 { common.Rewound = uint64(rewound) } // Check rollback hash exist. - if rollbackHash := ctx.GlobalString(utils.RollbackFlag.Name); rollbackHash != "" { + if rollbackHash := ctx.String(utils.RollbackFlag.Name); rollbackHash != "" { common.RollbackHash = common.HexToHash(rollbackHash) } // Check GasPrice common.MinGasPrice = big.NewInt(common.DefaultMinGasPrice) - if ctx.GlobalIsSet(utils.GasPriceFlag.Name) { - if gasPrice := int64(ctx.GlobalInt(utils.GasPriceFlag.Name)); gasPrice > common.DefaultMinGasPrice { + if ctx.IsSet(utils.GasPriceFlag.Name) { + if gasPrice := int64(ctx.Int(utils.GasPriceFlag.Name)); gasPrice > common.DefaultMinGasPrice { common.MinGasPrice = big.NewInt(gasPrice) } } @@ -203,8 +203,8 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, XDCConfig) { 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) + if ctx.IsSet(utils.EthStatsURLFlag.Name) { + cfg.Ethstats.URL = ctx.String(utils.EthStatsURLFlag.Name) } utils.SetXDCXConfig(ctx, &cfg.XDCX, cfg.Node.DataDir) diff --git a/cmd/XDC/consolecmd.go b/cmd/XDC/consolecmd.go index c9bf6b2982f29..a5fad4b3673ba 100644 --- a/cmd/XDC/consolecmd.go +++ b/cmd/XDC/consolecmd.go @@ -28,31 +28,29 @@ import ( "github.com/XinFinOrg/XDPoSChain/console" "github.com/XinFinOrg/XDPoSChain/node" "github.com/XinFinOrg/XDPoSChain/rpc" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) 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(nodeFlags, rpcFlags...), consoleFlags...), - Category: "CONSOLE COMMANDS", + consoleCommand = &cli.Command{ + Action: localConsole, + Name: "console", + Usage: "Start an interactive JavaScript environment", + Flags: utils.GroupFlags(nodeFlags, rpcFlags, consoleFlags), Description: ` The XDC 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/XinFinOrg/XDPoSChain/wiki/JavaScript-Console.`, } - attachCommand = cli.Command{ - Action: utils.MigrateFlags(remoteConsole), + attachCommand = &cli.Command{ + Action: remoteConsole, Name: "attach", Usage: "Start an interactive JavaScript environment (connect to node)", ArgsUsage: "[endpoint]", - Flags: append(consoleFlags, utils.DataDirFlag), - Category: "CONSOLE COMMANDS", + Flags: utils.GroupFlags([]cli.Flag{utils.DataDirFlag}, consoleFlags), Description: ` The XDC console is an interactive shell for the JavaScript runtime environment which exposes a node admin interface as well as the Ðapp JavaScript API. @@ -60,13 +58,12 @@ See https://github.com/XinFinOrg/XDPoSChain/wiki/JavaScript-Console. This command allows to open a console on a running XDC node.`, } - javascriptCommand = cli.Command{ - Action: utils.MigrateFlags(ephemeralConsole), + javascriptCommand = &cli.Command{ + Action: ephemeralConsole, Name: "js", Usage: "Execute the specified JavaScript files", ArgsUsage: " [jsfile...]", - Flags: append(nodeFlags, consoleFlags...), - Category: "CONSOLE COMMANDS", + Flags: utils.GroupFlags(nodeFlags, consoleFlags), Description: ` The JavaScript VM exposes a node admin interface as well as the Ðapp JavaScript API. See https://github.com/XinFinOrg/XDPoSChain/wiki/JavaScript-Console`, @@ -88,7 +85,7 @@ func localConsole(ctx *cli.Context) error { } config := console.Config{ DataDir: utils.MakeDataDir(ctx), - DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), + DocRoot: ctx.String(utils.JSpathFlag.Name), Client: client, Preload: utils.MakeConsolePreloads(ctx), } @@ -100,7 +97,7 @@ func localConsole(ctx *cli.Context) error { defer console.Stop(false) // If only a short execution was requested, evaluate and return - if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" { + if script := ctx.String(utils.ExecFlag.Name); script != "" { console.Evaluate(script) return nil } @@ -118,13 +115,13 @@ func remoteConsole(ctx *cli.Context) error { endpoint := ctx.Args().First() if endpoint == "" { path := node.DefaultDataDir() - if ctx.GlobalIsSet(utils.DataDirFlag.Name) { - path = ctx.GlobalString(utils.DataDirFlag.Name) + if ctx.IsSet(utils.DataDirFlag.Name) { + path = ctx.String(utils.DataDirFlag.Name) } if path != "" { - if ctx.GlobalBool(utils.TestnetFlag.Name) { + if ctx.Bool(utils.TestnetFlag.Name) { path = filepath.Join(path, "testnet") - } else if ctx.GlobalBool(utils.RinkebyFlag.Name) { + } else if ctx.Bool(utils.RinkebyFlag.Name) { path = filepath.Join(path, "rinkeby") } } @@ -137,7 +134,7 @@ func remoteConsole(ctx *cli.Context) error { } config := console.Config{ DataDir: utils.MakeDataDir(ctx), - DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), + DocRoot: ctx.String(utils.JSpathFlag.Name), Client: client, Preload: utils.MakeConsolePreloads(ctx), } @@ -148,7 +145,7 @@ func remoteConsole(ctx *cli.Context) error { } defer console.Stop(false) - if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" { + if script := ctx.String(utils.ExecFlag.Name); script != "" { console.Evaluate(script) return nil } @@ -190,7 +187,7 @@ func ephemeralConsole(ctx *cli.Context) error { } config := console.Config{ DataDir: utils.MakeDataDir(ctx), - DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), + DocRoot: ctx.String(utils.JSpathFlag.Name), Client: client, Preload: utils.MakeConsolePreloads(ctx), } @@ -202,7 +199,7 @@ func ephemeralConsole(ctx *cli.Context) error { defer console.Stop(false) // Evaluate each of the specified JavaScript files - for _, file := range ctx.Args() { + for _, file := range ctx.Args().Slice() { if err = console.Execute(file); err != nil { utils.Fatalf("Failed to execute %s: %v", file, err) } diff --git a/cmd/XDC/consolecmd_test.go b/cmd/XDC/consolecmd_test.go index ecbd11762aee4..9ca2e0b73ed4f 100644 --- a/cmd/XDC/consolecmd_test.go +++ b/cmd/XDC/consolecmd_test.go @@ -39,13 +39,14 @@ const ( // then terminated by closing the input stream. func TestConsoleWelcome(t *testing.T) { coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182" + datadir := tmpdir(t) + defer os.RemoveAll(datadir) // Start a XDC console, make sure it's cleaned up and terminate the console XDC := runXDC(t, - "--XDCx.datadir", tmpdir(t)+"XDCx/"+time.Now().String(), + "console", "--datadir", datadir, "--XDCx.datadir", datadir+"/XDCx/"+time.Now().String(), "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", - "--etherbase", coinbase, - "console") + "--etherbase", coinbase) // Gather all the infos the welcome message needs to contain XDC.SetTemplateFunc("goos", func() string { return runtime.GOOS }) @@ -76,16 +77,16 @@ at block: 0 ({{niltime}}) func TestIPCAttachWelcome(t *testing.T) { // Configure the instance for IPC attachement coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182" + datadir := tmpdir(t) + defer os.RemoveAll(datadir) var ipc string if runtime.GOOS == "windows" { ipc = `\\.\pipe\XDC` + strconv.Itoa(trulyRandInt(100000, 999999)) } else { - ws := tmpdir(t) - defer os.RemoveAll(ws) - ipc = filepath.Join(ws, "XDC.ipc") + ipc = filepath.Join(datadir, "XDC.ipc") } XDC := runXDC(t, - "--XDCx.datadir", tmpdir(t)+"XDCx/"+time.Now().String(), + "--datadir", datadir, "--XDCx.datadir", datadir+"/XDCx/"+time.Now().String(), "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--etherbase", coinbase, "--ipcpath", ipc) @@ -99,8 +100,10 @@ func TestIPCAttachWelcome(t *testing.T) { func TestHTTPAttachWelcome(t *testing.T) { coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182" port := strconv.Itoa(trulyRandInt(1024, 65536)) // Yeah, sometimes this will fail, sorry :P + datadir := tmpdir(t) + defer os.RemoveAll(datadir) XDC := runXDC(t, - "--XDCx.datadir", tmpdir(t)+"XDCx/"+time.Now().String(), + "--datadir", datadir, "--XDCx.datadir", datadir+"/XDCx/"+time.Now().String(), "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--etherbase", coinbase, "--rpc", "--rpcport", port) @@ -114,9 +117,10 @@ func TestHTTPAttachWelcome(t *testing.T) { func TestWSAttachWelcome(t *testing.T) { coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182" port := strconv.Itoa(trulyRandInt(1024, 65536)) // Yeah, sometimes this will fail, sorry :P - + datadir := tmpdir(t) + defer os.RemoveAll(datadir) XDC := runXDC(t, - "--XDCx.datadir", tmpdir(t)+"XDCx/"+time.Now().String(), + "--datadir", datadir, "--XDCx.datadir", datadir+"/XDCx/"+time.Now().String(), "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--etherbase", coinbase, "--ws", "--wsport", port) diff --git a/cmd/XDC/dao_test.go b/cmd/XDC/dao_test.go index 030e255517c3b..5444a4b13761e 100644 --- a/cmd/XDC/dao_test.go +++ b/cmd/XDC/dao_test.go @@ -111,11 +111,10 @@ func testDAOForkBlockNewChain(t *testing.T, test int, genesis string, expectBloc if err := os.WriteFile(json, []byte(genesis), 0600); err != nil { t.Fatalf("test %d: failed to write genesis file: %v", test, err) } - runXDC(t, "--datadir", datadir, "init", json).WaitExit() + runXDC(t, "init", "--datadir", datadir, json).WaitExit() } else { // Force chain initialization - args := []string{"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir} - XDC := runXDC(t, append(args, []string{"--exec", "2+2", "console"}...)...) + XDC := runXDC(t, "console", "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir, "--exec", "2+2") XDC.WaitExit() } // Retrieve the DAO config flag from the database diff --git a/cmd/XDC/main.go b/cmd/XDC/main.go index dcf2613ab9864..a736c81e27d93 100644 --- a/cmd/XDC/main.go +++ b/cmd/XDC/main.go @@ -33,14 +33,14 @@ import ( "github.com/XinFinOrg/XDPoSChain/eth" "github.com/XinFinOrg/XDPoSChain/ethclient" "github.com/XinFinOrg/XDPoSChain/internal/debug" + "github.com/XinFinOrg/XDPoSChain/internal/flags" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/metrics" "github.com/XinFinOrg/XDPoSChain/node" + "github.com/urfave/cli/v2" // Force-load the native, to trigger registration _ "github.com/XinFinOrg/XDPoSChain/eth/tracers/native" - - "gopkg.in/urfave/cli.v1" ) const ( @@ -51,7 +51,7 @@ var ( // Git SHA1 commit hash of the release (set via linker flags) gitCommit = "" // The app that holds all commands and flags. - app = utils.NewApp(gitCommit, "the XDPoSChain command line interface") + app = flags.NewApp(gitCommit, "the XDPoSChain command line interface") // flags that configure the node nodeFlags = []cli.Flag{ utils.IdentityFlag, @@ -168,8 +168,8 @@ func init() { // Initialize the CLI app and start XDC app.Action = XDC app.HideVersion = true // we have a command to print the version - app.Copyright = "Copyright (c) 2018 XDPoSChain" - app.Commands = []cli.Command{ + app.Copyright = "Copyright (c) 2024 XDPoSChain" + app.Commands = []*cli.Command{ // See chaincmd.go: initCommand, importCommand, @@ -197,6 +197,7 @@ func init() { app.Before = func(ctx *cli.Context) error { runtime.GOMAXPROCS(runtime.NumCPU()) + flags.MigrateGlobalFlags(ctx) if err := debug.Setup(ctx); err != nil { return err } @@ -242,11 +243,11 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) { // Unlock any account specifically requested ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - if ctx.GlobalIsSet(utils.UnlockedAccountFlag.Name) { - cfg.Account.Unlocks = strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") + if ctx.IsSet(utils.UnlockedAccountFlag.Name) { + cfg.Account.Unlocks = strings.Split(ctx.String(utils.UnlockedAccountFlag.Name), ",") } - if ctx.GlobalIsSet(utils.PasswordFileFlag.Name) { + if ctx.IsSet(utils.PasswordFileFlag.Name) { cfg.Account.Passwords = utils.MakePasswordList(ctx) } @@ -299,7 +300,7 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) { // Start auxiliary services if enabled // Mining only makes sense if a full Ethereum node is running - if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { + if ctx.Bool(utils.LightModeFlag.Name) || ctx.String(utils.SyncModeFlag.Name) == "light" { utils.Fatalf("Light clients do not support staking") } // Start metrics export if enabled @@ -315,7 +316,7 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) { go func() { started := false ok := false - slaveMode := ctx.GlobalIsSet(utils.XDCSlaveModeFlag.Name) + slaveMode := ctx.IsSet(utils.XDCSlaveModeFlag.Name) var err error ok, err = ethereum.ValidateMasternode() if err != nil { @@ -328,7 +329,7 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) { } else { log.Info("Masternode found. Enabling staking mode...") // Use a reduced number of threads if requested - if threads := ctx.GlobalInt(utils.StakerThreadsFlag.Name); threads > 0 { + if threads := ctx.Int(utils.StakerThreadsFlag.Name); threads > 0 { type threaded interface { SetThreads(threads int) } @@ -370,7 +371,7 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) { } else { log.Info("Masternode found. Enabling staking mode...") // Use a reduced number of threads if requested - if threads := ctx.GlobalInt(utils.StakerThreadsFlag.Name); threads > 0 { + if threads := ctx.Int(utils.StakerThreadsFlag.Name); threads > 0 { type threaded interface { SetThreads(threads int) } diff --git a/cmd/XDC/misccmd.go b/cmd/XDC/misccmd.go index e86f7c27cccd8..65a0ae0d80e54 100644 --- a/cmd/XDC/misccmd.go +++ b/cmd/XDC/misccmd.go @@ -28,16 +28,15 @@ import ( "github.com/XinFinOrg/XDPoSChain/eth" "github.com/XinFinOrg/XDPoSChain/eth/ethconfig" "github.com/XinFinOrg/XDPoSChain/params" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) var ( - makecacheCommand = cli.Command{ - Action: utils.MigrateFlags(makecache), + makecacheCommand = &cli.Command{ + Action: makecache, Name: "makecache", Usage: "Generate ethash verification cache (for testing)", ArgsUsage: " ", - Category: "MISCELLANEOUS COMMANDS", Description: ` The makecache command generates an ethash cache in . @@ -45,12 +44,11 @@ This command exists to support the system testing project. Regular users do not need to execute it. `, } - makedagCommand = cli.Command{ - Action: utils.MigrateFlags(makedag), + makedagCommand = &cli.Command{ + Action: makedag, Name: "makedag", Usage: "Generate ethash mining DAG (for testing)", ArgsUsage: " ", - Category: "MISCELLANEOUS COMMANDS", Description: ` The makedag command generates an ethash DAG in . @@ -58,28 +56,26 @@ This command exists to support the system testing project. Regular users do not need to execute it. `, } - versionCommand = cli.Command{ - Action: utils.MigrateFlags(version), + versionCommand = &cli.Command{ + Action: 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), + licenseCommand = &cli.Command{ + Action: 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() + args := ctx.Args().Slice() if len(args) != 2 { utils.Fatalf(`Usage: XDC makecache `) } @@ -94,7 +90,7 @@ func makecache(ctx *cli.Context) error { // makedag generates an ethash mining DAG into the provided folder. func makedag(ctx *cli.Context) error { - args := ctx.Args() + args := ctx.Args().Slice() if len(args) != 2 { utils.Fatalf(`Usage: XDC makedag `) } diff --git a/cmd/XDC/run_test.go b/cmd/XDC/run_test.go index 82b4c8fd58622..231385e1ac19c 100644 --- a/cmd/XDC/run_test.go +++ b/cmd/XDC/run_test.go @@ -66,12 +66,12 @@ func runXDC(t *testing.T, args ...string) *testXDC { tt := &testXDC{} tt.TestCmd = cmdtest.NewTestCmd(t, tt) for i, arg := range args { - switch { - case arg == "-datadir" || arg == "--datadir": + switch arg { + case "--datadir": if i < len(args)-1 { tt.Datadir = args[i+1] } - case arg == "-etherbase" || arg == "--etherbase": + case "--etherbase": if i < len(args)-1 { tt.Etherbase = args[i+1] } @@ -80,7 +80,7 @@ func runXDC(t *testing.T, args ...string) *testXDC { if tt.Datadir == "" { tt.Datadir = tmpdir(t) tt.Cleanup = func() { os.RemoveAll(tt.Datadir) } - args = append([]string{"-datadir", tt.Datadir}, args...) + args = append([]string{"--datadir", tt.Datadir}, args...) // Remove the temporary datadir if something fails below. defer func() { if t.Failed() { diff --git a/cmd/XDC/usage.go b/cmd/XDC/usage.go deleted file mode 100644 index 2fdfdd9576c2a..0000000000000 --- a/cmd/XDC/usage.go +++ /dev/null @@ -1,329 +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 . - -// Contains the XDC command usage template and generator. - -package main - -import ( - "io" - "sort" - - "github.com/XinFinOrg/XDPoSChain/cmd/utils" - "github.com/XinFinOrg/XDPoSChain/internal/debug" - "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 (c) 2018 XDPoSChain - -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: "XDPoSChain", - Flags: []cli.Flag{ - configFileFlag, - utils.DataDirFlag, - utils.KeyStoreDirFlag, - //utils.NoUSBFlag, - utils.NetworkIdFlag, - //utils.TestnetFlag, - //utils.RinkebyFlag, - utils.SyncModeFlag, - utils.GCModeFlag, - utils.EthStatsURLFlag, - utils.IdentityFlag, - //utils.LightServFlag, - //utils.LightPeersFlag, - //utils.LightKDFFlag, - }, - }, - //{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.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.CacheGCFlag, - // utils.TrieCacheGenFlag, - utils.FDLimitFlag, - }, - }, - { - Name: "ACCOUNT", - Flags: []cli.Flag{ - utils.UnlockedAccountFlag, - utils.PasswordFileFlag, - }, - }, - { - Name: "API AND CONSOLE", - Flags: []cli.Flag{ - utils.RPCEnabledFlag, - utils.RPCGlobalGasCapFlag, - utils.RPCListenAddrFlag, - utils.RPCPortFlag, - utils.RPCHttpReadTimeoutFlag, - utils.RPCHttpWriteTimeoutFlag, - utils.RPCHttpIdleTimeoutFlag, - utils.RPCApiFlag, - utils.WSEnabledFlag, - utils.WSListenAddrFlag, - utils.WSPortFlag, - utils.WSApiFlag, - utils.WSAllowedOriginsFlag, - utils.IPCDisabledFlag, - utils.IPCPathFlag, - utils.RPCCORSDomainFlag, - utils.RPCVirtualHostsFlag, - utils.RPCGlobalTxFeeCap, - 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: "STAKER", - Flags: []cli.Flag{ - utils.StakingEnabledFlag, - utils.StakerThreadsFlag, - utils.EtherbaseFlag, - utils.TargetGasLimitFlag, - utils.GasPriceFlag, - utils.ExtraDataFlag, - }, - }, - //{ - // Name: "GAS PRICE ORACLE", - // Flags: []cli.Flag{ - // utils.GpoBlocksFlag, - // utils.GpoPercentileFlag, - // utils.GpoMaxGasPriceFlag, - // utils.GpoIgnoreGasPriceFlag, - // }, - //}, - //{ - // Name: "VIRTUAL MACHINE", - // Flags: []cli.Flag{ - // utils.VMEnableDebugFlag, - // }, - //}, - { - Name: "LOGGING AND DEBUGGING", - Flags: append([]cli.Flag{ - utils.MetricsEnabledFlag, - //utils.FakePoWFlag, - //utils.NoCompactionFlag, - }, debug.Flags...), - }, - { - Name: "DEPRECATED", - Flags: []cli.Flag{ - utils.FastSyncFlag, - utils.LightModeFlag, - }, - }, - { - 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{}{} - } - } - uncategorized := []cli.Flag{} - for _, flag := range data.(*cli.App).Flags { - if _, ok := categorized[flag.String()]; !ok { - 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) - } - } -} diff --git a/cmd/abigen/main.go b/cmd/abigen/main.go index a8c3ebfc8cf9d..9a19efe96fca5 100644 --- a/cmd/abigen/main.go +++ b/cmd/abigen/main.go @@ -18,50 +18,101 @@ package main import ( "encoding/json" - "flag" "fmt" "os" "strings" "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind" "github.com/XinFinOrg/XDPoSChain/common/compiler" + "github.com/XinFinOrg/XDPoSChain/internal/flags" + "github.com/XinFinOrg/XDPoSChain/log" + "github.com/urfave/cli/v2" ) var ( - abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind") - binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)") - typFlag = flag.String("type", "", "Struct name for the binding (default = package name)") + // Git SHA1 commit hash of the release (set via linker flags) + gitCommit = "" - solFlag = flag.String("sol", "", "Path to the Ethereum contract Solidity source to build and bind") - solcFlag = flag.String("solc", "solc", "Solidity compiler to use if source builds are requested") - excFlag = flag.String("exc", "", "Comma separated types to exclude from binding") + app *cli.App +) - pkgFlag = flag.String("pkg", "", "Package name to generate the binding into") - outFlag = flag.String("out", "", "Output file for the generated binding (default = stdout)") - langFlag = flag.String("lang", "go", "Destination language for the bindings (go)") +var ( + // Flags needed by abigen + abiFlag = &cli.StringFlag{ + Name: "abi", + Usage: "Path to the Ethereum contract ABI json to bind", + } + binFlag = &cli.StringFlag{ + Name: "bin", + Usage: "Path to the Ethereum contract bytecode (generate deploy method)", + } + typeFlag = &cli.StringFlag{ + Name: "type", + Usage: "Struct name for the binding (default = package name)", + } + solFlag = &cli.StringFlag{ + Name: "sol", + Usage: "Path to the Ethereum contract Solidity source to build and bind", + } + solcFlag = &cli.StringFlag{ + Name: "solc", + Usage: "Solidity compiler to use if source builds are requested", + Value: "solc", + } + excFlag = &cli.StringFlag{ + Name: "exc", + Usage: "Comma separated types to exclude from binding", + } + pkgFlag = &cli.StringFlag{ + Name: "pkg", + Usage: "Package name to generate the binding into", + } + outFlag = &cli.StringFlag{ + Name: "out", + Usage: "Output file for the generated binding (default = stdout)", + } + langFlag = &cli.StringFlag{ + Name: "lang", + Usage: "Destination language for the bindings (go)", + Value: "go", + } ) -func main() { - // Parse and ensure all needed inputs are specified - flag.Parse() +func init() { + app = flags.NewApp(gitCommit, "ethereum checkpoint helper tool") + app.Name = "abigen" + app.Flags = []cli.Flag{ + abiFlag, + binFlag, + typeFlag, + solFlag, + solcFlag, + excFlag, + pkgFlag, + outFlag, + langFlag, + } + app.Action = abigen +} - if *abiFlag == "" && *solFlag == "" { +func abigen(c *cli.Context) error { + if c.String(abiFlag.Name) == "" && c.String(solFlag.Name) == "" { fmt.Printf("No contract ABI (--abi) or Solidity source (--sol) specified\n") os.Exit(-1) - } else if (*abiFlag != "" || *binFlag != "" || *typFlag != "") && *solFlag != "" { + } else if (c.String(abiFlag.Name) != "" || c.String(binFlag.Name) != "" || c.String(typeFlag.Name) != "") && c.String(solFlag.Name) != "" { fmt.Printf("Contract ABI (--abi), bytecode (--bin) and type (--type) flags are mutually exclusive with the Solidity source (--sol) flag\n") os.Exit(-1) } - if *pkgFlag == "" { + if c.String(pkgFlag.Name) == "" { fmt.Printf("No destination package specified (--pkg)\n") os.Exit(-1) } var lang bind.Lang - switch *langFlag { + switch c.String(langFlag.Name) { case "go": lang = bind.LangGo default: - fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", *langFlag) + fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", c.String(langFlag.Name)) os.Exit(-1) } // If the entire solidity code was specified, build and bind based on that @@ -70,13 +121,13 @@ func main() { bins []string types []string ) - if *solFlag != "" { + if c.String(solFlag.Name) != "" { // Generate the list of types to exclude from binding exclude := make(map[string]bool) - for _, kind := range strings.Split(*excFlag, ",") { + for _, kind := range strings.Split(c.String(excFlag.Name), ",") { exclude[strings.ToLower(kind)] = true } - contracts, err := compiler.CompileSolidity(*solcFlag, *solFlag) + contracts, err := compiler.CompileSolidity(c.String(solcFlag.Name), c.String(solFlag.Name)) if err != nil { fmt.Printf("Failed to build Solidity contract: %v\n", err) os.Exit(-1) @@ -95,7 +146,7 @@ func main() { } } else { // Otherwise load up the ABI, optional bytecode and type name from the parameters - abi, err := os.ReadFile(*abiFlag) + abi, err := os.ReadFile(c.String(abiFlag.Name)) if err != nil { fmt.Printf("Failed to read input ABI: %v\n", err) os.Exit(-1) @@ -103,33 +154,43 @@ func main() { abis = append(abis, string(abi)) bin := []byte{} - if *binFlag != "" { - if bin, err = os.ReadFile(*binFlag); err != nil { + if c.String(binFlag.Name) != "" { + if bin, err = os.ReadFile(c.String(binFlag.Name)); err != nil { fmt.Printf("Failed to read input bytecode: %v\n", err) os.Exit(-1) } } bins = append(bins, string(bin)) - kind := *typFlag + kind := c.String(typeFlag.Name) if kind == "" { - kind = *pkgFlag + kind = c.String(pkgFlag.Name) } types = append(types, kind) } // Generate the contract binding - code, err := bind.Bind(types, abis, bins, *pkgFlag, lang) + code, err := bind.Bind(types, abis, bins, c.String(pkgFlag.Name), lang) if err != nil { fmt.Printf("Failed to generate ABI binding: %v\n", err) os.Exit(-1) } // Either flush it out to a file or display on the standard output - if *outFlag == "" { + if c.String(outFlag.Name) == "" { fmt.Printf("%s\n", code) - return + return nil } - if err := os.WriteFile(*outFlag, []byte(code), 0600); err != nil { + if err := os.WriteFile(c.String(outFlag.Name), []byte(code), 0600); err != nil { fmt.Printf("Failed to write ABI binding: %v\n", err) os.Exit(-1) } + return nil +} + +func main() { + log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true))) + + if err := app.Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } diff --git a/cmd/ethkey/generate.go b/cmd/ethkey/generate.go index 2f61c7a8f1088..6da3f8beb6aff 100644 --- a/cmd/ethkey/generate.go +++ b/cmd/ethkey/generate.go @@ -26,7 +26,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/cmd/utils" "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/pborman/uuid" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) type outputGenerate struct { @@ -34,7 +34,14 @@ type outputGenerate struct { AddressEIP55 string } -var commandGenerate = cli.Command{ +var ( + privateKeyFlag = &cli.StringFlag{ + Name: "privatekey", + Usage: "file containing a raw private key to encrypt", + } +) + +var commandGenerate = &cli.Command{ Name: "generate", Usage: "generate new keyfile", ArgsUsage: "[ ]", @@ -47,10 +54,7 @@ If you want to encrypt an existing private key, it can be specified by setting Flags: []cli.Flag{ passphraseFlag, jsonFlag, - cli.StringFlag{ - Name: "privatekey", - Usage: "file containing a raw private key to encrypt", - }, + privateKeyFlag, }, Action: func(ctx *cli.Context) error { // Check if keyfile path given and make sure it doesn't already exist. diff --git a/cmd/ethkey/inspect.go b/cmd/ethkey/inspect.go index efd6b4589dcf3..f8baa953c9eb5 100644 --- a/cmd/ethkey/inspect.go +++ b/cmd/ethkey/inspect.go @@ -24,7 +24,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/accounts/keystore" "github.com/XinFinOrg/XDPoSChain/cmd/utils" "github.com/XinFinOrg/XDPoSChain/crypto" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) type outputInspect struct { @@ -33,7 +33,14 @@ type outputInspect struct { PrivateKey string } -var commandInspect = cli.Command{ +var ( + privateFlag = &cli.BoolFlag{ + Name: "private", + Usage: "include the private key in the output", + } +) + +var commandInspect = &cli.Command{ Name: "inspect", Usage: "inspect a keyfile", ArgsUsage: "", @@ -45,10 +52,7 @@ make sure to use this feature with great caution!`, Flags: []cli.Flag{ passphraseFlag, jsonFlag, - cli.BoolFlag{ - Name: "private", - Usage: "include the private key in the output", - }, + privateFlag, }, Action: func(ctx *cli.Context) error { keyfilepath := ctx.Args().First() diff --git a/cmd/ethkey/main.go b/cmd/ethkey/main.go index 323bb9e1aba69..f1840227a3643 100644 --- a/cmd/ethkey/main.go +++ b/cmd/ethkey/main.go @@ -20,8 +20,8 @@ import ( "fmt" "os" - "github.com/XinFinOrg/XDPoSChain/cmd/utils" - "gopkg.in/urfave/cli.v1" + "github.com/XinFinOrg/XDPoSChain/internal/flags" + "github.com/urfave/cli/v2" ) const ( @@ -34,8 +34,8 @@ var gitCommit = "" var app *cli.App func init() { - app = utils.NewApp(gitCommit, "an Ethereum key manager") - app.Commands = []cli.Command{ + app = flags.NewApp(gitCommit, "an Ethereum key manager") + app.Commands = []*cli.Command{ commandGenerate, commandInspect, commandSignMessage, @@ -45,15 +45,15 @@ func init() { // Commonly used command line flags. var ( - passphraseFlag = cli.StringFlag{ + passphraseFlag = &cli.StringFlag{ Name: "passwordfile", - Usage: "the file that contains the passphrase for the keyfile", + Usage: "the file that contains the password for the keyfile", } - jsonFlag = cli.BoolFlag{ + jsonFlag = &cli.BoolFlag{ Name: "json", Usage: "output JSON instead of human-readable format", } - messageFlag = cli.StringFlag{ + messageFlag = &cli.StringFlag{ Name: "message", Usage: "the file that contains the message to sign/verify", } diff --git a/cmd/ethkey/message.go b/cmd/ethkey/message.go index 9442785f6882a..3566475c7cda1 100644 --- a/cmd/ethkey/message.go +++ b/cmd/ethkey/message.go @@ -25,19 +25,19 @@ import ( "github.com/XinFinOrg/XDPoSChain/cmd/utils" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/crypto" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) type outputSign struct { Signature string } -var msgfileFlag = cli.StringFlag{ +var msgfileFlag = &cli.StringFlag{ Name: "msgfile", Usage: "file containing the message to sign/verify", } -var commandSignMessage = cli.Command{ +var commandSignMessage = &cli.Command{ Name: "signmessage", Usage: "sign a message", ArgsUsage: " ", @@ -88,7 +88,7 @@ type outputVerify struct { RecoveredPublicKey string } -var commandVerifyMessage = cli.Command{ +var commandVerifyMessage = &cli.Command{ Name: "verifymessage", Usage: "verify the signature of a signed message", ArgsUsage: "
", @@ -143,7 +143,7 @@ It is possible to refer to a file containing the message.`, func getMessage(ctx *cli.Context, msgarg int) []byte { if file := ctx.String("msgfile"); file != "" { - if len(ctx.Args()) > msgarg { + if ctx.NArg() > msgarg { utils.Fatalf("Can't use --msgfile and message argument at the same time.") } msg, err := os.ReadFile(file) @@ -151,9 +151,9 @@ func getMessage(ctx *cli.Context, msgarg int) []byte { utils.Fatalf("Can't read message file: %v", err) } return msg - } else if len(ctx.Args()) == msgarg+1 { + } else if ctx.NArg() == msgarg+1 { return []byte(ctx.Args().Get(msgarg)) } - utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, len(ctx.Args())) + utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, ctx.NArg()) return nil } diff --git a/cmd/ethkey/utils.go b/cmd/ethkey/utils.go index cd32c5d80104c..6f1b681ef03b5 100644 --- a/cmd/ethkey/utils.go +++ b/cmd/ethkey/utils.go @@ -25,7 +25,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/cmd/utils" "github.com/XinFinOrg/XDPoSChain/console" "github.com/XinFinOrg/XDPoSChain/crypto" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) // getPassPhrase obtains a passphrase given by the user. It first checks the diff --git a/cmd/evm/compiler.go b/cmd/evm/compiler.go index 0206fed0efdd5..b2f45e2f911f3 100644 --- a/cmd/evm/compiler.go +++ b/cmd/evm/compiler.go @@ -22,11 +22,10 @@ import ( "os" "github.com/XinFinOrg/XDPoSChain/cmd/evm/internal/compiler" - - cli "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) -var compileCommand = cli.Command{ +var compileCommand = &cli.Command{ Action: compileCmd, Name: "compile", Usage: "compiles easm source to evm binary", @@ -34,7 +33,7 @@ var compileCommand = cli.Command{ } func compileCmd(ctx *cli.Context) error { - debug := ctx.GlobalBool(DebugFlag.Name) + debug := ctx.Bool(DebugFlag.Name) if len(ctx.Args().First()) == 0 { return errors.New("filename required") diff --git a/cmd/evm/disasm.go b/cmd/evm/disasm.go index 72ca7683d676d..2e09f5aab693c 100644 --- a/cmd/evm/disasm.go +++ b/cmd/evm/disasm.go @@ -23,10 +23,10 @@ import ( "strings" "github.com/XinFinOrg/XDPoSChain/core/asm" - cli "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) -var disasmCommand = cli.Command{ +var disasmCommand = &cli.Command{ Action: disasmCmd, Name: "disasm", Usage: "disassembles evm binary", @@ -34,17 +34,22 @@ var disasmCommand = cli.Command{ } func disasmCmd(ctx *cli.Context) error { - if len(ctx.Args().First()) == 0 { - return errors.New("filename required") + var in string + switch { + case len(ctx.Args().First()) > 0: + fn := ctx.Args().First() + input, err := os.ReadFile(fn) + if err != nil { + return err + } + in = string(input) + case ctx.IsSet(InputFlag.Name): + in = ctx.String(InputFlag.Name) + default: + return errors.New("missing filename or --input value") } - fn := ctx.Args().First() - in, err := os.ReadFile(fn) - if err != nil { - return err - } - - code := strings.TrimSpace(string(in[:])) + code := strings.TrimSpace(in) fmt.Printf("%v\n", code) return asm.PrintDisassembled(code) } diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 18de3710d2c55..0ac8e896e2bd1 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -22,101 +22,126 @@ import ( "math/big" "os" - "github.com/XinFinOrg/XDPoSChain/cmd/utils" - "gopkg.in/urfave/cli.v1" + "github.com/XinFinOrg/XDPoSChain/internal/flags" + "github.com/urfave/cli/v2" ) -var gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags) - var ( - app = utils.NewApp(gitCommit, "the evm command line interface") + gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags) - DebugFlag = cli.BoolFlag{ - Name: "debug", - Usage: "output full trace logs", - } - MemProfileFlag = cli.StringFlag{ - Name: "memprofile", - Usage: "creates a memory profile at the given path", - } - CPUProfileFlag = cli.StringFlag{ - Name: "cpuprofile", - Usage: "creates a CPU profile at the given path", - } - StatDumpFlag = cli.BoolFlag{ - Name: "statdump", - Usage: "displays stack and heap memory information", - } - CodeFlag = cli.StringFlag{ - Name: "code", - Usage: "EVM code", - } - CodeFileFlag = cli.StringFlag{ - Name: "codefile", - Usage: "File containing EVM code. If '-' is specified, code is read from stdin ", - } - GasFlag = cli.Uint64Flag{ - Name: "gas", - Usage: "gas limit for the evm", - Value: 10000000000, - } - PriceFlag = utils.BigFlag{ - Name: "price", - Usage: "price set for the evm", - Value: new(big.Int), - } - ValueFlag = utils.BigFlag{ - Name: "value", - Usage: "value set for the evm", - Value: new(big.Int), - } - DumpFlag = cli.BoolFlag{ - Name: "dump", - Usage: "dumps the state after the run", - } - InputFlag = cli.StringFlag{ - Name: "input", - Usage: "input for the EVM", - } - VerbosityFlag = cli.IntFlag{ - Name: "verbosity", - Usage: "sets the verbosity level", - } - CreateFlag = cli.BoolFlag{ - Name: "create", - Usage: "indicates the action should be create rather than call", - } - GenesisFlag = cli.StringFlag{ - Name: "prestate", - Usage: "JSON file with prestate (genesis) config", - } - MachineFlag = cli.BoolFlag{ - Name: "json", - Usage: "output trace logs in machine readable format (json)", - } - SenderFlag = cli.StringFlag{ - Name: "sender", - Usage: "The transaction origin", - } - ReceiverFlag = cli.StringFlag{ - Name: "receiver", - Usage: "The transaction receiver (execution context)", - } - DisableMemoryFlag = cli.BoolFlag{ - Name: "nomemory", - Usage: "disable memory output", - } - DisableStackFlag = cli.BoolFlag{ - Name: "nostack", - Usage: "disable stack output", + app = flags.NewApp(gitCommit, "the evm command line interface") +) + +var ( + DebugFlag = &cli.BoolFlag{ + Name: "debug", + Usage: "output full trace logs", + Category: flags.VMCategory, + } + MemProfileFlag = &cli.StringFlag{ + Name: "memprofile", + Usage: "creates a memory profile at the given path", + Category: flags.VMCategory, + } + CPUProfileFlag = &cli.StringFlag{ + Name: "cpuprofile", + Usage: "creates a CPU profile at the given path", + Category: flags.VMCategory, + } + StatDumpFlag = &cli.BoolFlag{ + Name: "statdump", + Usage: "displays stack and heap memory information", + Category: flags.VMCategory, + } + CodeFlag = &cli.StringFlag{ + Name: "code", + Usage: "EVM code", + Category: flags.VMCategory, + } + CodeFileFlag = &cli.StringFlag{ + Name: "codefile", + Usage: "File containing EVM code. If '-' is specified, code is read from stdin ", + Category: flags.VMCategory, + } + GasFlag = &cli.Uint64Flag{ + Name: "gas", + Usage: "gas limit for the evm", + Value: 10000000000, + Category: flags.VMCategory, + } + PriceFlag = &flags.BigFlag{ + Name: "price", + Usage: "price set for the evm", + Value: new(big.Int), + Category: flags.VMCategory, + } + ValueFlag = &flags.BigFlag{ + Name: "value", + Usage: "value set for the evm", + Value: new(big.Int), + Category: flags.VMCategory, + } + DumpFlag = &cli.BoolFlag{ + Name: "dump", + Usage: "dumps the state after the run", + Category: flags.VMCategory, + } + InputFlag = &cli.StringFlag{ + Name: "input", + Usage: "input for the EVM", + Category: flags.VMCategory, + } + VerbosityFlag = &cli.IntFlag{ + Name: "verbosity", + Usage: "sets the verbosity level", + Category: flags.VMCategory, + } + CreateFlag = &cli.BoolFlag{ + Name: "create", + Usage: "indicates the action should be create rather than call", + Category: flags.VMCategory, + } + GenesisFlag = &cli.StringFlag{ + Name: "prestate", + Usage: "JSON file with prestate (genesis) config", + Category: flags.VMCategory, + } + MachineFlag = &cli.BoolFlag{ + Name: "json", + Usage: "output trace logs in machine readable format (json)", + Category: flags.VMCategory, + } + SenderFlag = &cli.StringFlag{ + Name: "sender", + Usage: "The transaction origin", + Category: flags.VMCategory, + } + ReceiverFlag = &cli.StringFlag{ + Name: "receiver", + Usage: "The transaction receiver (execution context)", + Category: flags.VMCategory, + } + DisableMemoryFlag = &cli.BoolFlag{ + Name: "nomemory", + Value: true, + Usage: "disable memory output", + Category: flags.VMCategory, + } + DisableStackFlag = &cli.BoolFlag{ + Name: "nostack", + Usage: "disable stack output", + Category: flags.VMCategory, } DisableStorageFlag = &cli.BoolFlag{ Name: "nostorage", Usage: "disable storage output", + Category: flags.VMCategory, } DisableReturnDataFlag = &cli.BoolFlag{ Name: "noreturndata", + Value: true, Usage: "enable return data output", + Category: flags.VMCategory, } ) @@ -142,7 +167,7 @@ func init() { DisableMemoryFlag, DisableStackFlag, } - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ compileCommand, disasmCommand, runCommand, diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index cc71f4214ac87..05adeae2be9ff 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -34,11 +34,12 @@ import ( "github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/vm" "github.com/XinFinOrg/XDPoSChain/core/vm/runtime" + "github.com/XinFinOrg/XDPoSChain/internal/flags" "github.com/XinFinOrg/XDPoSChain/params" - cli "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) -var runCommand = cli.Command{ +var runCommand = &cli.Command{ Action: runCmd, Name: "run", Usage: "run arbitrary evm binary", @@ -69,11 +70,11 @@ func readGenesis(genesisPath string) *core.Genesis { func runCmd(ctx *cli.Context) error { logconfig := &vm.LogConfig{ - EnableMemory: !ctx.GlobalBool(DisableMemoryFlag.Name), - DisableStack: ctx.GlobalBool(DisableStackFlag.Name), - DisableStorage: ctx.GlobalBool(DisableStorageFlag.Name), - EnableReturnData: !ctx.GlobalBool(DisableReturnDataFlag.Name), - Debug: ctx.GlobalBool(DebugFlag.Name), + EnableMemory: !ctx.Bool(DisableMemoryFlag.Name), + DisableStack: ctx.Bool(DisableStackFlag.Name), + DisableStorage: ctx.Bool(DisableStorageFlag.Name), + EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name), + Debug: ctx.Bool(DebugFlag.Name), } var ( @@ -84,17 +85,17 @@ func runCmd(ctx *cli.Context) error { sender = common.StringToAddress("sender") receiver = common.StringToAddress("receiver") ) - if ctx.GlobalBool(MachineFlag.Name) { + if ctx.Bool(MachineFlag.Name) { tracer = vm.NewJSONLogger(logconfig, os.Stdout) - } else if ctx.GlobalBool(DebugFlag.Name) { + } else if ctx.Bool(DebugFlag.Name) { debugLogger = vm.NewStructLogger(logconfig) tracer = debugLogger } else { debugLogger = vm.NewStructLogger(logconfig) } - if ctx.GlobalString(GenesisFlag.Name) != "" { - gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) + if ctx.String(GenesisFlag.Name) != "" { + gen := readGenesis(ctx.String(GenesisFlag.Name)) db := rawdb.NewMemoryDatabase() genesis := gen.ToBlock(db) statedb, _ = state.New(genesis.Root(), state.NewDatabase(db)) @@ -103,13 +104,13 @@ func runCmd(ctx *cli.Context) error { db := rawdb.NewMemoryDatabase() statedb, _ = state.New(common.Hash{}, state.NewDatabase(db)) } - if ctx.GlobalString(SenderFlag.Name) != "" { - sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name)) + if ctx.String(SenderFlag.Name) != "" { + sender = common.HexToAddress(ctx.String(SenderFlag.Name)) } statedb.CreateAccount(sender) - if ctx.GlobalString(ReceiverFlag.Name) != "" { - receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name)) + if ctx.String(ReceiverFlag.Name) != "" { + receiver = common.HexToAddress(ctx.String(ReceiverFlag.Name)) } var ( @@ -118,11 +119,11 @@ func runCmd(ctx *cli.Context) error { err error ) // The '--code' or '--codefile' flag overrides code in state - if ctx.GlobalString(CodeFileFlag.Name) != "" { + if ctx.String(CodeFileFlag.Name) != "" { var hexcode []byte var err error // If - is specified, it means that code comes from stdin - if ctx.GlobalString(CodeFileFlag.Name) == "-" { + if ctx.String(CodeFileFlag.Name) == "-" { //Try reading from stdin if hexcode, err = io.ReadAll(os.Stdin); err != nil { fmt.Printf("Could not load code from stdin: %v\n", err) @@ -130,15 +131,15 @@ func runCmd(ctx *cli.Context) error { } } else { // Codefile with hex assembly - if hexcode, err = os.ReadFile(ctx.GlobalString(CodeFileFlag.Name)); err != nil { + if hexcode, err = os.ReadFile(ctx.String(CodeFileFlag.Name)); err != nil { fmt.Printf("Could not load code from file: %v\n", err) os.Exit(1) } } code = common.Hex2Bytes(string(bytes.TrimRight(hexcode, "\n"))) - } else if ctx.GlobalString(CodeFlag.Name) != "" { - code = common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)) + } else if ctx.String(CodeFlag.Name) != "" { + code = common.Hex2Bytes(ctx.String(CodeFlag.Name)) } else if fn := ctx.Args().First(); len(fn) > 0 { // EASM-file to compile src, err := os.ReadFile(fn) @@ -152,20 +153,20 @@ func runCmd(ctx *cli.Context) error { code = common.Hex2Bytes(bin) } - initialGas := ctx.GlobalUint64(GasFlag.Name) + initialGas := ctx.Uint64(GasFlag.Name) runtimeConfig := runtime.Config{ Origin: sender, State: statedb, GasLimit: initialGas, - GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), - Value: utils.GlobalBig(ctx, ValueFlag.Name), + GasPrice: flags.GlobalBig(ctx, PriceFlag.Name), + Value: flags.GlobalBig(ctx, ValueFlag.Name), EVMConfig: vm.Config{ Tracer: tracer, - Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), + Debug: ctx.Bool(DebugFlag.Name) || ctx.Bool(MachineFlag.Name), }, } - if cpuProfilePath := ctx.GlobalString(CPUProfileFlag.Name); cpuProfilePath != "" { + if cpuProfilePath := ctx.String(CPUProfileFlag.Name); cpuProfilePath != "" { f, err := os.Create(cpuProfilePath) if err != nil { fmt.Println("could not create CPU profile: ", err) @@ -183,23 +184,23 @@ func runCmd(ctx *cli.Context) error { } tstart := time.Now() var leftOverGas uint64 - if ctx.GlobalBool(CreateFlag.Name) { - input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...) + if ctx.Bool(CreateFlag.Name) { + input := append(code, common.Hex2Bytes(ctx.String(InputFlag.Name))...) ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig) } else { if len(code) > 0 { statedb.SetCode(receiver, code) } - ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) + ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.String(InputFlag.Name)), &runtimeConfig) } execTime := time.Since(tstart) - if ctx.GlobalBool(DumpFlag.Name) { + if ctx.Bool(DumpFlag.Name) { statedb.IntermediateRoot(true) fmt.Println(string(statedb.Dump())) } - if memProfilePath := ctx.GlobalString(MemProfileFlag.Name); memProfilePath != "" { + if memProfilePath := ctx.String(MemProfileFlag.Name); memProfilePath != "" { f, err := os.Create(memProfilePath) if err != nil { fmt.Println("could not create memory profile: ", err) @@ -212,7 +213,7 @@ func runCmd(ctx *cli.Context) error { f.Close() } - if ctx.GlobalBool(DebugFlag.Name) { + if ctx.Bool(DebugFlag.Name) { if debugLogger != nil { fmt.Fprintln(os.Stderr, "#### TRACE ####") vm.WriteTrace(os.Stderr, debugLogger.StructLogs()) @@ -221,7 +222,7 @@ func runCmd(ctx *cli.Context) error { vm.WriteLogs(os.Stderr, statedb.Logs()) } - if ctx.GlobalBool(StatDumpFlag.Name) { + if ctx.Bool(StatDumpFlag.Name) { var mem goruntime.MemStats goruntime.ReadMemStats(&mem) fmt.Fprintf(os.Stderr, `evm execution time: %v diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go index 197a1c61c382e..80dfdddf402c5 100644 --- a/cmd/evm/staterunner.go +++ b/cmd/evm/staterunner.go @@ -25,10 +25,10 @@ import ( "github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/vm" "github.com/XinFinOrg/XDPoSChain/tests" - cli "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) -var stateTestCommand = cli.Command{ +var stateTestCommand = &cli.Command{ Action: stateTestCmd, Name: "statetest", Usage: "executes the given state tests", @@ -50,10 +50,10 @@ func stateTestCmd(ctx *cli.Context) error { // Configure the EVM logger config := &vm.LogConfig{ - EnableMemory: !ctx.GlobalBool(DisableMemoryFlag.Name), - DisableStack: ctx.GlobalBool(DisableStackFlag.Name), - DisableStorage: ctx.GlobalBool(DisableStorageFlag.Name), - EnableReturnData: !ctx.GlobalBool(DisableReturnDataFlag.Name), + EnableMemory: !ctx.Bool(DisableMemoryFlag.Name), + DisableStack: ctx.Bool(DisableStackFlag.Name), + DisableStorage: ctx.Bool(DisableStorageFlag.Name), + EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name), } var ( @@ -61,10 +61,10 @@ func stateTestCmd(ctx *cli.Context) error { debugger *vm.StructLogger ) switch { - case ctx.GlobalBool(MachineFlag.Name): + case ctx.Bool(MachineFlag.Name): tracer = vm.NewJSONLogger(config, os.Stderr) - case ctx.GlobalBool(DebugFlag.Name): + case ctx.Bool(DebugFlag.Name): debugger = vm.NewStructLogger(config) tracer = debugger @@ -83,7 +83,7 @@ func stateTestCmd(ctx *cli.Context) error { // Iterate over all the tests, run them and aggregate the results cfg := vm.Config{ Tracer: tracer, - Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), + Debug: ctx.Bool(DebugFlag.Name) || ctx.Bool(MachineFlag.Name), } results := make([]StatetestResult, 0, len(tests)) for key, test := range tests { @@ -94,20 +94,20 @@ func stateTestCmd(ctx *cli.Context) error { if err != nil { // Test failed, mark as so and dump any state to aid debugging result.Pass, result.Error = false, err.Error() - if ctx.GlobalBool(DumpFlag.Name) && state != nil { + if ctx.Bool(DumpFlag.Name) && state != nil { dump := state.RawDump() result.State = &dump } } // print state root for evmlab tracing (already committed above, so no need to delete objects again - if ctx.GlobalBool(MachineFlag.Name) && state != nil { + if ctx.Bool(MachineFlag.Name) && state != nil { fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false)) } results = append(results, *result) // Print any structured logs collected - if ctx.GlobalBool(DebugFlag.Name) { + if ctx.Bool(DebugFlag.Name) { if debugger != nil { fmt.Fprintln(os.Stderr, "#### TRACE ####") vm.WriteTrace(os.Stderr, debugger.StructLogs()) diff --git a/cmd/p2psim/main.go b/cmd/p2psim/main.go index 539b29cb73312..6536d6657df6f 100644 --- a/cmd/p2psim/main.go +++ b/cmd/p2psim/main.go @@ -19,21 +19,20 @@ // Here is an example of creating a 2 node network with the first node // connected to the second: // -// $ p2psim node create -// Created node01 +// $ p2psim node create +// Created node01 // -// $ p2psim node start node01 -// Started node01 +// $ p2psim node start node01 +// Started node01 // -// $ p2psim node create -// Created node02 +// $ p2psim node create +// Created node02 // -// $ p2psim node start node02 -// Started node02 -// -// $ p2psim node connect node01 node02 -// Connected node01 to node02 +// $ p2psim node start node02 +// Started node02 // +// $ p2psim node connect node01 node02 +// Connected node01 to node02 package main import ( @@ -46,32 +45,77 @@ import ( "text/tabwriter" "github.com/XinFinOrg/XDPoSChain/crypto" + "github.com/XinFinOrg/XDPoSChain/internal/flags" "github.com/XinFinOrg/XDPoSChain/p2p" "github.com/XinFinOrg/XDPoSChain/p2p/discover" "github.com/XinFinOrg/XDPoSChain/p2p/simulations" "github.com/XinFinOrg/XDPoSChain/p2p/simulations/adapters" "github.com/XinFinOrg/XDPoSChain/rpc" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) var client *simulations.Client +var ( + // global command flags + apiFlag = &cli.StringFlag{ + Name: "api", + Value: "http://localhost:8888", + Usage: "simulation API URL", + EnvVars: []string{"P2PSIM_API_URL"}, + } + + // events subcommand flags + currentFlag = &cli.BoolFlag{ + Name: "current", + Usage: "get existing nodes and conns first", + } + filterFlag = &cli.StringFlag{ + Name: "filter", + Value: "", + Usage: "message filter", + } + + // node create subcommand flags + nameFlag = &cli.StringFlag{ + Name: "name", + Value: "", + Usage: "node name", + } + servicesFlag = &cli.StringFlag{ + Name: "services", + Value: "", + Usage: "node services (comma separated)", + } + keyFlag = &cli.StringFlag{ + Name: "key", + Value: "", + Usage: "node private key (hex encoded)", + } + + // node rpc subcommand flags + subscribeFlag = &cli.BoolFlag{ + Name: "subscribe", + Usage: "method is a subscription", + } +) + +var ( + // Git information set by linker when building with ci.go. + gitCommit string +) + func main() { - app := cli.NewApp() + app := flags.NewApp(gitCommit, "devp2p simulation command-line client") app.Usage = "devp2p simulation command-line client" app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "api", - Value: "http://localhost:8888", - Usage: "simulation API URL", - EnvVar: "P2PSIM_API_URL", - }, + apiFlag, } app.Before = func(ctx *cli.Context) error { - client = simulations.NewClient(ctx.GlobalString("api")) + client = simulations.NewClient(ctx.String("api")) return nil } - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ { Name: "show", Usage: "show network information", @@ -82,15 +126,8 @@ func main() { Usage: "stream network events", Action: streamNetwork, Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "current", - Usage: "get existing nodes and conns first", - }, - cli.StringFlag{ - Name: "filter", - Value: "", - Usage: "message filter", - }, + currentFlag, + filterFlag, }, }, { @@ -107,7 +144,7 @@ func main() { Name: "node", Usage: "manage simulation nodes", Action: listNodes, - Subcommands: []cli.Command{ + Subcommands: []*cli.Command{ { Name: "list", Usage: "list nodes", @@ -118,21 +155,9 @@ func main() { Usage: "create a node", Action: createNode, Flags: []cli.Flag{ - cli.StringFlag{ - Name: "name", - Value: "", - Usage: "node name", - }, - cli.StringFlag{ - Name: "services", - Value: "", - Usage: "node services (comma separated)", - }, - cli.StringFlag{ - Name: "key", - Value: "", - Usage: "node private key (hex encoded)", - }, + nameFlag, + servicesFlag, + keyFlag, }, }, { @@ -171,10 +196,7 @@ func main() { Usage: "call a node RPC method", Action: rpcNode, Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "subscribe", - Usage: "method is a subscription", - }, + subscribeFlag, }, }, }, @@ -184,7 +206,7 @@ func main() { } func showNetwork(ctx *cli.Context) error { - if len(ctx.Args()) != 0 { + if ctx.NArg() != 0 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } network, err := client.GetNetwork() @@ -199,7 +221,7 @@ func showNetwork(ctx *cli.Context) error { } func streamNetwork(ctx *cli.Context) error { - if len(ctx.Args()) != 0 { + if ctx.NArg() != 0 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } events := make(chan *simulations.Event) @@ -225,7 +247,7 @@ func streamNetwork(ctx *cli.Context) error { } func createSnapshot(ctx *cli.Context) error { - if len(ctx.Args()) != 0 { + if ctx.NArg() != 0 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } snap, err := client.CreateSnapshot() @@ -236,7 +258,7 @@ func createSnapshot(ctx *cli.Context) error { } func loadSnapshot(ctx *cli.Context) error { - if len(ctx.Args()) != 0 { + if ctx.NArg() != 0 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } snap := &simulations.Snapshot{} @@ -247,7 +269,7 @@ func loadSnapshot(ctx *cli.Context) error { } func listNodes(ctx *cli.Context) error { - if len(ctx.Args()) != 0 { + if ctx.NArg() != 0 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } nodes, err := client.GetNodes() @@ -272,7 +294,7 @@ func protocolList(node *p2p.NodeInfo) []string { } func createNode(ctx *cli.Context) error { - if len(ctx.Args()) != 0 { + if ctx.NArg() != 0 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } config := &adapters.NodeConfig{ @@ -298,11 +320,10 @@ func createNode(ctx *cli.Context) error { } func showNode(ctx *cli.Context) error { - args := ctx.Args() - if len(args) != 1 { + if ctx.NArg() != 1 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - nodeName := args[0] + nodeName := ctx.Args().First() node, err := client.GetNode(nodeName) if err != nil { return err @@ -323,11 +344,10 @@ func showNode(ctx *cli.Context) error { } func startNode(ctx *cli.Context) error { - args := ctx.Args() - if len(args) != 1 { + if ctx.NArg() != 1 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - nodeName := args[0] + nodeName := ctx.Args().First() if err := client.StartNode(nodeName); err != nil { return err } @@ -336,11 +356,10 @@ func startNode(ctx *cli.Context) error { } func stopNode(ctx *cli.Context) error { - args := ctx.Args() - if len(args) != 1 { + if ctx.NArg() != 1 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - nodeName := args[0] + nodeName := ctx.Args().First() if err := client.StopNode(nodeName); err != nil { return err } @@ -349,12 +368,12 @@ func stopNode(ctx *cli.Context) error { } func connectNode(ctx *cli.Context) error { - args := ctx.Args() - if len(args) != 2 { + if ctx.NArg() != 2 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - nodeName := args[0] - peerName := args[1] + args := ctx.Args() + nodeName := args.Get(0) + peerName := args.Get(1) if err := client.ConnectNode(nodeName, peerName); err != nil { return err } @@ -364,11 +383,11 @@ func connectNode(ctx *cli.Context) error { func disconnectNode(ctx *cli.Context) error { args := ctx.Args() - if len(args) != 2 { + if args.Len() != 2 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - nodeName := args[0] - peerName := args[1] + nodeName := args.Get(0) + peerName := args.Get(1) if err := client.DisconnectNode(nodeName, peerName); err != nil { return err } @@ -378,21 +397,21 @@ func disconnectNode(ctx *cli.Context) error { func rpcNode(ctx *cli.Context) error { args := ctx.Args() - if len(args) < 2 { + if args.Len() < 2 { return cli.ShowCommandHelp(ctx, ctx.Command.Name) } - nodeName := args[0] - method := args[1] + nodeName := args.Get(0) + method := args.Get(1) rpcClient, err := client.RPCClient(context.Background(), nodeName) if err != nil { return err } if ctx.Bool("subscribe") { - return rpcSubscribe(rpcClient, ctx.App.Writer, method, args[3:]...) + return rpcSubscribe(rpcClient, ctx.App.Writer, method, args.Slice()[3:]...) } var result interface{} - params := make([]interface{}, len(args[3:])) - for i, v := range args[3:] { + params := make([]interface{}, len(args.Slice()[3:])) + for i, v := range args.Slice()[3:] { params[i] = v } if err := rpcClient.Call(&result, method, params...); err != nil { diff --git a/cmd/puppeth/puppeth.go b/cmd/puppeth/puppeth.go index 51a60e0cb5a6e..6989f95f62d51 100644 --- a/cmd/puppeth/puppeth.go +++ b/cmd/puppeth/puppeth.go @@ -24,7 +24,7 @@ import ( "time" "github.com/XinFinOrg/XDPoSChain/log" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) // main is just a boring entry point to set up the CLI app. @@ -33,11 +33,11 @@ func main() { app.Name = "puppeth" app.Usage = "assemble and maintain private Ethereum networks" app.Flags = []cli.Flag{ - cli.StringFlag{ + &cli.StringFlag{ Name: "network", Usage: "name of the network to administer (no spaces or hyphens, please)", }, - cli.IntFlag{ + &cli.IntFlag{ Name: "loglevel", Value: 3, Usage: "log level to emit to the screen", diff --git a/cmd/utils/customflags.go b/cmd/utils/customflags.go deleted file mode 100644 index 2304678344f0c..0000000000000 --- a/cmd/utils/customflags.go +++ /dev/null @@ -1,240 +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 . - -package utils - -import ( - "encoding" - "errors" - "flag" - "fmt" - "math/big" - "os" - "os/user" - "path" - "strings" - - "github.com/XinFinOrg/XDPoSChain/common/math" - "gopkg.in/urfave/cli.v1" -) - -// Custom type which is registered in the flags library which cli uses for -// argument parsing. This allows us to expand Value to an absolute path when -// the argument is parsed -type DirectoryString struct { - Value string -} - -func (ds *DirectoryString) String() string { - return ds.Value -} - -func (ds *DirectoryString) Set(value string) error { - ds.Value = expandPath(value) - return nil -} - -// Custom cli.Flag type which expand the received string to an absolute path. -// e.g. ~/.ethereum -> /home/username/.ethereum -type DirectoryFlag struct { - Name string - Value DirectoryString - Usage string -} - -func (df DirectoryFlag) String() string { - fmtString := "%s %v\t%v" - if len(df.Value.Value) > 0 { - fmtString = "%s \"%v\"\t%v" - } - return fmt.Sprintf(fmtString, prefixedNames(df.Name), df.Value.Value, df.Usage) -} - -func eachName(longName string, fn func(string)) { - parts := strings.Split(longName, ",") - for _, name := range parts { - name = strings.Trim(name, " ") - fn(name) - } -} - -// called by cli library, grabs variable from environment (if in env) -// and adds variable to flag set for parsing. -func (df DirectoryFlag) Apply(set *flag.FlagSet) { - eachName(df.Name, func(name string) { - set.Var(&df.Value, df.Name, df.Usage) - }) -} - -type TextMarshaler interface { - encoding.TextMarshaler - encoding.TextUnmarshaler -} - -// textMarshalerVal turns a TextMarshaler into a flag.Value -type textMarshalerVal struct { - v TextMarshaler -} - -func (t textMarshalerVal) String() string { - if t.v == nil { - return "" - } - text, _ := t.v.MarshalText() - return string(text) -} - -func (t textMarshalerVal) Set(s string) error { - return t.v.UnmarshalText([]byte(s)) -} - -// TextMarshalerFlag wraps a TextMarshaler value. -type TextMarshalerFlag struct { - Name string - Value TextMarshaler - Usage string -} - -func (t TextMarshalerFlag) GetName() string { - return t.Name -} - -func (t TextMarshalerFlag) String() string { - return fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(t.Name), t.Value, t.Usage) -} - -func (t TextMarshalerFlag) Apply(set *flag.FlagSet) { - eachName(t.Name, func(name string) { - set.Var(textMarshalerVal{t.Value}, t.Name, t.Usage) - }) -} - -// GlobalTextMarshaler returns the value of a TextMarshalerFlag from the global flag set. -func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { - val := ctx.GlobalGeneric(name) - if val == nil { - return nil - } - return val.(textMarshalerVal).v -} - -// BigFlag is a command line flag that accepts 256 bit big integers in decimal or -// hexadecimal syntax. -type BigFlag struct { - Name string - Value *big.Int - Usage string -} - -// bigValue turns *big.Int into a flag.Value -type bigValue big.Int - -func (bv *bigValue) String() string { - if bv == nil { - return "" - } - return (*big.Int)(bv).String() -} - -func (bv *bigValue) Set(s string) error { - int, ok := math.ParseBig256(s) - if !ok { - return errors.New("invalid integer syntax") - } - *bv = (bigValue)(*int) - return nil -} - -func (bf BigFlag) GetName() string { - return bf.Name -} - -func (bf BigFlag) String() string { - fmtString := "%s %v\t%v" - if bf.Value != nil { - fmtString = "%s \"%v\"\t%v" - } - return fmt.Sprintf(fmtString, prefixedNames(bf.Name), bf.Value, bf.Usage) -} - -func (bf BigFlag) Apply(set *flag.FlagSet) { - eachName(bf.Name, func(name string) { - set.Var((*bigValue)(bf.Value), bf.Name, bf.Usage) - }) -} - -// GlobalBig returns the value of a BigFlag from the global flag set. -func GlobalBig(ctx *cli.Context, name string) *big.Int { - val := ctx.GlobalGeneric(name) - if val == nil { - return nil - } - return (*big.Int)(val.(*bigValue)) -} - -func prefixFor(name string) (prefix string) { - if len(name) == 1 { - prefix = "-" - } else { - prefix = "--" - } - - return -} - -func prefixedNames(fullName string) (prefixed string) { - parts := strings.Split(fullName, ",") - for i, name := range parts { - name = strings.Trim(name, " ") - prefixed += prefixFor(name) + name - if i < len(parts)-1 { - prefixed += ", " - } - } - return -} - -func (df DirectoryFlag) GetName() string { - return df.Name -} - -func (df *DirectoryFlag) Set(value string) { - df.Value.Value = value -} - -// Expands a file path -// 1. replace tilde with users home dir -// 2. expands embedded environment variables -// 3. cleans the path, e.g. /a/b/../c -> /a/c -// Note, it has limitations, e.g. ~someuser/tmp will not be expanded -func expandPath(p string) string { - if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { - if home := homeDir(); home != "" { - p = home + p[1:] - } - } - return path.Clean(os.ExpandEnv(p)) -} - -func homeDir() string { - if home := os.Getenv("HOME"); home != "" { - return home - } - if usr, err := user.Current(); err == nil { - return usr.HomeDir - } - return "" -} diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 700695516d901..db42606da5947 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -47,6 +47,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/eth/gasprice" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/internal/ethapi" + "github.com/XinFinOrg/XDPoSChain/internal/flags" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/metrics" "github.com/XinFinOrg/XDPoSChain/metrics/exp" @@ -59,54 +60,9 @@ import ( "github.com/XinFinOrg/XDPoSChain/params" "github.com/XinFinOrg/XDPoSChain/rpc" gopsutil "github.com/shirou/gopsutil/mem" - "gopkg.in/urfave/cli.v1" + "github.com/urfave/cli/v2" ) -var ( - CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...] -{{if .cmd.Description}}{{.cmd.Description}} -{{end}}{{if .cmd.Subcommands}} -SUBCOMMANDS: - {{range .cmd.Subcommands}}{{.cmd.Name}}{{with .cmd.ShortName}}, {{.cmd}}{{end}}{{ "\t" }}{{.cmd.Usage}} - {{end}}{{end}}{{if .categorizedFlags}} -{{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS: -{{range $categorized.Flags}}{{"\t"}}{{.}} -{{end}} -{{end}}{{end}}` -) - -func init() { - cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] - -VERSION: - {{.Version}} - -COMMANDS: - {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} - {{end}}{{if .Flags}} -GLOBAL OPTIONS: - {{range .Flags}}{{.}} - {{end}}{{end}} -` - - cli.CommandHelpTemplate = CommandHelpTemplate -} - -// NewApp creates an app with sane defaults. -func NewApp(gitCommit, usage string) *cli.App { - app := cli.NewApp() - app.Name = filepath.Base(os.Args[0]) - app.Author = "" - //app.Authors = nil - app.Email = "" - app.Version = params.Version - if len(gitCommit) >= 8 { - app.Version += "-" + gitCommit[:8] - } - app.Usage = usage - return app -} - // These are all the command line flags we support. // If you add to this list, please remember to include the // flag in the appropriate command definition. @@ -115,530 +71,644 @@ func NewApp(gitCommit, usage string) *cli.App { // are the same for all commands. var ( - // XDC flags. - RollbackFlag = cli.StringFlag{ - Name: "rollback", - Usage: "Rollback chain at hash", - Value: "", - } - Enable0xPrefixFlag = cli.BoolFlag{ - Name: "enable-0x-prefix", - Usage: "Addres use 0x-prefix (Deprecated: this is on by default, to use xdc prefix use --enable-xdc-prefix)", - } - EnableXDCPrefixFlag = cli.BoolFlag{ - Name: "enable-xdc-prefix", - Usage: "Addres use xdc-prefix (default = false)", - } // General settings - AnnounceTxsFlag = cli.BoolFlag{ - Name: "announce-txs", - Usage: "Always commit transactions", - } - StoreRewardFlag = cli.BoolFlag{ - Name: "store-reward", - Usage: "Store reward to file", - } - DataDirFlag = DirectoryFlag{ - Name: "datadir", - Usage: "Data directory for the databases and keystore", - Value: DirectoryString{node.DefaultDataDir()}, - } - KeyStoreDirFlag = DirectoryFlag{ - Name: "keystore", - Usage: "Directory for the keystore (default = inside the datadir)", - } - NoUSBFlag = cli.BoolFlag{ - Name: "nousb", - Usage: "Disables monitoring for and managing USB hardware wallets", - } - NetworkIdFlag = cli.Uint64Flag{ - Name: "networkid", - Usage: "Network identifier (integer, 89=XDPoSChain)", - Value: ethconfig.Defaults.NetworkId, - } - TestnetFlag = cli.BoolFlag{ - Name: "testnet", - Usage: "Ropsten network: pre-configured proof-of-work test network", - } - XDCTestnetFlag = cli.BoolFlag{ - Name: "apothem", - Usage: "XDC Apothem Network", - } - RinkebyFlag = cli.BoolFlag{ - Name: "rinkeby", - Usage: "Rinkeby network: pre-configured proof-of-authority test network", - } - DeveloperFlag = cli.BoolFlag{ - Name: "dev", - Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", - } - DeveloperPeriodFlag = cli.IntFlag{ - Name: "dev.period", - Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", - } - IdentityFlag = cli.StringFlag{ - Name: "identity", - Usage: "Custom node name", - } - DocRootFlag = DirectoryFlag{ - Name: "docroot", - Usage: "Document Root for HTTPClient file scheme", - Value: DirectoryString{homeDir()}, - } - FastSyncFlag = cli.BoolFlag{ - Name: "fast", - Usage: "Enable fast syncing through state downloads", - } - LightModeFlag = cli.BoolFlag{ - Name: "light", - Usage: "Enable light client mode", + DataDirFlag = &flags.DirectoryFlag{ + Name: "datadir", + Usage: "Data directory for the databases and keystore", + Value: flags.DirectoryString(node.DefaultDataDir()), + Category: flags.EthCategory, + } + KeyStoreDirFlag = &flags.DirectoryFlag{ + Name: "keystore", + Usage: "Directory for the keystore (default = inside the datadir)", + Category: flags.AccountCategory, + } + NetworkIdFlag = &cli.Uint64Flag{ + Name: "networkid", + Usage: "Network identifier (integer, 89=XDPoSChain)", + Value: ethconfig.Defaults.NetworkId, + Category: flags.EthCategory, + } + TestnetFlag = &cli.BoolFlag{ + Name: "testnet", + Usage: "Ropsten network: pre-configured proof-of-work test network", + Category: flags.EthCategory, + } + XDCTestnetFlag = &cli.BoolFlag{ + Name: "apothem", + Usage: "XDC Apothem Network", + Category: flags.EthCategory, + } + RinkebyFlag = &cli.BoolFlag{ + Name: "rinkeby", + Usage: "Rinkeby network: pre-configured proof-of-authority test network", + Category: flags.EthCategory, + } + + // Dev mode + DeveloperFlag = &cli.BoolFlag{ + Name: "dev", + Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", + Category: flags.DevCategory, + } + DeveloperPeriodFlag = &cli.IntFlag{ + Name: "dev-period", + Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", + Category: flags.DevCategory, + } + IdentityFlag = &cli.StringFlag{ + Name: "identity", + Usage: "Custom node name", + Category: flags.NetworkingCategory, + } + DocRootFlag = &flags.DirectoryFlag{ + Name: "docroot", + Usage: "Document Root for HTTPClient file scheme", + Value: flags.DirectoryString(flags.HomeDir()), + Category: flags.APICategory, } + defaultSyncMode = ethconfig.Defaults.SyncMode - SyncModeFlag = TextMarshalerFlag{ - Name: "syncmode", - Usage: `Blockchain sync mode ("fast", "full", or "light")`, - Value: &defaultSyncMode, - } - GCModeFlag = cli.StringFlag{ - Name: "gcmode", - Usage: `Blockchain garbage collection mode ("full", "archive")`, - Value: "full", - } - LightServFlag = cli.IntFlag{ - Name: "lightserv", - Usage: "Maximum percentage of time allowed for serving LES requests (0-90)", - Value: 0, - } - LightPeersFlag = cli.IntFlag{ - Name: "lightpeers", - Usage: "Maximum number of LES client peers", - Value: ethconfig.Defaults.LightPeers, - } - LightKDFFlag = cli.BoolFlag{ - Name: "lightkdf", - Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", - } - // XDCX settings - XDCXEnabledFlag = cli.BoolFlag{ - Name: "XDCx", - Usage: "Enable the XDCX protocol", + SyncModeFlag = &flags.TextMarshalerFlag{ + Name: "syncmode", + Usage: `Blockchain sync mode ("fast", "full", or "light")`, + Value: &defaultSyncMode, + Category: flags.EthCategory, + } + GCModeFlag = &cli.StringFlag{ + Name: "gcmode", + Usage: `Blockchain garbage collection mode ("full", "archive")`, + Value: "full", + Category: flags.EthCategory, + } + LightKDFFlag = &cli.BoolFlag{ + Name: "lightkdf", + Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", + Category: flags.AccountCategory, + } + + // Light server and client settings + LightServFlag = &cli.IntFlag{ + Name: "lightserv", + Usage: "Maximum percentage of time allowed for serving LES requests (0-90)", + Value: ethconfig.Defaults.LightServ, + Category: flags.LightCategory, + } + LightPeersFlag = &cli.IntFlag{ + Name: "lightpeers", + Usage: "Maximum number of LES client peers", + Value: ethconfig.Defaults.LightPeers, + Category: flags.LightCategory, } + // Ethash settings - EthashCacheDirFlag = DirectoryFlag{ - Name: "ethash.cachedir", - Usage: "Directory to store the ethash verification caches (default = inside the datadir)", - } - EthashCachesInMemoryFlag = cli.IntFlag{ - Name: "ethash.cachesinmem", - Usage: "Number of recent ethash caches to keep in memory (16MB each)", - Value: ethconfig.Defaults.Ethash.CachesInMem, - } - EthashCachesOnDiskFlag = cli.IntFlag{ - Name: "ethash.cachesondisk", - Usage: "Number of recent ethash caches to keep on disk (16MB each)", - Value: ethconfig.Defaults.Ethash.CachesOnDisk, - } - EthashDatasetDirFlag = DirectoryFlag{ - Name: "ethash.dagdir", - Usage: "Directory to store the ethash mining DAGs (default = inside home folder)", - Value: DirectoryString{ethconfig.Defaults.Ethash.DatasetDir}, - } - EthashDatasetsInMemoryFlag = cli.IntFlag{ - Name: "ethash.dagsinmem", - Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)", - Value: ethconfig.Defaults.Ethash.DatasetsInMem, - } - EthashDatasetsOnDiskFlag = cli.IntFlag{ - Name: "ethash.dagsondisk", - Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)", - Value: ethconfig.Defaults.Ethash.DatasetsOnDisk, + EthashCacheDirFlag = &flags.DirectoryFlag{ + Name: "ethash.cachedir", + Usage: "Directory to store the ethash verification caches (default = inside the datadir)", + Category: flags.EthashCategory, + } + EthashCachesInMemoryFlag = &cli.IntFlag{ + Name: "ethash.cachesinmem", + Usage: "Number of recent ethash caches to keep in memory (16MB each)", + Value: ethconfig.Defaults.Ethash.CachesInMem, + Category: flags.EthashCategory, + } + EthashCachesOnDiskFlag = &cli.IntFlag{ + Name: "ethash.cachesondisk", + Usage: "Number of recent ethash caches to keep on disk (16MB each)", + Value: ethconfig.Defaults.Ethash.CachesOnDisk, + Category: flags.EthashCategory, + } + EthashDatasetDirFlag = &flags.DirectoryFlag{ + Name: "ethash.dagdir", + Usage: "Directory to store the ethash mining DAGs (default = inside home folder)", + Value: flags.DirectoryString(ethconfig.Defaults.Ethash.DatasetDir), + Category: flags.EthashCategory, + } + EthashDatasetsInMemoryFlag = &cli.IntFlag{ + Name: "ethash.dagsinmem", + Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)", + Value: ethconfig.Defaults.Ethash.DatasetsInMem, + Category: flags.EthashCategory, + } + EthashDatasetsOnDiskFlag = &cli.IntFlag{ + Name: "ethash.dagsondisk", + Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)", + Value: ethconfig.Defaults.Ethash.DatasetsOnDisk, + Category: flags.EthashCategory, } + // Transaction pool settings - TxPoolNoLocalsFlag = cli.BoolFlag{ - Name: "txpool.nolocals", - Usage: "Disables price exemptions for locally submitted transactions", - } - TxPoolJournalFlag = cli.StringFlag{ - Name: "txpool.journal", - Usage: "Disk journal for local transaction to survive node restarts", - Value: txpool.DefaultConfig.Journal, - } - TxPoolRejournalFlag = cli.DurationFlag{ - Name: "txpool.rejournal", - Usage: "Time interval to regenerate the local transaction journal", - Value: txpool.DefaultConfig.Rejournal, - } - TxPoolPriceLimitFlag = cli.Uint64Flag{ - Name: "txpool.pricelimit", - Usage: "Minimum gas price limit to enforce for acceptance into the pool", - Value: ethconfig.Defaults.TxPool.PriceLimit, - } - TxPoolPriceBumpFlag = cli.Uint64Flag{ - Name: "txpool.pricebump", - Usage: "Price bump percentage to replace an already existing transaction", - Value: ethconfig.Defaults.TxPool.PriceBump, - } - TxPoolAccountSlotsFlag = cli.Uint64Flag{ - Name: "txpool.accountslots", - Usage: "Minimum number of executable transaction slots guaranteed per account", - Value: ethconfig.Defaults.TxPool.AccountSlots, - } - TxPoolGlobalSlotsFlag = cli.Uint64Flag{ - Name: "txpool.globalslots", - Usage: "Maximum number of executable transaction slots for all accounts", - Value: ethconfig.Defaults.TxPool.GlobalSlots, - } - TxPoolAccountQueueFlag = cli.Uint64Flag{ - Name: "txpool.accountqueue", - Usage: "Maximum number of non-executable transaction slots permitted per account", - Value: ethconfig.Defaults.TxPool.AccountQueue, - } - TxPoolGlobalQueueFlag = cli.Uint64Flag{ - Name: "txpool.globalqueue", - Usage: "Maximum number of non-executable transaction slots for all accounts", - Value: ethconfig.Defaults.TxPool.GlobalQueue, - } - TxPoolLifetimeFlag = cli.DurationFlag{ - Name: "txpool.lifetime", - Usage: "Maximum amount of time non-executable transaction are queued", - Value: ethconfig.Defaults.TxPool.Lifetime, + TxPoolNoLocalsFlag = &cli.BoolFlag{ + Name: "txpool.nolocals", + Usage: "Disables price exemptions for locally submitted transactions", + Category: flags.TxPoolCategory, + } + TxPoolJournalFlag = &cli.StringFlag{ + Name: "txpool.journal", + Usage: "Disk journal for local transaction to survive node restarts", + Value: txpool.DefaultConfig.Journal, + Category: flags.TxPoolCategory, + } + TxPoolRejournalFlag = &cli.DurationFlag{ + Name: "txpool.rejournal", + Usage: "Time interval to regenerate the local transaction journal", + Value: txpool.DefaultConfig.Rejournal, + Category: flags.TxPoolCategory, + } + TxPoolPriceLimitFlag = &cli.Uint64Flag{ + Name: "txpool.pricelimit", + Usage: "Minimum gas price limit to enforce for acceptance into the pool", + Value: ethconfig.Defaults.TxPool.PriceLimit, + Category: flags.TxPoolCategory, + } + TxPoolPriceBumpFlag = &cli.Uint64Flag{ + Name: "txpool.pricebump", + Usage: "Price bump percentage to replace an already existing transaction", + Value: ethconfig.Defaults.TxPool.PriceBump, + Category: flags.TxPoolCategory, + } + TxPoolAccountSlotsFlag = &cli.Uint64Flag{ + Name: "txpool.accountslots", + Usage: "Minimum number of executable transaction slots guaranteed per account", + Value: ethconfig.Defaults.TxPool.AccountSlots, + Category: flags.TxPoolCategory, + } + TxPoolGlobalSlotsFlag = &cli.Uint64Flag{ + Name: "txpool.globalslots", + Usage: "Maximum number of executable transaction slots for all accounts", + Value: ethconfig.Defaults.TxPool.GlobalSlots, + Category: flags.TxPoolCategory, + } + TxPoolAccountQueueFlag = &cli.Uint64Flag{ + Name: "txpool.accountqueue", + Usage: "Maximum number of non-executable transaction slots permitted per account", + Value: ethconfig.Defaults.TxPool.AccountQueue, + Category: flags.TxPoolCategory, + } + TxPoolGlobalQueueFlag = &cli.Uint64Flag{ + Name: "txpool.globalqueue", + Usage: "Maximum number of non-executable transaction slots for all accounts", + Value: ethconfig.Defaults.TxPool.GlobalQueue, + Category: flags.TxPoolCategory, + } + TxPoolLifetimeFlag = &cli.DurationFlag{ + Name: "txpool.lifetime", + Usage: "Maximum amount of time non-executable transaction are queued", + Value: ethconfig.Defaults.TxPool.Lifetime, + Category: flags.TxPoolCategory, } + // Performance tuning settings - CacheFlag = cli.IntFlag{ - Name: "cache", - Usage: "Megabytes of memory allocated to internal caching", - Value: 1024, - } - CacheDatabaseFlag = cli.IntFlag{ - Name: "cache.database", - Usage: "Percentage of cache memory allowance to use for database io", - Value: 75, - } - CacheGCFlag = cli.IntFlag{ - Name: "cache.gc", - Usage: "Percentage of cache memory allowance to use for trie pruning", - Value: 25, + CacheFlag = &cli.IntFlag{ + Name: "cache", + Usage: "Megabytes of memory allocated to internal caching", + Value: 1024, + Category: flags.PerfCategory, + } + CacheDatabaseFlag = &cli.IntFlag{ + Name: "cache.database", + Usage: "Percentage of cache memory allowance to use for database io", + Value: 50, + Category: flags.PerfCategory, + } + CacheGCFlag = &cli.IntFlag{ + Name: "cache.gc", + Usage: "Percentage of cache memory allowance to use for trie pruning", + Value: 25, + Category: flags.PerfCategory, } CacheLogSizeFlag = &cli.IntFlag{ - Name: "cache.blocklogs", - Usage: "Size (in number of blocks) of the log cache for filtering", - Value: ethconfig.Defaults.FilterLogCacheSize, + Name: "cache.blocklogs", + Usage: "Size (in number of blocks) of the log cache for filtering", + Value: ethconfig.Defaults.FilterLogCacheSize, + Category: flags.PerfCategory, } - FDLimitFlag = cli.IntFlag{ - Name: "fdlimit", - Usage: "Raise the open file descriptor resource limit (default = system fd limit)", + FDLimitFlag = &cli.IntFlag{ + Name: "fdlimit", + Usage: "Raise the open file descriptor resource limit (default = system fd limit)", + Category: flags.PerfCategory, } + // Miner settings - StakingEnabledFlag = cli.BoolFlag{ - Name: "mine", - Usage: "Enable staking", - } - StakerThreadsFlag = cli.IntFlag{ - Name: "minerthreads", - Usage: "Number of CPU threads to use for staking", - Value: runtime.NumCPU(), - } - TargetGasLimitFlag = cli.Uint64Flag{ - Name: "targetgaslimit", - Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine", - Value: params.XDCGenesisGasLimit, - } - EtherbaseFlag = cli.StringFlag{ - Name: "etherbase", - Usage: "Public address for block mining rewards (default = first account created)", - Value: "0", - } - GasPriceFlag = BigFlag{ - Name: "gasprice", - Usage: "Minimal gas price to accept for mining a transactions", - Value: ethconfig.Defaults.GasPrice, - } - ExtraDataFlag = cli.StringFlag{ - Name: "extradata", - Usage: "Block extra data set by the miner (default = client version)", + StakingEnabledFlag = &cli.BoolFlag{ + Name: "mine", + Usage: "Enable staking", + Category: flags.MinerCategory, + } + StakerThreadsFlag = &cli.IntFlag{ + Name: "minerthreads", + Usage: "Number of CPU threads to use for staking", + Value: runtime.NumCPU(), + Category: flags.MinerCategory, + } + TargetGasLimitFlag = &cli.Uint64Flag{ + Name: "targetgaslimit", + Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine", + Value: params.XDCGenesisGasLimit, + Category: flags.MinerCategory, + } + EtherbaseFlag = &cli.StringFlag{ + Name: "etherbase", + Usage: "Public address for block mining rewards (default = first account created)", + Value: "0", + Category: flags.MinerCategory, + } + GasPriceFlag = &flags.BigFlag{ + Name: "gasprice", + Usage: "Minimal gas price to accept for mining a transactions", + Value: ethconfig.Defaults.GasPrice, + Category: flags.MinerCategory, + } + ExtraDataFlag = &cli.StringFlag{ + Name: "extradata", + Usage: "Block extra data set by the miner (default = client version)", + Category: flags.MinerCategory, } + // Account settings - UnlockedAccountFlag = cli.StringFlag{ - Name: "unlock", - Usage: "Comma separated list of accounts to unlock", - Value: "", + UnlockedAccountFlag = &cli.StringFlag{ + Name: "unlock", + Usage: "Comma separated list of accounts to unlock", + Value: "", + Category: flags.AccountCategory, } - PasswordFileFlag = cli.StringFlag{ - Name: "password", - Usage: "Password file to use for non-interactive password input", - Value: "", + PasswordFileFlag = &cli.StringFlag{ + Name: "password", + Usage: "Password file to use for non-interactive password input", + Value: "", + Category: flags.AccountCategory, } - VMEnableDebugFlag = cli.BoolFlag{ - Name: "vmdebug", - Usage: "Record information useful for VM and contract debugging", + // EVM settings + VMEnableDebugFlag = &cli.BoolFlag{ + Name: "vmdebug", + Usage: "Record information useful for VM and contract debugging", + Category: flags.VMCategory, } - RPCGlobalGasCapFlag = cli.Uint64Flag{ - Name: "rpc-gascap", - Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", - Value: ethconfig.Defaults.RPCGasCap, + + // API options + RPCGlobalGasCapFlag = &cli.Uint64Flag{ + Name: "rpc-gascap", + Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", + Value: ethconfig.Defaults.RPCGasCap, + Category: flags.APICategory, } - RPCGlobalTxFeeCap = cli.Float64Flag{ - Name: "rpc.txfeecap", - Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", - Value: ethconfig.Defaults.RPCTxFeeCap, + RPCGlobalTxFeeCap = &cli.Float64Flag{ + Name: "rpc.txfeecap", + Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", + Value: ethconfig.Defaults.RPCTxFeeCap, + Category: flags.APICategory, } + // Logging and debug settings - EthStatsURLFlag = cli.StringFlag{ - Name: "ethstats", - Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", + EthStatsURLFlag = &cli.StringFlag{ + Name: "ethstats", + Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", + Category: flags.MetricsCategory, } - // MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint. - // Since the pprof service enables sensitive/vulnerable behavior, this allows a user - // to enable a public-OK metrics endpoint without having to worry about ALSO exposing - // other profiling behavior or information. - MetricsHTTPFlag = cli.StringFlag{ - Name: "metrics.addr", - Usage: "Enable stand-alone metrics HTTP server listening interface", - Value: metrics.DefaultConfig.HTTP, - } - MetricsPortFlag = cli.IntFlag{ - Name: "metrics.port", - Usage: "Metrics HTTP server listening port", - Value: metrics.DefaultConfig.Port, + FakePoWFlag = &cli.BoolFlag{ + Name: "fakepow", + Usage: "Disables proof-of-work verification", + Category: flags.LoggingCategory, } - MetricsEnabledFlag = cli.BoolFlag{ - Name: metrics.MetricsEnabledFlag, - Usage: "Enable metrics collection and reporting", - } - FakePoWFlag = cli.BoolFlag{ - Name: "fakepow", - Usage: "Disables proof-of-work verification", - } - NoCompactionFlag = cli.BoolFlag{ - Name: "nocompaction", - Usage: "Disables db compaction after import", + NoCompactionFlag = &cli.BoolFlag{ + Name: "nocompaction", + Usage: "Disables db compaction after import", + Category: flags.LoggingCategory, } + // RPC settings - RPCEnabledFlag = cli.BoolFlag{ - Name: "rpc", - Usage: "Enable the HTTP-RPC server", - } - RPCListenAddrFlag = cli.StringFlag{ - Name: "rpcaddr", - Usage: "HTTP-RPC server listening interface", - Value: node.DefaultHTTPHost, - } - RewoundFlag = cli.IntFlag{ - Name: "rewound", - Usage: "Rewound blocks", - Value: 0, - } - RPCPortFlag = cli.IntFlag{ - Name: "rpcport", - Usage: "HTTP-RPC server listening port", - Value: node.DefaultHTTPPort, - } - RPCHttpReadTimeoutFlag = cli.DurationFlag{ - Name: "rpcreadtimeout", - Usage: "HTTP-RPC server read timeout", - Value: rpc.DefaultHTTPTimeouts.ReadTimeout, - } - RPCHttpWriteTimeoutFlag = cli.DurationFlag{ - Name: "rpcwritetimeout", - Usage: "HTTP-RPC server write timeout", - Value: rpc.DefaultHTTPTimeouts.WriteTimeout, - } - RPCHttpIdleTimeoutFlag = cli.DurationFlag{ - Name: "rpcidletimeout", - Usage: "HTTP-RPC server idle timeout", - Value: rpc.DefaultHTTPTimeouts.IdleTimeout, - } - RPCCORSDomainFlag = cli.StringFlag{ - Name: "rpccorsdomain", - Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", - Value: "", - } - RPCVirtualHostsFlag = cli.StringFlag{ - Name: "rpcvhosts", - Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", - Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), - } - RPCApiFlag = cli.StringFlag{ - Name: "rpcapi", - Usage: "API's offered over the HTTP-RPC interface", - Value: "", - } - IPCDisabledFlag = cli.BoolFlag{ - Name: "ipcdisable", - Usage: "Disable the IPC-RPC server", - } - IPCPathFlag = DirectoryFlag{ - Name: "ipcpath", - Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", - } - WSEnabledFlag = cli.BoolFlag{ - Name: "ws", - Usage: "Enable the WS-RPC server", - } - WSListenAddrFlag = cli.StringFlag{ - Name: "wsaddr", - Usage: "WS-RPC server listening interface", - Value: node.DefaultWSHost, - } - WSPortFlag = cli.IntFlag{ - Name: "wsport", - Usage: "WS-RPC server listening port", - Value: node.DefaultWSPort, - } - WSApiFlag = cli.StringFlag{ - Name: "wsapi", - Usage: "API's offered over the WS-RPC interface", - Value: "", - } - WSAllowedOriginsFlag = cli.StringFlag{ - Name: "wsorigins", - Usage: "Origins from which to accept websockets requests", - Value: "", - } - ExecFlag = cli.StringFlag{ - Name: "exec", - Usage: "Execute JavaScript statement", - } - PreloadJSFlag = cli.StringFlag{ - Name: "preload", - Usage: "Comma separated list of JavaScript files to preload into the console", + IPCDisabledFlag = &cli.BoolFlag{ + Name: "ipcdisable", + Usage: "Disable the IPC-RPC server", + Category: flags.APICategory, + } + IPCPathFlag = &flags.DirectoryFlag{ + Name: "ipcpath", + Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", + Category: flags.APICategory, + } + RPCEnabledFlag = &cli.BoolFlag{ + Name: "rpc", + Usage: "Enable the HTTP-RPC server", + Category: flags.APICategory, + } + RPCListenAddrFlag = &cli.StringFlag{ + Name: "rpcaddr", + Usage: "HTTP-RPC server listening interface", + Value: node.DefaultHTTPHost, + Category: flags.APICategory, + } + RPCPortFlag = &cli.IntFlag{ + Name: "rpcport", + Usage: "HTTP-RPC server listening port", + Value: node.DefaultHTTPPort, + Category: flags.APICategory, + } + RPCCORSDomainFlag = &cli.StringFlag{ + Name: "rpccorsdomain", + Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", + Value: "", + Category: flags.APICategory, + } + RPCVirtualHostsFlag = &cli.StringFlag{ + Name: "rpcvhosts", + Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", + Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), + Category: flags.APICategory, + } + RPCApiFlag = &cli.StringFlag{ + Name: "rpcapi", + Usage: "API's offered over the HTTP-RPC interface", + Value: "", + Category: flags.APICategory, + } + WSEnabledFlag = &cli.BoolFlag{ + Name: "ws", + Usage: "Enable the WS-RPC server", + Category: flags.APICategory, + } + WSListenAddrFlag = &cli.StringFlag{ + Name: "wsaddr", + Usage: "WS-RPC server listening interface", + Value: node.DefaultWSHost, + Category: flags.APICategory, + } + WSPortFlag = &cli.IntFlag{ + Name: "wsport", + Usage: "WS-RPC server listening port", + Value: node.DefaultWSPort, + Category: flags.APICategory, + } + WSApiFlag = &cli.StringFlag{ + Name: "wsapi", + Usage: "API's offered over the WS-RPC interface", + Value: "", + Category: flags.APICategory, + } + WSAllowedOriginsFlag = &cli.StringFlag{ + Name: "wsorigins", + Usage: "Origins from which to accept websockets requests", + Value: "", + Category: flags.APICategory, + } + ExecFlag = &cli.StringFlag{ + Name: "exec", + Usage: "Execute JavaScript statement", + Category: flags.APICategory, + } + PreloadJSFlag = &cli.StringFlag{ + Name: "preload", + Usage: "Comma separated list of JavaScript files to preload into the console", + Category: flags.APICategory, + } + RPCHttpReadTimeoutFlag = &cli.DurationFlag{ + Name: "rpcreadtimeout", + Usage: "HTTP-RPC server read timeout", + Value: rpc.DefaultHTTPTimeouts.ReadTimeout, + Category: flags.APICategory, + } + RPCHttpWriteTimeoutFlag = &cli.DurationFlag{ + Name: "rpcwritetimeout", + Usage: "HTTP-RPC server write timeout", + Value: rpc.DefaultHTTPTimeouts.WriteTimeout, + Category: flags.APICategory, + } + RPCHttpIdleTimeoutFlag = &cli.DurationFlag{ + Name: "rpcidletimeout", + Usage: "HTTP-RPC server idle timeout", + Value: rpc.DefaultHTTPTimeouts.IdleTimeout, + Category: flags.APICategory, } // Network Settings - MaxPeersFlag = cli.IntFlag{ - Name: "maxpeers", - Usage: "Maximum number of network peers (network disabled if set to 0)", - Value: node.DefaultConfig.P2P.MaxPeers, - } - MaxPendingPeersFlag = cli.IntFlag{ - Name: "maxpendpeers", - Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", - Value: node.DefaultConfig.P2P.MaxPendingPeers, - } - ListenPortFlag = cli.IntFlag{ - Name: "port", - Usage: "Network listening port", - Value: 30303, + MaxPeersFlag = &cli.IntFlag{ + Name: "maxpeers", + Usage: "Maximum number of network peers (network disabled if set to 0)", + Value: node.DefaultConfig.P2P.MaxPeers, + Category: flags.NetworkingCategory, + } + MaxPendingPeersFlag = &cli.IntFlag{ + Name: "maxpendpeers", + Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", + Value: node.DefaultConfig.P2P.MaxPendingPeers, + Category: flags.NetworkingCategory, + } + ListenPortFlag = &cli.IntFlag{ + Name: "port", + Usage: "Network listening port", + Value: 30303, + Category: flags.NetworkingCategory, + } + BootnodesFlag = &cli.StringFlag{ + Name: "bootnodes", + Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)", + Value: "", + Category: flags.NetworkingCategory, + } + BootnodesV4Flag = &cli.StringFlag{ + Name: "bootnodesv4", + Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)", + Value: "", + Category: flags.NetworkingCategory, + } + BootnodesV5Flag = &cli.StringFlag{ + Name: "bootnodesv5", + Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)", + Value: "", + Category: flags.NetworkingCategory, + } + NodeKeyFileFlag = &cli.StringFlag{ + Name: "nodekey", + Usage: "P2P node key file", + Category: flags.NetworkingCategory, + } + NodeKeyHexFlag = &cli.StringFlag{ + Name: "nodekeyhex", + Usage: "P2P node key as hex (for testing)", + Category: flags.NetworkingCategory, + } + NATFlag = &cli.StringFlag{ + Name: "nat", + Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", + Value: "any", + Category: flags.NetworkingCategory, + } + NoDiscoverFlag = &cli.BoolFlag{ + Name: "nodiscover", + Usage: "Disables the peer discovery mechanism (manual peer addition)", + Category: flags.NetworkingCategory, + } + DiscoveryV5Flag = &cli.BoolFlag{ + Name: "v5disc", + Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", + Category: flags.NetworkingCategory, + } + NetrestrictFlag = &cli.StringFlag{ + Name: "netrestrict", + Usage: "Restricts network communication to the given IP networks (CIDR masks)", + Category: flags.NetworkingCategory, + } + + // Console + JSpathFlag = &cli.StringFlag{ + Name: "jspath", + Usage: "JavaScript root path for `loadScript`", + Value: ".", + Category: flags.APICategory, } - BootnodesFlag = cli.StringFlag{ - Name: "bootnodes", - Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)", - Value: "", - } - BootnodesV4Flag = cli.StringFlag{ - Name: "bootnodesv4", - Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)", - Value: "", - } - BootnodesV5Flag = cli.StringFlag{ - Name: "bootnodesv5", - Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)", - Value: "", - } - NodeKeyFileFlag = cli.StringFlag{ - Name: "nodekey", - Usage: "P2P node key file", - } - NodeKeyHexFlag = cli.StringFlag{ - Name: "nodekeyhex", - Usage: "P2P node key as hex (for testing)", - } - NATFlag = cli.StringFlag{ - Name: "nat", - Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", - Value: "any", - } - NoDiscoverFlag = cli.BoolFlag{ - Name: "nodiscover", - Usage: "Disables the peer discovery mechanism (manual peer addition)", - } - DiscoveryV5Flag = cli.BoolFlag{ - Name: "v5disc", - Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", - } - NetrestrictFlag = cli.StringFlag{ - Name: "netrestrict", - Usage: "Restricts network communication to the given IP networks (CIDR masks)", + + // Gas price oracle settings + GpoBlocksFlag = &cli.IntFlag{ + Name: "gpoblocks", + Usage: "Number of recent blocks to check for gas prices", + Value: ethconfig.Defaults.GPO.Blocks, + Category: flags.GasPriceCategory, + } + GpoPercentileFlag = &cli.IntFlag{ + Name: "gpopercentile", + Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", + Value: ethconfig.Defaults.GPO.Percentile, + Category: flags.GasPriceCategory, + } + GpoMaxGasPriceFlag = &cli.Int64Flag{ + Name: "gpo.maxprice", + Usage: "Maximum gas price will be recommended by gpo", + Value: ethconfig.Defaults.GPO.MaxPrice.Int64(), + Category: flags.GasPriceCategory, + } + GpoIgnoreGasPriceFlag = &cli.Int64Flag{ + Name: "gpo.ignoreprice", + Usage: "Gas price below which gpo will ignore transactions", + Value: ethconfig.Defaults.GPO.IgnorePrice.Int64(), + Category: flags.GasPriceCategory, + } + + // Metrics flags + MetricsEnabledFlag = &cli.BoolFlag{ + Name: "metrics", + Usage: "Enable metrics collection and reporting", + Category: flags.MetricsCategory, } - // ATM the url is left to the user and deployment to - JSpathFlag = cli.StringFlag{ - Name: "jspath", - Usage: "JavaScript root path for `loadScript`", - Value: ".", + // MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint. + // Since the pprof service enables sensitive/vulnerable behavior, this allows a user + // to enable a public-OK metrics endpoint without having to worry about ALSO exposing + // other profiling behavior or information. + MetricsHTTPFlag = &cli.StringFlag{ + Name: "metrics.addr", + Usage: "Enable stand-alone metrics HTTP server listening interface", + Value: metrics.DefaultConfig.HTTP, + Category: flags.MetricsCategory, + } + MetricsPortFlag = &cli.IntFlag{ + Name: "metrics.port", + Usage: "Metrics HTTP server listening port", + Value: metrics.DefaultConfig.Port, + Category: flags.MetricsCategory, + } + + // MISC settings + RollbackFlag = &cli.StringFlag{ + Name: "rollback", + Usage: "Rollback chain at hash", + Value: "", + Category: flags.MiscCategory, + } + AnnounceTxsFlag = &cli.BoolFlag{ + Name: "announce-txs", + Usage: "Always commit transactions", + Value: false, + Category: flags.MiscCategory, + } + StoreRewardFlag = &cli.BoolFlag{ + Name: "store-reward", + Usage: "Store reward to file", + Value: false, + Category: flags.MiscCategory, + } + RewoundFlag = &cli.IntFlag{ + Name: "rewound", + Usage: "Rewound blocks", + Value: 0, + Category: flags.MiscCategory, + } + + // XDC settings + Enable0xPrefixFlag = &cli.BoolFlag{ + Name: "enable-0x-prefix", + Usage: "Addres use 0x-prefix (Deprecated: this is on by default, to use xdc prefix use --enable-xdc-prefix)", + Value: true, + Category: flags.XdcCategory, + } + EnableXDCPrefixFlag = &cli.BoolFlag{ + Name: "enable-xdc-prefix", + Usage: "Addres use xdc-prefix (default = false)", + Value: false, + Category: flags.XdcCategory, + } + XDCSlaveModeFlag = &cli.BoolFlag{ + Name: "slave", + Usage: "Enable slave mode", + Category: flags.XdcCategory, } - // Gas price oracle settings - GpoBlocksFlag = cli.IntFlag{ - Name: "gpoblocks", - Usage: "Number of recent blocks to check for gas prices", - Value: ethconfig.Defaults.GPO.Blocks, - } - GpoPercentileFlag = cli.IntFlag{ - Name: "gpopercentile", - Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", - Value: ethconfig.Defaults.GPO.Percentile, - } - GpoMaxGasPriceFlag = cli.Int64Flag{ - Name: "gpo.maxprice", - Usage: "Maximum gas price will be recommended by gpo", - Value: ethconfig.Defaults.GPO.MaxPrice.Int64(), - } - GpoIgnoreGasPriceFlag = cli.Int64Flag{ - Name: "gpo.ignoreprice", - Usage: "Gas price below which gpo will ignore transactions", - Value: ethconfig.Defaults.GPO.IgnorePrice.Int64(), - } - XDCXDataDirFlag = DirectoryFlag{ - Name: "XDCx.datadir", - Usage: "Data directory for the XDCX databases", - Value: DirectoryString{filepath.Join(DataDirFlag.Value.String(), "XDCx")}, - } - XDCXDBEngineFlag = cli.StringFlag{ - Name: "XDCx.dbengine", - Usage: "Database engine for XDCX (leveldb, mongodb)", - Value: "leveldb", - } - XDCXDBNameFlag = cli.StringFlag{ - Name: "XDCx.dbName", - Usage: "Database name for XDCX", - Value: "XDCdex", - } - XDCXDBConnectionUrlFlag = cli.StringFlag{ - Name: "XDCx.dbConnectionUrl", - Usage: "ConnectionUrl to database if dbEngine is mongodb. Host:port. If there are multiple instances, separated by comma. Eg: localhost:27017,localhost:27018", - Value: "localhost:27017", - } - XDCXDBReplicaSetNameFlag = cli.StringFlag{ - Name: "XDCx.dbReplicaSetName", - Usage: "ReplicaSetName if Master-Slave is setup", - } - XDCSlaveModeFlag = cli.BoolFlag{ - Name: "slave", - Usage: "Enable slave mode", - } - // Deprecated November 2023 - LogBacktraceAtFlag = &cli.StringFlag{ - Name: "log-backtrace", - Usage: "Request a stack trace at a specific logging statement (deprecated)", - Value: "", - } - LogDebugFlag = &cli.BoolFlag{ - Name: "log-debug", - Usage: "Prepends log messages with call-site location (deprecated)", + // XDCX settings + XDCXEnabledFlag = &cli.BoolFlag{ + Name: "XDCx", + Usage: "Enable the XDCX protocol", + Category: flags.XdcxCategory, + } + XDCXDataDirFlag = &flags.DirectoryFlag{ + Name: "XDCx.datadir", + Usage: "Data directory for the XDCX databases", + Value: flags.DirectoryString(filepath.Join(DataDirFlag.Value.String(), "XDCx")), + Category: flags.XdcxCategory, + } + XDCXDBEngineFlag = &cli.StringFlag{ + Name: "XDCx.dbengine", + Usage: "Database engine for XDCX (leveldb, mongodb)", + Value: "leveldb", + Category: flags.XdcxCategory, + } + XDCXDBNameFlag = &cli.StringFlag{ + Name: "XDCx.dbName", + Usage: "Database name for XDCX", + Value: "XDCdex", + Category: flags.XdcxCategory, + } + XDCXDBConnectionUrlFlag = &cli.StringFlag{ + Name: "XDCx.dbConnectionUrl", + Usage: "ConnectionUrl to database if dbEngine is mongodb. Host:port. If there are multiple instances, separated by comma. Eg: localhost:27017,localhost:27018", + Value: "localhost:27017", + Category: flags.XdcxCategory, + } + XDCXDBReplicaSetNameFlag = &cli.StringFlag{ + Name: "XDCx.dbReplicaSetName", + Usage: "ReplicaSetName if Master-Slave is setup", + Category: flags.XdcxCategory, } ) +// GroupFlags combines the given flag slices together and returns the merged one. +func GroupFlags(groups ...[]cli.Flag) []cli.Flag { + var ret []cli.Flag + for _, group := range groups { + ret = append(ret, group...) + } + return ret +} + // MakeDataDir retrieves the currently requested data directory, terminating // if none (or the empty string) is specified. If the node is starting a testnet, // the a subdirectory of the specified datadir will be used. func MakeDataDir(ctx *cli.Context) string { - if path := ctx.GlobalString(DataDirFlag.Name); path != "" { - if ctx.GlobalBool(TestnetFlag.Name) { + if path := ctx.String(DataDirFlag.Name); path != "" { + if ctx.Bool(TestnetFlag.Name) { return filepath.Join(path, "testnet") } - if ctx.GlobalBool(RinkebyFlag.Name) { + if ctx.Bool(RinkebyFlag.Name) { return filepath.Join(path, "rinkeby") } return path @@ -652,8 +722,8 @@ func MakeDataDir(ctx *cli.Context) string { // method returns nil and an emphemeral key is to be generated. func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { var ( - hex = ctx.GlobalString(NodeKeyHexFlag.Name) - file = ctx.GlobalString(NodeKeyFileFlag.Name) + hex = ctx.String(NodeKeyHexFlag.Name) + file = ctx.String(NodeKeyFileFlag.Name) key *ecdsa.PrivateKey err error ) @@ -675,7 +745,7 @@ func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { // setNodeUserIdent creates the user identifier from CLI flags. func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { - if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { + if identity := ctx.String(IdentityFlag.Name); len(identity) > 0 { cfg.UserIdent = identity } } @@ -685,21 +755,21 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { urls := []string{} switch { - case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name): - if ctx.GlobalIsSet(BootnodesV4Flag.Name) { - urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",") + case ctx.IsSet(BootnodesFlag.Name) || ctx.IsSet(BootnodesV4Flag.Name): + if ctx.IsSet(BootnodesV4Flag.Name) { + urls = strings.Split(ctx.String(BootnodesV4Flag.Name), ",") } else { - urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") + urls = strings.Split(ctx.String(BootnodesFlag.Name), ",") } - // case ctx.GlobalBool(TestnetFlag.Name): + // case ctx.Bool(TestnetFlag.Name): // urls = params.TestnetBootnodes - // case ctx.GlobalBool(RinkebyFlag.Name): + // case ctx.Bool(RinkebyFlag.Name): // urls = params.RinkebyBootnodes case cfg.BootstrapNodes != nil: return // already set, don't apply defaults. - case !ctx.GlobalIsSet(BootnodesFlag.Name): + case !ctx.IsSet(BootnodesFlag.Name): urls = params.MainnetBootnodes - case ctx.GlobalBool(XDCTestnetFlag.Name): + case ctx.Bool(XDCTestnetFlag.Name): urls = params.TestnetBootnodes } cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls)) @@ -718,13 +788,13 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { urls := params.DiscoveryV5Bootnodes switch { - case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name): - if ctx.GlobalIsSet(BootnodesV5Flag.Name) { - urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",") + case ctx.IsSet(BootnodesFlag.Name) || ctx.IsSet(BootnodesV5Flag.Name): + if ctx.IsSet(BootnodesV5Flag.Name) { + urls = strings.Split(ctx.String(BootnodesV5Flag.Name), ",") } else { - urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") + urls = strings.Split(ctx.String(BootnodesFlag.Name), ",") } - case ctx.GlobalBool(RinkebyFlag.Name): + case ctx.Bool(RinkebyFlag.Name): urls = params.RinkebyBootnodes case cfg.BootstrapNodesV5 != nil: return // already set, don't apply defaults. @@ -744,16 +814,16 @@ func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { // setListenAddress creates a TCP listening address string from set command // line flags. func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { - if ctx.GlobalIsSet(ListenPortFlag.Name) { - cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) + if ctx.IsSet(ListenPortFlag.Name) { + cfg.ListenAddr = fmt.Sprintf(":%d", ctx.Int(ListenPortFlag.Name)) } } // setNAT creates a port mapper from command line flags. func setNAT(ctx *cli.Context, cfg *p2p.Config) { - if ctx.GlobalIsSet(NATFlag.Name) { - log.Info("NAT is setted", "value", ctx.GlobalString(NATFlag.Name)) - natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) + if ctx.IsSet(NATFlag.Name) { + log.Info("NAT is setted", "value", ctx.String(NATFlag.Name)) + natif, err := nat.Parse(ctx.String(NATFlag.Name)) if err != nil { Fatalf("Option %s: %v", NATFlag.Name, err) } @@ -777,54 +847,54 @@ func splitAndTrim(input string) (ret []string) { // setHTTP creates the HTTP RPC listener interface string from the set // command line flags, returning empty if the HTTP endpoint is disabled. func setHTTP(ctx *cli.Context, cfg *node.Config) { - if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { + if ctx.Bool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { cfg.HTTPHost = "127.0.0.1" - if ctx.GlobalIsSet(RPCListenAddrFlag.Name) { - cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name) + if ctx.IsSet(RPCListenAddrFlag.Name) { + cfg.HTTPHost = ctx.String(RPCListenAddrFlag.Name) } } - if ctx.GlobalIsSet(RPCPortFlag.Name) { - cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) + if ctx.IsSet(RPCPortFlag.Name) { + cfg.HTTPPort = ctx.Int(RPCPortFlag.Name) } - if ctx.GlobalIsSet(RPCHttpReadTimeoutFlag.Name) { - cfg.HTTPTimeouts.ReadTimeout = ctx.GlobalDuration(RPCHttpReadTimeoutFlag.Name) + if ctx.IsSet(RPCHttpReadTimeoutFlag.Name) { + cfg.HTTPTimeouts.ReadTimeout = ctx.Duration(RPCHttpReadTimeoutFlag.Name) } - if ctx.GlobalIsSet(RPCHttpWriteTimeoutFlag.Name) { - cfg.HTTPTimeouts.WriteTimeout = ctx.GlobalDuration(RPCHttpWriteTimeoutFlag.Name) + if ctx.IsSet(RPCHttpWriteTimeoutFlag.Name) { + cfg.HTTPTimeouts.WriteTimeout = ctx.Duration(RPCHttpWriteTimeoutFlag.Name) } - if ctx.GlobalIsSet(RPCHttpIdleTimeoutFlag.Name) { - cfg.HTTPTimeouts.IdleTimeout = ctx.GlobalDuration(RPCHttpIdleTimeoutFlag.Name) + if ctx.IsSet(RPCHttpIdleTimeoutFlag.Name) { + cfg.HTTPTimeouts.IdleTimeout = ctx.Duration(RPCHttpIdleTimeoutFlag.Name) } - if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { - cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name)) + if ctx.IsSet(RPCCORSDomainFlag.Name) { + cfg.HTTPCors = splitAndTrim(ctx.String(RPCCORSDomainFlag.Name)) } - if ctx.GlobalIsSet(RPCApiFlag.Name) { - cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name)) + if ctx.IsSet(RPCApiFlag.Name) { + cfg.HTTPModules = splitAndTrim(ctx.String(RPCApiFlag.Name)) } - if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) { - cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name)) + if ctx.IsSet(RPCVirtualHostsFlag.Name) { + cfg.HTTPVirtualHosts = splitAndTrim(ctx.String(RPCVirtualHostsFlag.Name)) } } // setWS creates the WebSocket RPC listener interface string from the set // command line flags, returning empty if the HTTP endpoint is disabled. func setWS(ctx *cli.Context, cfg *node.Config) { - if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { + if ctx.Bool(WSEnabledFlag.Name) && cfg.WSHost == "" { cfg.WSHost = "127.0.0.1" - if ctx.GlobalIsSet(WSListenAddrFlag.Name) { - cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) + if ctx.IsSet(WSListenAddrFlag.Name) { + cfg.WSHost = ctx.String(WSListenAddrFlag.Name) } } - if ctx.GlobalIsSet(WSPortFlag.Name) { - cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) + if ctx.IsSet(WSPortFlag.Name) { + cfg.WSPort = ctx.Int(WSPortFlag.Name) } - if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { - cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) + if ctx.IsSet(WSAllowedOriginsFlag.Name) { + cfg.WSOrigins = splitAndTrim(ctx.String(WSAllowedOriginsFlag.Name)) } - if ctx.GlobalIsSet(WSApiFlag.Name) { - cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name)) + if ctx.IsSet(WSApiFlag.Name) { + cfg.WSModules = splitAndTrim(ctx.String(WSApiFlag.Name)) } } @@ -833,10 +903,10 @@ func setWS(ctx *cli.Context, cfg *node.Config) { func setIPC(ctx *cli.Context, cfg *node.Config) { checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) switch { - case ctx.GlobalBool(IPCDisabledFlag.Name): + case ctx.Bool(IPCDisabledFlag.Name): cfg.IPCPath = "" - case ctx.GlobalIsSet(IPCPathFlag.Name): - cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) + case ctx.IsSet(IPCPathFlag.Name): + cfg.IPCPath = ctx.String(IPCPathFlag.Name) } } @@ -899,8 +969,8 @@ func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error // setEtherbase retrieves the etherbase either from the directly specified // command line flags or from the keystore if CLI indexed. func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *ethconfig.Config) { - if ctx.GlobalIsSet(EtherbaseFlag.Name) { - account, err := MakeAddress(ks, ctx.GlobalString(EtherbaseFlag.Name)) + if ctx.IsSet(EtherbaseFlag.Name) { + account, err := MakeAddress(ks, ctx.String(EtherbaseFlag.Name)) if err != nil { Fatalf("Option %q: %v", EtherbaseFlag.Name, err) } @@ -910,7 +980,7 @@ func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *ethconfig.Config // MakePasswordList reads password lines from the file specified by the global --password flag. func MakePasswordList(ctx *cli.Context) []string { - path := ctx.GlobalString(PasswordFileFlag.Name) + path := ctx.String(PasswordFileFlag.Name) if path == "" { return nil } @@ -933,20 +1003,20 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { setBootstrapNodes(ctx, cfg) // setBootstrapNodesV5(ctx, cfg) - lightClient := ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalString(SyncModeFlag.Name) == "light" - lightServer := ctx.GlobalInt(LightServFlag.Name) != 0 - lightPeers := ctx.GlobalInt(LightPeersFlag.Name) + lightClient := ctx.Bool(LightModeFlag.Name) || ctx.String(SyncModeFlag.Name) == "light" + lightServer := ctx.Int(LightServFlag.Name) != 0 + lightPeers := ctx.Int(LightPeersFlag.Name) - if ctx.GlobalIsSet(MaxPeersFlag.Name) { - cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) - if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) { + if ctx.IsSet(MaxPeersFlag.Name) { + cfg.MaxPeers = ctx.Int(MaxPeersFlag.Name) + if lightServer && !ctx.IsSet(LightPeersFlag.Name) { cfg.MaxPeers += lightPeers } } else { if lightServer { cfg.MaxPeers += lightPeers } - if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers { + if lightClient && ctx.IsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers { cfg.MaxPeers = lightPeers } } @@ -959,24 +1029,24 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { } log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers) - if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { - cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) + if ctx.IsSet(MaxPendingPeersFlag.Name) { + cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name) } - if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { + if ctx.IsSet(NoDiscoverFlag.Name) || lightClient { cfg.NoDiscovery = true } // if we're running a light client or server, force enable the v5 peer discovery // unless it is explicitly disabled with --nodiscover note that explicitly specifying // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery - forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) - if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { - cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) + forceV5Discovery := (lightClient || lightServer) && !ctx.Bool(NoDiscoverFlag.Name) + if ctx.IsSet(DiscoveryV5Flag.Name) { + cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name) } else if forceV5Discovery { cfg.DiscoveryV5 = true } - if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { + if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" { list, err := netutil.ParseNetlist(netrestrict) if err != nil { Fatalf("Option %q: %v", NetrestrictFlag.Name, err) @@ -984,7 +1054,7 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { cfg.NetRestrict = list } - if ctx.GlobalBool(DeveloperFlag.Name) { + if ctx.Bool(DeveloperFlag.Name) { // --dev mode can't use p2p networking. cfg.MaxPeers = 0 cfg.ListenAddr = ":0" @@ -1003,27 +1073,27 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { setPrefix(ctx, cfg) switch { - case ctx.GlobalIsSet(DataDirFlag.Name): - cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) - case ctx.GlobalBool(DeveloperFlag.Name): + case ctx.IsSet(DataDirFlag.Name): + cfg.DataDir = ctx.String(DataDirFlag.Name) + case ctx.Bool(DeveloperFlag.Name): cfg.DataDir = "" // unless explicitly requested, use memory databases - case ctx.GlobalBool(TestnetFlag.Name): + case ctx.Bool(TestnetFlag.Name): cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet") - case ctx.GlobalBool(RinkebyFlag.Name): + case ctx.Bool(RinkebyFlag.Name): cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby") } - if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { - cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) + if ctx.IsSet(KeyStoreDirFlag.Name) { + cfg.KeyStoreDir = ctx.String(KeyStoreDirFlag.Name) } - if ctx.GlobalIsSet(LightKDFFlag.Name) { - cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) + if ctx.IsSet(LightKDFFlag.Name) { + cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name) } - if ctx.GlobalIsSet(NoUSBFlag.Name) { - cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name) + if ctx.IsSet(NoUSBFlag.Name) { + cfg.NoUSB = ctx.Bool(NoUSBFlag.Name) } - if ctx.GlobalIsSet(AnnounceTxsFlag.Name) { - cfg.AnnounceTxs = ctx.GlobalBool(AnnounceTxsFlag.Name) + if ctx.IsSet(AnnounceTxsFlag.Name) { + cfg.AnnounceTxs = ctx.Bool(AnnounceTxsFlag.Name) } // deprecation notice for log debug flags (TODO: find a more appropriate place to put these?) if ctx.IsSet(LogBacktraceAtFlag.Name) { @@ -1040,71 +1110,71 @@ func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) { if light { *cfg = ethconfig.LightClientGPO } - if ctx.GlobalIsSet(GpoBlocksFlag.Name) { - cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) + if ctx.IsSet(GpoBlocksFlag.Name) { + cfg.Blocks = ctx.Int(GpoBlocksFlag.Name) } - if ctx.GlobalIsSet(GpoPercentileFlag.Name) { - cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) + if ctx.IsSet(GpoPercentileFlag.Name) { + cfg.Percentile = ctx.Int(GpoPercentileFlag.Name) } - if ctx.GlobalIsSet(GpoMaxGasPriceFlag.Name) { - cfg.MaxPrice = big.NewInt(ctx.GlobalInt64(GpoMaxGasPriceFlag.Name)) + if ctx.IsSet(GpoMaxGasPriceFlag.Name) { + cfg.MaxPrice = big.NewInt(ctx.Int64(GpoMaxGasPriceFlag.Name)) } - if ctx.GlobalIsSet(GpoIgnoreGasPriceFlag.Name) { - cfg.IgnorePrice = big.NewInt(ctx.GlobalInt64(GpoIgnoreGasPriceFlag.Name)) + if ctx.IsSet(GpoIgnoreGasPriceFlag.Name) { + cfg.IgnorePrice = big.NewInt(ctx.Int64(GpoIgnoreGasPriceFlag.Name)) } } func setTxPool(ctx *cli.Context, cfg *txpool.Config) { - if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) { - cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name) + if ctx.IsSet(TxPoolNoLocalsFlag.Name) { + cfg.NoLocals = ctx.Bool(TxPoolNoLocalsFlag.Name) } - if ctx.GlobalIsSet(TxPoolJournalFlag.Name) { - cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name) + if ctx.IsSet(TxPoolJournalFlag.Name) { + cfg.Journal = ctx.String(TxPoolJournalFlag.Name) } - if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) { - cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name) + if ctx.IsSet(TxPoolRejournalFlag.Name) { + cfg.Rejournal = ctx.Duration(TxPoolRejournalFlag.Name) } - if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) { - cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name) + if ctx.IsSet(TxPoolPriceLimitFlag.Name) { + cfg.PriceLimit = ctx.Uint64(TxPoolPriceLimitFlag.Name) } - if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) { - cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name) + if ctx.IsSet(TxPoolPriceBumpFlag.Name) { + cfg.PriceBump = ctx.Uint64(TxPoolPriceBumpFlag.Name) } - if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) { - cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name) + if ctx.IsSet(TxPoolAccountSlotsFlag.Name) { + cfg.AccountSlots = ctx.Uint64(TxPoolAccountSlotsFlag.Name) } - if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) { - cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name) + if ctx.IsSet(TxPoolGlobalSlotsFlag.Name) { + cfg.GlobalSlots = ctx.Uint64(TxPoolGlobalSlotsFlag.Name) } - if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) { - cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name) + if ctx.IsSet(TxPoolAccountQueueFlag.Name) { + cfg.AccountQueue = ctx.Uint64(TxPoolAccountQueueFlag.Name) } - if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) { - cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name) + if ctx.IsSet(TxPoolGlobalQueueFlag.Name) { + cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name) } - if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) { - cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name) + if ctx.IsSet(TxPoolLifetimeFlag.Name) { + cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name) } } func setEthash(ctx *cli.Context, cfg *ethconfig.Config) { - if ctx.GlobalIsSet(EthashCacheDirFlag.Name) { - cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name) + if ctx.IsSet(EthashCacheDirFlag.Name) { + cfg.Ethash.CacheDir = ctx.String(EthashCacheDirFlag.Name) } - if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) { - cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name) + if ctx.IsSet(EthashDatasetDirFlag.Name) { + cfg.Ethash.DatasetDir = ctx.String(EthashDatasetDirFlag.Name) } - if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) { - cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name) + if ctx.IsSet(EthashCachesInMemoryFlag.Name) { + cfg.Ethash.CachesInMem = ctx.Int(EthashCachesInMemoryFlag.Name) } - if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) { - cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name) + if ctx.IsSet(EthashCachesOnDiskFlag.Name) { + cfg.Ethash.CachesOnDisk = ctx.Int(EthashCachesOnDiskFlag.Name) } - if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) { - cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name) + if ctx.IsSet(EthashDatasetsInMemoryFlag.Name) { + cfg.Ethash.DatasetsInMem = ctx.Int(EthashDatasetsInMemoryFlag.Name) } - if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) { - cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name) + if ctx.IsSet(EthashDatasetsOnDiskFlag.Name) { + cfg.Ethash.DatasetsOnDisk = ctx.Int(EthashDatasetsOnDiskFlag.Name) } } @@ -1120,13 +1190,13 @@ func checkExclusive(ctx *cli.Context, args ...interface{}) { panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) } // Check if next arg extends current and expand its name if so - name := flag.GetName() + name := flag.Names()[0] if i+1 < len(args) { switch option := args[i+1].(type) { case string: // Extended flag, expand the name and shift the arguments - if ctx.GlobalString(flag.GetName()) == option { + if ctx.String(flag.Names()[0]) == option { name += "=" + option } i++ @@ -1137,7 +1207,7 @@ func checkExclusive(ctx *cli.Context, args ...interface{}) { } } // Mark the flag if it's set - if ctx.GlobalIsSet(flag.GetName()) { + if ctx.IsSet(flag.Names()[0]) { set = append(set, "--"+name) } } @@ -1147,8 +1217,8 @@ func checkExclusive(ctx *cli.Context, args ...interface{}) { } func SetXDCXConfig(ctx *cli.Context, cfg *XDCx.Config, XDCDataDir string) { - if ctx.GlobalIsSet(XDCXDataDirFlag.Name) { - cfg.DataDir = ctx.GlobalString(XDCXDataDirFlag.Name) + if ctx.IsSet(XDCXDataDirFlag.Name) { + cfg.DataDir = ctx.String(XDCXDataDirFlag.Name) } else { // default XDCx datadir: DATADIR/XDCx defaultXDCXDataDir := filepath.Join(XDCDataDir, "XDCx") @@ -1162,23 +1232,23 @@ func SetXDCXConfig(ctx *cli.Context, cfg *XDCx.Config, XDCDataDir string) { } } log.Info("XDCX datadir", "path", cfg.DataDir) - if ctx.GlobalIsSet(XDCXDBEngineFlag.Name) { - cfg.DBEngine = ctx.GlobalString(XDCXDBEngineFlag.Name) + if ctx.IsSet(XDCXDBEngineFlag.Name) { + cfg.DBEngine = ctx.String(XDCXDBEngineFlag.Name) } else { cfg.DBEngine = XDCXDBEngineFlag.Value } - if ctx.GlobalIsSet(XDCXDBNameFlag.Name) { - cfg.DBName = ctx.GlobalString(XDCXDBNameFlag.Name) + if ctx.IsSet(XDCXDBNameFlag.Name) { + cfg.DBName = ctx.String(XDCXDBNameFlag.Name) } else { cfg.DBName = XDCXDBNameFlag.Value } - if ctx.GlobalIsSet(XDCXDBConnectionUrlFlag.Name) { - cfg.ConnectionUrl = ctx.GlobalString(XDCXDBConnectionUrlFlag.Name) + if ctx.IsSet(XDCXDBConnectionUrlFlag.Name) { + cfg.ConnectionUrl = ctx.String(XDCXDBConnectionUrlFlag.Name) } else { cfg.ConnectionUrl = XDCXDBConnectionUrlFlag.Value } - if ctx.GlobalIsSet(XDCXDBReplicaSetNameFlag.Name) { - cfg.ReplicaSetName = ctx.GlobalString(XDCXDBReplicaSetNameFlag.Name) + if ctx.IsSet(XDCXDBReplicaSetNameFlag.Name) { + cfg.ReplicaSetName = ctx.String(XDCXDBReplicaSetNameFlag.Name) } } @@ -1192,7 +1262,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) setEtherbase(ctx, ks, cfg) - setGPO(ctx, &cfg.GPO, ctx.GlobalString(SyncModeFlag.Name) == "light") + setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light") setTxPool(ctx, &cfg.TxPool) setEthash(ctx, cfg) @@ -1217,70 +1287,70 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { godebug.SetGCPercent(int(gogc)) switch { - case ctx.GlobalIsSet(SyncModeFlag.Name): - cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) - case ctx.GlobalBool(FastSyncFlag.Name): + case ctx.IsSet(SyncModeFlag.Name): + cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) + case ctx.Bool(FastSyncFlag.Name): cfg.SyncMode = downloader.FastSync - case ctx.GlobalBool(LightModeFlag.Name): + case ctx.Bool(LightModeFlag.Name): cfg.SyncMode = downloader.LightSync } - if ctx.GlobalIsSet(LightServFlag.Name) { - cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) + if ctx.IsSet(LightServFlag.Name) { + cfg.LightServ = ctx.Int(LightServFlag.Name) } - if ctx.GlobalIsSet(LightPeersFlag.Name) { - cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) + if ctx.IsSet(LightPeersFlag.Name) { + cfg.LightPeers = ctx.Int(LightPeersFlag.Name) } - if ctx.GlobalIsSet(NetworkIdFlag.Name) { - cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) + if ctx.IsSet(NetworkIdFlag.Name) { + cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name) } - if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { - cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 + if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheDatabaseFlag.Name) { + cfg.DatabaseCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 } - cfg.DatabaseHandles = MakeDatabaseHandles(ctx.GlobalInt(FDLimitFlag.Name)) + cfg.DatabaseHandles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) - if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { + if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } - cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" + cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive" - if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { - cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 + if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { + cfg.TrieCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 } - if ctx.GlobalIsSet(StakerThreadsFlag.Name) { - cfg.MinerThreads = ctx.GlobalInt(StakerThreadsFlag.Name) + if ctx.IsSet(StakerThreadsFlag.Name) { + cfg.MinerThreads = ctx.Int(StakerThreadsFlag.Name) } - if ctx.GlobalIsSet(DocRootFlag.Name) { - cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) + if ctx.IsSet(DocRootFlag.Name) { + cfg.DocRoot = ctx.String(DocRootFlag.Name) } - if ctx.GlobalIsSet(RPCGlobalGasCapFlag.Name) { - cfg.RPCGasCap = ctx.GlobalUint64(RPCGlobalGasCapFlag.Name) + if ctx.IsSet(RPCGlobalGasCapFlag.Name) { + cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name) } - if ctx.GlobalIsSet(RPCGlobalTxFeeCap.Name) { - cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCap.Name) + if ctx.IsSet(RPCGlobalTxFeeCap.Name) { + cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalTxFeeCap.Name) } - if ctx.GlobalIsSet(RPCGlobalGasCapFlag.Name) { - cfg.RPCGasCap = ctx.GlobalUint64(RPCGlobalGasCapFlag.Name) + if ctx.IsSet(RPCGlobalGasCapFlag.Name) { + cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name) } - if ctx.GlobalIsSet(ExtraDataFlag.Name) { - cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name)) + if ctx.IsSet(ExtraDataFlag.Name) { + cfg.ExtraData = []byte(ctx.String(ExtraDataFlag.Name)) } - if ctx.GlobalIsSet(GasPriceFlag.Name) { - cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name) + if ctx.IsSet(GasPriceFlag.Name) { + cfg.GasPrice = flags.GlobalBig(ctx, GasPriceFlag.Name) } if ctx.IsSet(CacheLogSizeFlag.Name) { cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name) } - if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { + if ctx.IsSet(VMEnableDebugFlag.Name) { // TODO(fjl): force-enable this in --dev mode - cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) + cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name) } if cfg.RPCGasCap != 0 { log.Info("Set global gas cap", "cap", cfg.RPCGasCap) } else { log.Info("Global gas cap disabled") } - if ctx.GlobalIsSet(StoreRewardFlag.Name) { + if ctx.IsSet(StoreRewardFlag.Name) { common.StoreRewardFolder = filepath.Join(stack.DataDir(), "XDC", "rewards") if _, err := os.Stat(common.StoreRewardFolder); os.IsNotExist(err) { os.Mkdir(common.StoreRewardFolder, os.ModePerm) @@ -1288,17 +1358,17 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } // Override any default configs for hard coded networks. switch { - case ctx.GlobalBool(TestnetFlag.Name): - if !ctx.GlobalIsSet(NetworkIdFlag.Name) { + case ctx.Bool(TestnetFlag.Name): + if !ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = 3 } cfg.Genesis = core.DefaultTestnetGenesisBlock() - case ctx.GlobalBool(RinkebyFlag.Name): - if !ctx.GlobalIsSet(NetworkIdFlag.Name) { + case ctx.Bool(RinkebyFlag.Name): + if !ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = 4 } cfg.Genesis = core.DefaultRinkebyGenesisBlock() - case ctx.GlobalBool(DeveloperFlag.Name): + case ctx.Bool(DeveloperFlag.Name): // Create new developer account or reuse existing one var ( developer accounts.Account @@ -1317,8 +1387,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } log.Info("Using developer account", "address", developer.Address) - cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address) - if !ctx.GlobalIsSet(GasPriceFlag.Name) { + cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), developer.Address) + if !ctx.IsSet(GasPriceFlag.Name) { cfg.GasPrice = big.NewInt(1) } } @@ -1328,17 +1398,17 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { // SetupNetwork configures the system for either the main net or some test network. func SetupNetwork(ctx *cli.Context) { // TODO(fjl): move target gas limit into config - params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name) + params.TargetGasLimit = ctx.Uint64(TargetGasLimitFlag.Name) } // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { var ( - cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 - handles = MakeDatabaseHandles(ctx.GlobalInt(FDLimitFlag.Name)) + cache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 + handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) ) name := "chaindata" - if ctx.GlobalBool(LightModeFlag.Name) { + if ctx.Bool(LightModeFlag.Name) { name = "lightchaindata" } chainDb, err := stack.OpenDatabase(name, cache, handles, "") @@ -1351,11 +1421,11 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { func MakeGenesis(ctx *cli.Context) *core.Genesis { var genesis *core.Genesis switch { - case ctx.GlobalBool(TestnetFlag.Name): + case ctx.Bool(TestnetFlag.Name): genesis = core.DefaultTestnetGenesisBlock() - case ctx.GlobalBool(RinkebyFlag.Name): + case ctx.Bool(RinkebyFlag.Name): genesis = core.DefaultRinkebyGenesisBlock() - case ctx.GlobalBool(DeveloperFlag.Name): + case ctx.Bool(DeveloperFlag.Name): Fatalf("Developer chains are ephemeral") } return genesis @@ -1375,7 +1445,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai engine = XDPoS.New(config, chainDb) } else { engine = ethash.NewFaker() - if !ctx.GlobalBool(FakePoWFlag.Name) { + if !ctx.Bool(FakePoWFlag.Name) { engine = ethash.New(ethash.Config{ CacheDir: stack.ResolvePath(ethconfig.Defaults.Ethash.CacheDir), CachesInMem: ethconfig.Defaults.Ethash.CachesInMem, @@ -1387,18 +1457,18 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai } Fatalf("Only support XDPoS consensus") } - if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { + if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } cache := &core.CacheConfig{ - Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive", + Disabled: ctx.String(GCModeFlag.Name) == "archive", TrieNodeLimit: ethconfig.Defaults.TrieCache, TrieTimeLimit: ethconfig.Defaults.TrieTimeout, } - if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { - cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 + if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { + cache.TrieNodeLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 } - vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} + vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)} chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg) if err != nil { Fatalf("Can't create BlockChain: %v", err) @@ -1410,43 +1480,19 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai // scripts to preload before starting. func MakeConsolePreloads(ctx *cli.Context) []string { // Skip preloading if there's nothing to preload - if ctx.GlobalString(PreloadJSFlag.Name) == "" { + if ctx.String(PreloadJSFlag.Name) == "" { return nil } // Otherwise resolve absolute paths and return them preloads := []string{} - assets := ctx.GlobalString(JSpathFlag.Name) - for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { + assets := ctx.String(JSpathFlag.Name) + for _, file := range strings.Split(ctx.String(PreloadJSFlag.Name), ",") { preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file))) } return preloads } -// MigrateFlags sets the global flag from a local flag when it's set. -// This is a temporary function used for migrating old command/flags to the -// new format. -// -// e.g. XDC account new --keystore /tmp/mykeystore --lightkdf -// -// is equivalent after calling this method with: -// -// XDC --keystore /tmp/mykeystore --lightkdf account new -// -// This allows the use of the existing configuration functionality. -// When all flags are migrated this function can be removed and the existing -// configuration functionality must be changed that is uses local flags -func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { - return func(ctx *cli.Context) error { - for _, name := range ctx.FlagNames() { - if ctx.IsSet(name) { - ctx.GlobalSet(name, ctx.String(name)) - } - } - return action(ctx) - } -} - // find all filenames match the given pattern in the given root directory func WalkMatch(root, pattern string) ([]string, error) { matches := []string{} @@ -1487,8 +1533,8 @@ func SetupMetrics(ctx *cli.Context) { if metrics.Enabled { log.Info("Enabling metrics collection") - if ctx.GlobalIsSet(MetricsHTTPFlag.Name) { - address := fmt.Sprintf("%s:%d", ctx.GlobalString(MetricsHTTPFlag.Name), ctx.GlobalInt(MetricsPortFlag.Name)) + if ctx.IsSet(MetricsHTTPFlag.Name) { + address := fmt.Sprintf("%s:%d", ctx.String(MetricsHTTPFlag.Name), ctx.Int(MetricsPortFlag.Name)) log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address) exp.Setup(address) } diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go new file mode 100644 index 0000000000000..b47a745956133 --- /dev/null +++ b/cmd/utils/flags_legacy.go @@ -0,0 +1,84 @@ +// Copyright 2020 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 . + +package utils + +import ( + "fmt" + + "github.com/XinFinOrg/XDPoSChain/internal/flags" + "github.com/urfave/cli/v2" +) + +var ShowDeprecated = &cli.Command{ + Action: showDeprecated, + Name: "show-deprecated-flags", + Usage: "Show flags that have been deprecated", + ArgsUsage: " ", + Description: "Show flags that have been deprecated and will soon be removed", +} + +var DeprecatedFlags = []cli.Flag{ + FastSyncFlag, + LightModeFlag, + NoUSBFlag, + LogBacktraceAtFlag, + LogDebugFlag, +} + +var ( + FastSyncFlag = &cli.BoolFlag{ + Name: "fast", + Usage: "Enable fast syncing through state downloads", + Category: flags.DeprecatedCategory, + } + LightModeFlag = &cli.BoolFlag{ + Name: "light", + Usage: "Enable light client mode", + Category: flags.DeprecatedCategory, + } + // (Deprecated May 2020, shown in aliased flags section) + NoUSBFlag = &cli.BoolFlag{ + Name: "nousb", + Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)", + Category: flags.DeprecatedCategory, + } + // Deprecated November 2023 + LogBacktraceAtFlag = &cli.StringFlag{ + Name: "log-backtrace", + Usage: "Request a stack trace at a specific logging statement (deprecated)", + Value: "", + Category: flags.DeprecatedCategory, + } + LogDebugFlag = &cli.BoolFlag{ + Name: "log-debug", + Usage: "Prepends log messages with call-site location (deprecated)", + Category: flags.DeprecatedCategory, + } +) + +// showDeprecated displays deprecated flags that will be soon removed from the codebase. +func showDeprecated(*cli.Context) error { + fmt.Println("--------------------------------------------------------------------") + fmt.Println("The following flags are deprecated and will be removed in the future!") + fmt.Println("--------------------------------------------------------------------") + fmt.Println() + for _, flag := range DeprecatedFlags { + fmt.Println(flag.String()) + } + fmt.Println() + return nil +} diff --git a/go.mod b/go.mod index a519dba12ac18..11576fdce6b50 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,6 @@ require ( gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 - gopkg.in/urfave/cli.v1 v1.20.0 ) require ( @@ -50,13 +49,14 @@ require ( github.com/kylelemons/godebug v1.1.0 github.com/mattn/go-isatty v0.0.17 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible - golang.org/x/exp v0.0.0-20231006140011-7918f672742d + github.com/urfave/cli/v2 v2.27.5 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/dlclark/regexp2 v1.10.0 // indirect github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect @@ -69,7 +69,9 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect golang.org/x/mod v0.13.0 // indirect golang.org/x/term v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect diff --git a/go.sum b/go.sum index d21c1f26a13a3..782d2654a694c 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,8 @@ github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -132,6 +134,8 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= @@ -144,12 +148,14 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -215,8 +221,6 @@ gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 h1:hhsSf/5z74 gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= -gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/internal/cmdtest/test_cmd.go b/internal/cmdtest/test_cmd.go index 45d10897ef4e0..5369678adb86d 100644 --- a/internal/cmdtest/test_cmd.go +++ b/internal/cmdtest/test_cmd.go @@ -26,6 +26,7 @@ import ( "regexp" "strings" "sync" + "syscall" "testing" "text/template" "time" @@ -49,6 +50,8 @@ type TestCmd struct { stdout *bufio.Reader stdin io.WriteCloser stderr *testlogger + // Err will contain the process exit error or interrupt signal error + Err error } // Run exec's the current binary using name as argv[0] which will trigger the @@ -181,11 +184,25 @@ func (tt *TestCmd) ExpectExit() { } func (tt *TestCmd) WaitExit() { - tt.cmd.Wait() + tt.Err = tt.cmd.Wait() } func (tt *TestCmd) Interrupt() { - tt.cmd.Process.Signal(os.Interrupt) + tt.Err = tt.cmd.Process.Signal(os.Interrupt) +} + +// ExitStatus exposes the process' OS exit code +// It will only return a valid value after the process has finished. +func (tt *TestCmd) ExitStatus() int { + if tt.Err != nil { + exitErr := tt.Err.(*exec.ExitError) + if exitErr != nil { + if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { + return status.ExitStatus() + } + } + } + return 0 } // StderrText returns any stderr output written so far. diff --git a/internal/debug/flags.go b/internal/debug/flags.go index 6534e2be1c9c0..6a366778c141f 100644 --- a/internal/debug/flags.go +++ b/internal/debug/flags.go @@ -26,105 +26,127 @@ import ( "path/filepath" "runtime" + "github.com/XinFinOrg/XDPoSChain/internal/flags" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/metrics" "github.com/XinFinOrg/XDPoSChain/metrics/exp" "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" + "github.com/urfave/cli/v2" "gopkg.in/natefinch/lumberjack.v2" - "gopkg.in/urfave/cli.v1" ) var ( - verbosityFlag = cli.IntFlag{ - Name: "verbosity", - Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail", - Value: 3, + verbosityFlag = &cli.IntFlag{ + Name: "verbosity", + Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail", + Value: 3, + Category: flags.LoggingCategory, } logVmoduleFlag = &cli.StringFlag{ - Name: "log-vmodule", - Usage: "Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4)", - Value: "", + Name: "log-vmodule", + Usage: "Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4)", + Value: "", + Category: flags.LoggingCategory, } - vmoduleFlag = cli.StringFlag{ - Name: "vmodule", - Usage: "Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4)", - Value: "", + vmoduleFlag = &cli.StringFlag{ + Name: "vmodule", + Usage: "Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4)", + Value: "", + Category: flags.LoggingCategory, } logjsonFlag = &cli.BoolFlag{ - Name: "log-json", - Usage: "Format logs with JSON", - Hidden: true, + Name: "log-json", + Usage: "Format logs with JSON", + Hidden: true, + Category: flags.LoggingCategory, } logFormatFlag = &cli.StringFlag{ - Name: "log-format", - Usage: "Log format to use (json|logfmt|terminal)", + Name: "log-format", + Usage: "Log format to use (json|logfmt|terminal)", + Category: flags.LoggingCategory, } logFileFlag = &cli.StringFlag{ - Name: "log-file", - Usage: "Write logs to a file", + Name: "log-file", + Usage: "Write logs to a file", + Category: flags.LoggingCategory, } logRotateFlag = &cli.BoolFlag{ - Name: "log-rotate", - Usage: "Enables log file rotation", + Name: "log-rotate", + Usage: "Enables log file rotation", + Category: flags.LoggingCategory, } logMaxSizeMBsFlag = &cli.IntFlag{ - Name: "log-maxsize", - Usage: "Maximum size in MBs of a single log file", - Value: 100, + Name: "log-maxsize", + Usage: "Maximum size in MBs of a single log file", + Value: 100, + Category: flags.LoggingCategory, } logMaxBackupsFlag = &cli.IntFlag{ - Name: "log-maxbackups", - Usage: "Maximum number of log files to retain", - Value: 10, + Name: "log-maxbackups", + Usage: "Maximum number of log files to retain", + Value: 10, + Category: flags.LoggingCategory, } logMaxAgeFlag = &cli.IntFlag{ - Name: "log-maxage", - Usage: "Maximum number of days to retain a log file", - Value: 30, + Name: "log-maxage", + Usage: "Maximum number of days to retain a log file", + Value: 30, + Category: flags.LoggingCategory, } logCompressFlag = &cli.BoolFlag{ - Name: "log-compress", - Usage: "Compress the log files", - } - pprofFlag = cli.BoolFlag{ - Name: "pprof", - Usage: "Enable the pprof HTTP server", - } - pprofPortFlag = cli.IntFlag{ - Name: "pprofport", - Usage: "pprof HTTP server listening port", - Value: 6060, - } - pprofAddrFlag = cli.StringFlag{ - Name: "pprofaddr", - Usage: "pprof HTTP server listening interface", - Value: "127.0.0.1", - } - memprofilerateFlag = cli.IntFlag{ - Name: "memprofilerate", - Usage: "Turn on memory profiling with the given rate", - Value: runtime.MemProfileRate, - } - blockprofilerateFlag = cli.IntFlag{ - Name: "blockprofilerate", - Usage: "Turn on block profiling with the given rate", - } - cpuprofileFlag = cli.StringFlag{ - Name: "cpuprofile", - Usage: "Write CPU profile to the given file", - } - traceFlag = cli.StringFlag{ - Name: "trace", - Usage: "Write execution trace to the given file", - } - periodicProfilingFlag = cli.BoolFlag{ - Name: "periodicprofile", - Usage: "Periodically profile cpu and memory status", - } - debugDataDirFlag = cli.StringFlag{ - Name: "debugdatadir", - Usage: "Debug Data directory for profiling output", + Name: "log-compress", + Usage: "Compress the log files", + Value: false, + Category: flags.LoggingCategory, + } + pprofFlag = &cli.BoolFlag{ + Name: "pprof", + Usage: "Enable the pprof HTTP server", + Category: flags.LoggingCategory, + } + pprofPortFlag = &cli.IntFlag{ + Name: "pprofport", + Usage: "pprof HTTP server listening port", + Value: 6060, + Category: flags.LoggingCategory, + } + pprofAddrFlag = &cli.StringFlag{ + Name: "pprofaddr", + Usage: "pprof HTTP server listening interface", + Value: "127.0.0.1", + Category: flags.LoggingCategory, + } + memprofilerateFlag = &cli.IntFlag{ + Name: "memprofilerate", + Usage: "Turn on memory profiling with the given rate", + Value: runtime.MemProfileRate, + Category: flags.LoggingCategory, + } + blockprofilerateFlag = &cli.IntFlag{ + Name: "blockprofilerate", + Usage: "Turn on block profiling with the given rate", + Category: flags.LoggingCategory, + } + cpuprofileFlag = &cli.StringFlag{ + Name: "cpuprofile", + Usage: "Write CPU profile to the given file", + Category: flags.LoggingCategory, + } + traceFlag = &cli.StringFlag{ + Name: "trace", + Usage: "Write execution trace to the given file", + Category: flags.LoggingCategory, + } + periodicProfilingFlag = &cli.BoolFlag{ + Name: "periodicprofile", + Usage: "Periodically profile cpu and memory status", + Category: flags.LoggingCategory, + } + debugDataDirFlag = &cli.StringFlag{ + Name: "debugdatadir", + Usage: "Debug Data directory for profiling output", + Category: flags.LoggingCategory, } ) @@ -178,11 +200,11 @@ func Setup(ctx *cli.Context) error { handler slog.Handler terminalOutput = io.Writer(os.Stderr) output io.Writer - logFmtFlag = ctx.GlobalString(logFormatFlag.Name) + logFmtFlag = ctx.String(logFormatFlag.Name) ) var ( - logFile = ctx.GlobalString(logFileFlag.Name) - rotation = ctx.GlobalBool(logRotateFlag.Name) + logFile = ctx.String(logFileFlag.Name) + rotation = ctx.Bool(logRotateFlag.Name) ) if len(logFile) > 0 { if err := validateLogLocation(filepath.Dir(logFile)); err != nil { @@ -205,10 +227,10 @@ func Setup(ctx *cli.Context) error { } logOutputFile = &lumberjack.Logger{ Filename: logFile, - MaxSize: ctx.GlobalInt(logMaxSizeMBsFlag.Name), - MaxBackups: ctx.GlobalInt(logMaxBackupsFlag.Name), - MaxAge: ctx.GlobalInt(logMaxAgeFlag.Name), - Compress: ctx.GlobalBool(logCompressFlag.Name), + MaxSize: ctx.Int(logMaxSizeMBsFlag.Name), + MaxBackups: ctx.Int(logMaxBackupsFlag.Name), + MaxAge: ctx.Int(logMaxAgeFlag.Name), + Compress: ctx.Bool(logCompressFlag.Name), } output = io.MultiWriter(terminalOutput, logOutputFile) } else if logFile != "" { @@ -223,7 +245,7 @@ func Setup(ctx *cli.Context) error { } switch { - case ctx.GlobalBool(logjsonFlag.Name): + case ctx.Bool(logjsonFlag.Name): // Retain backwards compatibility with `--log-json` flag if `--log-format` not set defer log.Warn("The flag '--log-json' is deprecated, please use '--log-format=json' instead") handler = log.JSONHandlerWithLevel(output, log.LevelInfo) @@ -244,18 +266,18 @@ func Setup(ctx *cli.Context) error { handler = log.NewTerminalHandler(output, useColor) default: // Unknown log format specified - return fmt.Errorf("unknown log format: %v", ctx.GlobalString(logFormatFlag.Name)) + return fmt.Errorf("unknown log format: %v", ctx.String(logFormatFlag.Name)) } glogger = log.NewGlogHandler(handler) // logging - verbosity := log.FromLegacyLevel(ctx.GlobalInt(verbosityFlag.Name)) + verbosity := log.FromLegacyLevel(ctx.Int(verbosityFlag.Name)) glogger.Verbosity(verbosity) - vmodule := ctx.GlobalString(logVmoduleFlag.Name) + vmodule := ctx.String(logVmoduleFlag.Name) if vmodule == "" { // Retain backwards compatibility with `--vmodule` flag if `--log-vmodule` not set - vmodule = ctx.GlobalString(vmoduleFlag.Name) + vmodule = ctx.String(vmoduleFlag.Name) if vmodule != "" { defer log.Warn("The flag '--vmodule' is deprecated, please use '--log-vmodule' instead") } @@ -265,31 +287,31 @@ func Setup(ctx *cli.Context) error { log.SetDefault(log.NewLogger(glogger)) // profiling, tracing - runtime.MemProfileRate = ctx.GlobalInt(memprofilerateFlag.Name) - Handler.SetBlockProfileRate(ctx.GlobalInt(blockprofilerateFlag.Name)) - if traceFile := ctx.GlobalString(traceFlag.Name); traceFile != "" { + runtime.MemProfileRate = ctx.Int(memprofilerateFlag.Name) + Handler.SetBlockProfileRate(ctx.Int(blockprofilerateFlag.Name)) + if traceFile := ctx.String(traceFlag.Name); traceFile != "" { if err := Handler.StartGoTrace(traceFile); err != nil { return err } } - if cpuFile := ctx.GlobalString(cpuprofileFlag.Name); cpuFile != "" { + if cpuFile := ctx.String(cpuprofileFlag.Name); cpuFile != "" { if err := Handler.StartCPUProfile(cpuFile); err != nil { return err } } - Handler.filePath = ctx.GlobalString(debugDataDirFlag.Name) + Handler.filePath = ctx.String(debugDataDirFlag.Name) - if periodicProfiling := ctx.GlobalBool(periodicProfilingFlag.Name); periodicProfiling { + if periodicProfiling := ctx.Bool(periodicProfilingFlag.Name); periodicProfiling { Handler.PeriodicComputeProfiling() } // pprof server - if ctx.GlobalBool(pprofFlag.Name) { + if ctx.Bool(pprofFlag.Name) { // Hook go-metrics into expvar on any /debug/metrics request, load all vars // from the registry into expvar, and execute regular expvar handler. exp.Exp(metrics.DefaultRegistry) - address := fmt.Sprintf("%s:%d", ctx.GlobalString(pprofAddrFlag.Name), ctx.GlobalInt(pprofPortFlag.Name)) + address := fmt.Sprintf("%s:%d", ctx.String(pprofAddrFlag.Name), ctx.Int(pprofPortFlag.Name)) go func() { log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address)) if err := http.ListenAndServe(address, nil); err != nil { diff --git a/internal/flags/categories.go b/internal/flags/categories.go new file mode 100644 index 0000000000000..d58534c0b6bc7 --- /dev/null +++ b/internal/flags/categories.go @@ -0,0 +1,45 @@ +// Copyright 2022 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package flags + +import "github.com/urfave/cli/v2" + +const ( + EthCategory = "ETHEREUM" + LightCategory = "LIGHT CLIENT" + DevCategory = "DEVELOPER CHAIN" + EthashCategory = "ETHASH" + TxPoolCategory = "TRANSACTION POOL" + PerfCategory = "PERFORMANCE TUNING" + AccountCategory = "ACCOUNT" + APICategory = "API AND CONSOLE" + NetworkingCategory = "NETWORKING" + MinerCategory = "MINER" + GasPriceCategory = "GAS PRICE ORACLE" + VMCategory = "VIRTUAL MACHINE" + LoggingCategory = "LOGGING AND DEBUGGING" + MetricsCategory = "METRICS AND STATS" + MiscCategory = "MISC" + DeprecatedCategory = "ALIASED (deprecated)" + XdcCategory = "XDC" + XdcxCategory = "XDCx" +) + +func init() { + cli.HelpFlag.(*cli.BoolFlag).Category = MiscCategory + cli.VersionFlag.(*cli.BoolFlag).Category = MiscCategory +} diff --git a/internal/flags/flags.go b/internal/flags/flags.go new file mode 100644 index 0000000000000..350f274455a36 --- /dev/null +++ b/internal/flags/flags.go @@ -0,0 +1,340 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package flags + +import ( + "encoding" + "errors" + "flag" + "math/big" + "os" + "os/user" + "path" + "strings" + + "github.com/XinFinOrg/XDPoSChain/common/math" + "github.com/urfave/cli/v2" +) + +// DirectoryString is custom type which is registered in the flags library which cli uses for +// argument parsing. This allows us to expand Value to an absolute path when +// the argument is parsed +type DirectoryString string + +func (s *DirectoryString) String() string { + return string(*s) +} + +func (s *DirectoryString) Set(value string) error { + *s = DirectoryString(expandPath(value)) + return nil +} + +var ( + _ cli.Flag = (*DirectoryFlag)(nil) + _ cli.RequiredFlag = (*DirectoryFlag)(nil) + _ cli.VisibleFlag = (*DirectoryFlag)(nil) + _ cli.DocGenerationFlag = (*DirectoryFlag)(nil) + _ cli.CategorizableFlag = (*DirectoryFlag)(nil) +) + +// DirectoryFlag is custom cli.Flag type which expand the received string to an absolute path. +// e.g. ~/.ethereum -> /home/username/.ethereum +type DirectoryFlag struct { + Name string + + Category string + DefaultText string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value DirectoryString + + Aliases []string +} + +// For cli.Flag: + +func (f *DirectoryFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) } +func (f *DirectoryFlag) IsSet() bool { return f.HasBeenSet } +func (f *DirectoryFlag) String() string { return cli.FlagStringer(f) } + +// Apply called by cli library, grabs variable from environment (if in env) +// and adds variable to flag set for parsing. +func (f *DirectoryFlag) Apply(set *flag.FlagSet) error { + eachName(f, func(name string) { + set.Var(&f.Value, f.Name, f.Usage) + }) + return nil +} + +// For cli.RequiredFlag: + +func (f *DirectoryFlag) IsRequired() bool { return f.Required } + +// For cli.VisibleFlag: + +func (f *DirectoryFlag) IsVisible() bool { return !f.Hidden } + +// For cli.CategorizableFlag: + +func (f *DirectoryFlag) GetCategory() string { return f.Category } + +// For cli.DocGenerationFlag: + +func (f *DirectoryFlag) TakesValue() bool { return true } +func (f *DirectoryFlag) GetUsage() string { return f.Usage } +func (f *DirectoryFlag) GetValue() string { return f.Value.String() } +func (f *DirectoryFlag) GetEnvVars() []string { return nil } // env not supported + +func (f *DirectoryFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +type TextMarshaler interface { + encoding.TextMarshaler + encoding.TextUnmarshaler +} + +// textMarshalerVal turns a TextMarshaler into a flag.Value +type textMarshalerVal struct { + v TextMarshaler +} + +func (v textMarshalerVal) String() string { + if v.v == nil { + return "" + } + text, _ := v.v.MarshalText() + return string(text) +} + +func (v textMarshalerVal) Set(s string) error { + return v.v.UnmarshalText([]byte(s)) +} + +var ( + _ cli.Flag = (*TextMarshalerFlag)(nil) + _ cli.RequiredFlag = (*TextMarshalerFlag)(nil) + _ cli.VisibleFlag = (*TextMarshalerFlag)(nil) + _ cli.DocGenerationFlag = (*TextMarshalerFlag)(nil) + _ cli.CategorizableFlag = (*TextMarshalerFlag)(nil) +) + +// TextMarshalerFlag wraps a TextMarshaler value. +type TextMarshalerFlag struct { + Name string + + Category string + DefaultText string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value TextMarshaler + + Aliases []string +} + +// For cli.Flag: + +func (f *TextMarshalerFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) } +func (f *TextMarshalerFlag) IsSet() bool { return f.HasBeenSet } +func (f *TextMarshalerFlag) String() string { return cli.FlagStringer(f) } + +func (f *TextMarshalerFlag) Apply(set *flag.FlagSet) error { + eachName(f, func(name string) { + set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage) + }) + return nil +} + +// For cli.RequiredFlag: + +func (f *TextMarshalerFlag) IsRequired() bool { return f.Required } + +// For cli.VisibleFlag: + +func (f *TextMarshalerFlag) IsVisible() bool { return !f.Hidden } + +// For cli.CategorizableFlag: + +func (f *TextMarshalerFlag) GetCategory() string { return f.Category } + +// For cli.DocGenerationFlag: + +func (f *TextMarshalerFlag) TakesValue() bool { return true } +func (f *TextMarshalerFlag) GetUsage() string { return f.Usage } +func (f *TextMarshalerFlag) GetEnvVars() []string { return nil } // env not supported + +func (f *TextMarshalerFlag) GetValue() string { + t, err := f.Value.MarshalText() + if err != nil { + return "(ERR: " + err.Error() + ")" + } + return string(t) +} + +func (f *TextMarshalerFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GlobalTextMarshaler returns the value of a TextMarshalerFlag from the global flag set. +func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { + val := ctx.Generic(name) + if val == nil { + return nil + } + return val.(textMarshalerVal).v +} + +var ( + _ cli.Flag = (*BigFlag)(nil) + _ cli.RequiredFlag = (*BigFlag)(nil) + _ cli.VisibleFlag = (*BigFlag)(nil) + _ cli.DocGenerationFlag = (*BigFlag)(nil) + _ cli.CategorizableFlag = (*BigFlag)(nil) +) + +// BigFlag is a command line flag that accepts 256 bit big integers in decimal or +// hexadecimal syntax. +type BigFlag struct { + Name string + + Category string + DefaultText string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *big.Int + + Aliases []string +} + +// For cli.Flag: + +func (f *BigFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) } +func (f *BigFlag) IsSet() bool { return f.HasBeenSet } +func (f *BigFlag) String() string { return cli.FlagStringer(f) } + +func (f *BigFlag) Apply(set *flag.FlagSet) error { + eachName(f, func(name string) { + f.Value = new(big.Int) + set.Var((*bigValue)(f.Value), f.Name, f.Usage) + }) + + return nil +} + +// For cli.RequiredFlag: + +func (f *BigFlag) IsRequired() bool { return f.Required } + +// For cli.VisibleFlag: + +func (f *BigFlag) IsVisible() bool { return !f.Hidden } + +// For cli.CategorizableFlag: + +func (f *BigFlag) GetCategory() string { return f.Category } + +// For cli.DocGenerationFlag: + +func (f *BigFlag) TakesValue() bool { return true } +func (f *BigFlag) GetUsage() string { return f.Usage } +func (f *BigFlag) GetValue() string { return f.Value.String() } +func (f *BigFlag) GetEnvVars() []string { return nil } // env not supported + +func (f *BigFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// bigValue turns *big.Int into a flag.Value +type bigValue big.Int + +func (b *bigValue) String() string { + if b == nil { + return "" + } + return (*big.Int)(b).String() +} + +func (b *bigValue) Set(s string) error { + intVal, ok := math.ParseBig256(s) + if !ok { + return errors.New("invalid integer syntax") + } + *b = (bigValue)(*intVal) + return nil +} + +// GlobalBig returns the value of a BigFlag from the global flag set. +func GlobalBig(ctx *cli.Context, name string) *big.Int { + val := ctx.Generic(name) + if val == nil { + return nil + } + return (*big.Int)(val.(*bigValue)) +} + +// Expands a file path +// 1. replace tilde with users home dir +// 2. expands embedded environment variables +// 3. cleans the path, e.g. /a/b/../c -> /a/c +// Note, it has limitations, e.g. ~someuser/tmp will not be expanded +func expandPath(p string) string { + if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { + if home := HomeDir(); home != "" { + p = home + p[1:] + } + } + return path.Clean(os.ExpandEnv(p)) +} + +func HomeDir() string { + if home := os.Getenv("HOME"); home != "" { + return home + } + if usr, err := user.Current(); err == nil { + return usr.HomeDir + } + return "" +} + +func eachName(f cli.Flag, fn func(string)) { + for _, name := range f.Names() { + name = strings.Trim(name, " ") + fn(name) + } +} diff --git a/cmd/utils/customflags_test.go b/internal/flags/flags_test.go similarity index 61% rename from cmd/utils/customflags_test.go rename to internal/flags/flags_test.go index de39ca36a116c..a0d4af7ca3606 100644 --- a/cmd/utils/customflags_test.go +++ b/internal/flags/flags_test.go @@ -1,20 +1,20 @@ // Copyright 2015 The go-ethereum Authors -// This file is part of go-ethereum. +// This file is part of the go-ethereum library. // -// 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 go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser 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, +// The go-ethereum library 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. +// GNU Lesser 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 . +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . -package utils +package flags import ( "os" diff --git a/internal/flags/helpers.go b/internal/flags/helpers.go new file mode 100644 index 0000000000000..e121aa544c407 --- /dev/null +++ b/internal/flags/helpers.go @@ -0,0 +1,176 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package flags + +import ( + "fmt" + "strings" + + "github.com/XinFinOrg/XDPoSChain/params" + "github.com/urfave/cli/v2" +) + +// NewApp creates an app with sane defaults. +func NewApp(gitCommit, usage string) *cli.App { + app := cli.NewApp() + app.EnableBashCompletion = true + app.Version = params.VersionWithCommit(gitCommit) + app.Usage = usage + app.Copyright = "Copyright 2024 XDPoSChain" + app.Before = func(ctx *cli.Context) error { + MigrateGlobalFlags(ctx) + return nil + } + return app +} + +var migrationApplied = map[*cli.Command]struct{}{} + +// MigrateGlobalFlags makes all global flag values available in the +// context. This should be called as early as possible in app.Before. +// +// Example: +// +// geth account new --keystore /tmp/mykeystore --lightkdf +// +// is equivalent after calling this method with: +// +// geth --keystore /tmp/mykeystore --lightkdf account new +// +// i.e. in the subcommand Action function of 'account new', ctx.Bool("lightkdf) +// will return true even if --lightkdf is set as a global option. +// +// This function may become unnecessary when https://github.com/urfave/cli/pull/1245 is merged. +func MigrateGlobalFlags(ctx *cli.Context) { + var iterate func(cs []*cli.Command, fn func(*cli.Command)) + iterate = func(cs []*cli.Command, fn func(*cli.Command)) { + for _, cmd := range cs { + if _, ok := migrationApplied[cmd]; ok { + continue + } + migrationApplied[cmd] = struct{}{} + fn(cmd) + iterate(cmd.Subcommands, fn) + } + } + + // This iterates over all commands and wraps their action function. + iterate(ctx.App.Commands, func(cmd *cli.Command) { + action := cmd.Action + cmd.Action = func(ctx *cli.Context) error { + doMigrateFlags(ctx) + return action(ctx) + } + }) +} + +func doMigrateFlags(ctx *cli.Context) { + for _, name := range ctx.FlagNames() { + for _, parent := range ctx.Lineage()[1:] { + if parent.IsSet(name) { + ctx.Set(name, parent.String(name)) + break + } + } + } +} + +func init() { + cli.FlagStringer = FlagString +} + +// FlagString prints a single flag in help. +func FlagString(f cli.Flag) string { + df, ok := f.(cli.DocGenerationFlag) + if !ok { + return "" + } + + needsPlaceholder := df.TakesValue() + placeholder := "" + if needsPlaceholder { + placeholder = "value" + } + + namesText := pad(cli.FlagNamePrefixer(df.Names(), placeholder), 30) + + defaultValueString := "" + if s := df.GetDefaultText(); s != "" { + defaultValueString = " (default: " + s + ")" + } + + usage := strings.TrimSpace(df.GetUsage()) + envHint := strings.TrimSpace(cli.FlagEnvHinter(df.GetEnvVars(), "")) + if len(envHint) > 0 { + usage += " " + envHint + } + + usage = wordWrap(usage, 80) + usage = indent(usage, 10) + + return fmt.Sprintf("\n %s%s\n%s", namesText, defaultValueString, usage) +} + +func pad(s string, length int) string { + if len(s) < length { + s += strings.Repeat(" ", length-len(s)) + } + return s +} + +func indent(s string, nspace int) string { + ind := strings.Repeat(" ", nspace) + return ind + strings.ReplaceAll(s, "\n", "\n"+ind) +} + +func wordWrap(s string, width int) string { + var ( + output strings.Builder + lineLength = 0 + ) + + for { + sp := strings.IndexByte(s, ' ') + var word string + if sp == -1 { + word = s + } else { + word = s[:sp] + } + wlen := len(word) + over := lineLength+wlen >= width + if over { + output.WriteByte('\n') + lineLength = 0 + } else { + if lineLength != 0 { + output.WriteByte(' ') + lineLength++ + } + } + + output.WriteString(word) + lineLength += wlen + + if sp == -1 { + break + } + s = s[wlen+1:] + } + + return output.String() +}