Merge pull request #741 from gzliudan/cli-v2

cmd: migrate to urfave/cli/v2
This commit is contained in:
Daniel Liu 2024-11-25 17:25:53 +08:00 committed by GitHub
commit 4278930885
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 2436 additions and 1976 deletions

View file

@ -53,10 +53,10 @@ echo "Running a node with wallet: ${wallet} at local"
../../build/bin/XDC --ethstats ${netstats} --gcmode=archive \
--bootnodes ${bootnodes} --syncmode full \
--datadir ./tmp/xdcchain --networkid 551 \
-port 30303 --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 \
--rpcport 8545 \
--rpcapi db,eth,debug,miner,net,shh,txpool,personal,web3,XDPoS \
--rpcvhosts "*" --unlock "${wallet}" --password ./tmp/.pwd --mine \
--gasprice "1" --targetgaslimit "420000000" --verbosity ${log_level} \
--ws --wsaddr=0.0.0.0 --wsport 8555 \
--wsorigins "*" 2>&1 >>./tmp/xdc.log
--port 30303 --http --http-corsdomain "*" --http-addr 0.0.0.0 \
--http-port 8545 \
--http-api db,eth,debug,miner,net,shh,txpool,personal,web3,XDPoS \
--http-vhosts "*" --unlock "${wallet}" --password ./tmp/.pwd --mine \
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
--ws --ws-addr=0.0.0.0 --ws-port 8555 \
--ws-origins "*" 2>&1 >>./tmp/xdc.log

View file

@ -75,11 +75,11 @@ XDC --ethstats ${netstats} --gcmode archive \
--nat extip:${INSTANCE_IP} \
--bootnodes ${bootnodes} --syncmode full \
--datadir /work/xdcchain --networkid 551 \
-port $port --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 \
--rpcport $rpc_port \
--rpcapi db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
--rpcvhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
--gasprice "1" --targetgaslimit "420000000" --verbosity ${log_level} \
--port $port --http --http-corsdomain "*" --http-addr 0.0.0.0 \
--http-port $rpc_port \
--http-api db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
--http-vhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
--debugdatadir /work/xdcchain \
--ws --wsaddr=0.0.0.0 --wsport $ws_port \
--wsorigins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log

View file

@ -74,11 +74,11 @@ XDC --ethstats ${netstats} --gcmode archive \
--nat extip:${INSTANCE_IP} \
--bootnodes ${bootnodes} --syncmode full \
--datadir /work/xdcchain --networkid 50 \
-port $port --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 \
--rpcport $rpc_port \
--rpcapi db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
--rpcvhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
--gasprice "1" --targetgaslimit "420000000" --verbosity ${log_level} \
--port $port --http --http-corsdomain "*" --http-addr 0.0.0.0 \
--http-port $rpc_port \
--http-api db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
--http-vhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
--debugdatadir /work/xdcchain \
--ws --wsaddr=0.0.0.0 --wsport $ws_port \
--wsorigins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log

View file

@ -76,11 +76,11 @@ XDC --ethstats ${netstats} --gcmode archive \
--nat extip:${INSTANCE_IP} \
--bootnodes ${bootnodes} --syncmode full \
--datadir /work/xdcchain --networkid 51 \
-port $port --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 \
--rpcport $rpc_port \
--rpcapi db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
--rpcvhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
--gasprice "1" --targetgaslimit "420000000" --verbosity ${log_level} \
--port $port --http --http-corsdomain "*" --http-addr 0.0.0.0 \
--http-port $rpc_port \
--http-api db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
--http-vhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
--debugdatadir /work/xdcchain \
--ws --wsaddr=0.0.0.0 --wsport $ws_port \
--wsorigins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log

View file

@ -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: "<keyFile>",
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: "<address>",
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)

View file

@ -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()
if runtime.GOOS == "windows" {
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
`)
} else {
XDC.Expect(`
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" {
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
`
}
{
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.

View file

@ -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"

View file

@ -36,21 +36,21 @@ import (
"github.com/XinFinOrg/XDPoSChain/event"
"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: "<genesisPath>",
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 +58,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: "<filename> (<filename 2> ... <filename N>) ",
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 +79,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: "<filename> [<blockNumFirst> <blockNumLast>]",
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: "<datafile>",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.XDCXDataDirFlag,
utils.CacheFlag,
utils.LightModeFlag,
},
@ -110,57 +111,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: "<dumpfile>",
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: "<sourceChaindataDir>",
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: "[<blockHash> | <blockNum>]...",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.XDCXDataDirFlag,
utils.CacheFlag,
utils.LightModeFlag,
},
@ -174,12 +176,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 +187,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 +224,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 +256,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 +294,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 +322,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 +335,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 +359,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 +379,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 +398,24 @@ 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)
var syncmode downloader.SyncMode
if err := syncmode.UnmarshalText([]byte(ctx.String(utils.SyncModeFlag.Name))); err != nil {
utils.Fatalf("invalid --syncmode flag: %v", err)
}
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 +486,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))

View file

@ -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.MiningEnabledFlag.Name) {
cfg.StakeEnable = ctx.Bool(utils.MiningEnabledFlag.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.MinerGasPriceFlag.Name) {
if gasPrice := int64(ctx.Int(utils.MinerGasPriceFlag.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)

View file

@ -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> [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
}
@ -114,17 +111,20 @@ func localConsole(ctx *cli.Context) error {
// remoteConsole will connect to a remote XDC instance, attaching a JavaScript
// console to it.
func remoteConsole(ctx *cli.Context) error {
// Attach to a remotely running XDC instance and start the JavaScript console
if ctx.Args().Len() > 1 {
utils.Fatalf("invalid command-line: too many arguments")
}
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 +137,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 +148,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 +190,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 +202,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)
}

View file

@ -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")
"--miner-etherbase", coinbase)
// Gather all the infos the welcome message needs to contain
XDC.SetTemplateFunc("goos", func() string { return runtime.GOOS })
@ -76,18 +77,18 @@ 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)
"--miner-etherbase", coinbase, "--ipcpath", ipc)
time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open
testAttachWelcome(t, XDC, "ipc:"+ipc, ipcAPIs)
@ -99,10 +100,12 @@ 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)
"--miner-etherbase", coinbase, "--http", "--http-port", port)
time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open
testAttachWelcome(t, XDC, "http://localhost:"+port, httpAPIs)
@ -114,11 +117,12 @@ 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)
"--miner-etherbase", coinbase, "--ws", "--ws-port", port)
time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open
testAttachWelcome(t, XDC, "ws://localhost:"+port, httpAPIs)

View file

@ -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

View file

@ -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,
@ -101,11 +101,11 @@ var (
utils.ListenPortFlag,
utils.MaxPeersFlag,
utils.MaxPendingPeersFlag,
utils.EtherbaseFlag,
utils.GasPriceFlag,
utils.StakerThreadsFlag,
utils.StakingEnabledFlag,
utils.TargetGasLimitFlag,
utils.MinerEtherbaseFlag,
utils.MinerGasPriceFlag,
utils.MinerThreadsFlag,
utils.MiningEnabledFlag,
utils.MinerGasLimitFlag,
utils.NATFlag,
utils.NoDiscoverFlag,
//utils.DiscoveryV5Flag,
@ -122,8 +122,8 @@ var (
utils.EnableXDCPrefixFlag,
utils.RewoundFlag,
utils.NetworkIdFlag,
utils.RPCCORSDomainFlag,
utils.RPCVirtualHostsFlag,
utils.HTTPCORSDomainFlag,
utils.HTTPVirtualHostsFlag,
utils.EthStatsURLFlag,
utils.MetricsEnabledFlag,
utils.MetricsHTTPFlag,
@ -145,14 +145,14 @@ var (
}
rpcFlags = []cli.Flag{
utils.RPCEnabledFlag,
utils.HTTPEnabledFlag,
utils.RPCGlobalGasCapFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
utils.RPCHttpReadTimeoutFlag,
utils.RPCHttpWriteTimeoutFlag,
utils.RPCHttpIdleTimeoutFlag,
utils.RPCApiFlag,
utils.HTTPListenAddrFlag,
utils.HTTPPortFlag,
utils.HTTPReadTimeoutFlag,
utils.HTTPWriteTimeoutFlag,
utils.HTTPIdleTimeoutFlag,
utils.HTTPApiFlag,
utils.WSEnabledFlag,
utils.WSListenAddrFlag,
utils.WSPortFlag,
@ -167,9 +167,8 @@ var (
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,
@ -194,12 +193,15 @@ func init() {
app.Flags = append(app.Flags, rpcFlags...)
app.Flags = append(app.Flags, consoleFlags...)
app.Flags = append(app.Flags, debug.Flags...)
flags.AutoEnvVars(app.Flags, "XDC")
app.Before = func(ctx *cli.Context) error {
runtime.GOMAXPROCS(runtime.NumCPU())
flags.MigrateGlobalFlags(ctx)
if err := debug.Setup(ctx); err != nil {
return err
}
flags.CheckEnvVars(ctx, app.Flags, "XDC")
// Start system runtime metrics collection
go metrics.CollectProcessMetrics(3 * time.Second)
@ -242,11 +244,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 +301,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 +317,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 +330,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.MinerThreadsFlag.Name); threads > 0 {
type threaded interface {
SetThreads(threads int)
}
@ -370,7 +372,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.MinerThreadsFlag.Name); threads > 0 {
type threaded interface {
SetThreads(threads int)
}

View file

@ -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: "<blockNum> <outputDir>",
Category: "MISCELLANEOUS COMMANDS",
Description: `
The makecache command generates an ethash cache in <outputDir>.
@ -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: "<blockNum> <outputDir>",
Category: "MISCELLANEOUS COMMANDS",
Description: `
The makedag command generates an ethash DAG in <outputDir>.
@ -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 <block number> <outputdir>`)
}
@ -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 <block number> <outputdir>`)
}

View file

@ -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 "--miner-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() {

View file

@ -5,24 +5,24 @@ NAT = "" # flag --nat
[Eth]
NetworkId = 89 # flag --networkid
SyncMode = "full" # flag --syncmode
GasPrice = 1 # flag --gasprice
GasPrice = 1 # flag --miner-gasprice
[Shh]
[Node]
DataDir = "node1/" # flag --datadir
HTTPPort = 8501 # flag --rpcport
HTTPHost = "localhost" # flags --rpcaddr & --rpc
HTTPPort = 8501 # flag --http-port
HTTPHost = "localhost" # flags --http-addr & --http
# in 3 cases :
# HTTPHost is "" == --rpc & --rpcaddr is not set
# HTTPHost is "localhost" or "127.0.0.1" == only set --rpc
# HTTPHost is other IP (ex : 192.168.1.1) = set 2 flags --rpc & --rpcaddr
WSHost = "localhost" # flags --wsaddr & --ws . same option HTTPHost
WSPort = 8546 # flag --wsport
WSModules = ["eth","ssh"] #flag --wsapi
# HTTPHost is "" == --http & --http-addr is not set
# HTTPHost is "localhost" or "127.0.0.1" == only set --http
# HTTPHost is other IP (ex : 192.168.1.1) = set 2 flags --http & --http-addr
WSHost = "localhost" # flags --ws-addr & --ws . same option HTTPHost
WSPort = 8546 # flag --ws-port
WSModules = ["eth","ssh"] #flag --ws-api
HTTPModules = ["personal","db","eth","net","web3","txpool","miner"] # flag --rpcapi
HTTPModules = ["personal","db","eth","net","web3","txpool","miner"] # flag --http-api
KeyStoreDir = "" # flag --keystore
UserIdent = "" # flag --identity

View file

@ -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 <http://www.gnu.org/licenses/>.
// 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)
}
}
}

View file

@ -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")
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)")
app *cli.App
)
func main() {
// Parse and ensure all needed inputs are specified
flag.Parse()
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",
}
)
if *abiFlag == "" && *solFlag == "" {
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
}
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)
}
}

View file

@ -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: "[ <keyfile> ]",
@ -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.

View file

@ -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: "<keyfile>",
@ -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()

View file

@ -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",
}

View file

@ -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: "<keyfile> <message>",
@ -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: "<address> <signature> <message>",
@ -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
}

View file

@ -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

View file

@ -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")

View file

@ -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)
}

View file

@ -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 (
gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
app = flags.NewApp(gitCommit, "the evm command line interface")
)
var (
app = utils.NewApp(gitCommit, "the evm command line interface")
DebugFlag = cli.BoolFlag{
Name: "debug",
Usage: "output full trace logs",
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",
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",
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",
StatDumpFlag = &cli.BoolFlag{
Name: "statdump",
Usage: "displays stack and heap memory information",
Category: flags.VMCategory,
}
CodeFlag = cli.StringFlag{
Name: "code",
Usage: "EVM code",
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 ",
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,
GasFlag = &cli.Uint64Flag{
Name: "gas",
Usage: "gas limit for the evm",
Value: 10000000000,
Category: flags.VMCategory,
}
PriceFlag = utils.BigFlag{
Name: "price",
Usage: "price set for the evm",
Value: new(big.Int),
PriceFlag = &flags.BigFlag{
Name: "price",
Usage: "price set for the evm",
Value: new(big.Int),
Category: flags.VMCategory,
}
ValueFlag = utils.BigFlag{
Name: "value",
Usage: "value set for the evm",
Value: new(big.Int),
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",
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",
InputFlag = &cli.StringFlag{
Name: "input",
Usage: "input for the EVM",
Category: flags.VMCategory,
}
VerbosityFlag = cli.IntFlag{
Name: "verbosity",
Usage: "sets the verbosity level",
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",
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",
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)",
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",
SenderFlag = &cli.StringFlag{
Name: "sender",
Usage: "The transaction origin",
Category: flags.VMCategory,
}
ReceiverFlag = cli.StringFlag{
Name: "receiver",
Usage: "The transaction receiver (execution context)",
ReceiverFlag = &cli.StringFlag{
Name: "receiver",
Usage: "The transaction receiver (execution context)",
Category: flags.VMCategory,
}
DisableMemoryFlag = cli.BoolFlag{
Name: "nomemory",
Usage: "disable memory output",
DisableMemoryFlag = &cli.BoolFlag{
Name: "nomemory",
Value: true,
Usage: "disable memory output",
Category: flags.VMCategory,
}
DisableStackFlag = cli.BoolFlag{
Name: "nostack",
Usage: "disable stack output",
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,

View file

@ -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

View file

@ -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())

View file

@ -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 {

View file

@ -42,7 +42,7 @@ ADD genesis.json /genesis.json
RUN \
echo 'XDC --cache 512 init /genesis.json' > XDC.sh && \{{if .Unlock}}
echo 'mkdir -p /root/.ethereum/keystore/ && cp /signer.json /root/.ethereum/keystore/' >> XDC.sh && \{{end}}
echo $'XDC --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .Bootnodes}}--bootnodes {{.Bootnodes}}{{end}} {{if .Etherbase}}--etherbase {{.Etherbase}} --mine --minerthreads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --targetgaslimit {{.GasTarget}} --gasprice {{.GasPrice}}' >> XDC.sh
echo $'XDC --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .Bootnodes}}--bootnodes {{.Bootnodes}}{{end}} {{if .Etherbase}}--miner-etherbase {{.Etherbase}} --mine --miner-threads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --miner-gaslimit {{.GasTarget}} --miner-gasprice {{.GasPrice}}' >> XDC.sh
ENTRYPOINT ["/bin/sh", "XDC.sh"]
`
@ -92,7 +92,7 @@ func deployNode(client *sshClient, network string, bootnodes []string, config *n
lightFlag := ""
if config.peersLight > 0 {
lightFlag = fmt.Sprintf("--lightpeers=%d --lightserv=50", config.peersLight)
lightFlag = fmt.Sprintf("--light-peers=%d --light-serv=50", config.peersLight)
}
dockerfile := new(bytes.Buffer)
template.Must(template.New("").Parse(nodeDockerfile)).Execute(dockerfile, map[string]interface{}{

View file

@ -37,7 +37,7 @@ ADD genesis.json /genesis.json
RUN \
echo 'node server.js &' > wallet.sh && \
echo 'XDC --cache 512 init /genesis.json' >> wallet.sh && \
echo $'XDC --networkid {{.NetworkID}} --port {{.NodePort}} --bootnodes {{.Bootnodes}} --ethstats \'{{.Ethstats}}\' --cache=512 --rpc --rpcaddr=0.0.0.0 --rpccorsdomain "*" --rpcvhosts "*"' >> wallet.sh
echo $'XDC --networkid {{.NetworkID}} --port {{.NodePort}} --bootnodes {{.Bootnodes}} --ethstats \'{{.Ethstats}}\' --cache=512 --http --http-addr=0.0.0.0 --http-corsdomain "*" --http-vhosts "*"' >> wallet.sh
RUN \
sed -i 's/PuppethNetworkID/{{.NetworkID}}/g' dist/js/etherwallet-master.js && \

View file

@ -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",

View file

@ -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 <http://www.gnu.org/licenses/>.
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 ""
}

View file

@ -1,41 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package utils
import (
"os"
"os/user"
"testing"
)
func TestPathExpansion(t *testing.T) {
user, _ := user.Current()
tests := map[string]string{
"/home/someuser/tmp": "/home/someuser/tmp",
"~/tmp": user.HomeDir + "/tmp",
"~thisOtherUser/b/": "~thisOtherUser/b",
"$DDDXXX/a/b": "/tmp/a/b",
"/a/b/": "/a/b",
}
os.Setenv("DDDXXX", "/tmp")
for test, expected := range tests {
got := expandPath(test)
if got != expected {
t.Errorf("test %s, got %s, expected %s\n", test, got, expected)
}
}
}

File diff suppressed because it is too large Load diff

84
cmd/utils/flags_legacy.go Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
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
}

View file

@ -56,7 +56,7 @@ if [[ ! -z $NETWORK_ID ]]; then
;;
89 )
genesisPath="testnet.json"
params="$params --apothem --gcmode archive --rpcapi db,eth,net,web3,debug,XDPoS"
params="$params --apothem --gcmode archive --http-api db,eth,net,web3,debug,XDPoS"
;;
90 )
genesisPath="devnet.json"
@ -158,7 +158,7 @@ fi
# debug mode
if [[ ! -z $DEBUG_MODE ]]; then
params="$params --gcmode archive --rpcapi db,eth,net,web3,debug,XDPoS"
params="$params --gcmode archive --http-api db,eth,net,web3,debug,XDPoS"
fi
# maxpeers
@ -179,18 +179,18 @@ exec XDC $params \
--maxpeers $MAXPEERS \
--password ./password \
--port 30303 \
--txpool.globalqueue 5000 \
--txpool.globalslots 5000 \
--rpc \
--rpccorsdomain "*" \
--rpcaddr 0.0.0.0 \
--rpcport 8545 \
--rpcvhosts "*" \
--txpool-globalqueue 5000 \
--txpool-globalslots 5000 \
--http \
--http-corsdomain "*" \
--http-addr 0.0.0.0 \
--http-port 8545 \
--http-vhosts "*" \
--ws \
--wsaddr 0.0.0.0 \
--wsport 8546 \
--wsorigins "*" \
--ws-addr 0.0.0.0 \
--ws-port 8546 \
--ws-origins "*" \
--mine \
--gasprice "250000000" \
--targetgaslimit "84000000" \
--miner-gaslimit "84000000" \
"$@"

6
go.mod
View file

@ -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

12
go.sum
View file

@ -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=

View file

@ -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.

View file

@ -26,105 +26,132 @@ 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 <pattern>=<level> (e.g. eth/*=5,p2p=4)",
Value: "",
Name: "log-vmodule",
Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)",
Value: "",
Category: flags.LoggingCategory,
}
vmoduleFlag = cli.StringFlag{
Name: "vmodule",
Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)",
Value: "",
vmoduleFlag = &cli.StringFlag{
Name: "vmodule",
Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (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",
Name: "log-compress",
Usage: "Compress the log files",
Value: false,
Category: flags.LoggingCategory,
}
pprofFlag = cli.BoolFlag{
Name: "pprof",
Usage: "Enable the pprof HTTP server",
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,
pprofPortFlag = &cli.IntFlag{
Name: "pprof-port",
Aliases: []string{"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",
pprofAddrFlag = &cli.StringFlag{
Name: "pprof-addr",
Aliases: []string{"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,
memprofilerateFlag = &cli.IntFlag{
Name: "pprof-memprofilerate",
Aliases: []string{"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",
blockprofilerateFlag = &cli.IntFlag{
Name: "pprof-blockprofilerate",
Aliases: []string{"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",
cpuprofileFlag = &cli.StringFlag{
Name: "pprof-cpuprofile",
Aliases: []string{"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",
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",
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",
debugDataDirFlag = &cli.StringFlag{
Name: "debugdatadir",
Usage: "Debug Data directory for profiling output",
Category: flags.LoggingCategory,
}
)
@ -178,11 +205,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 +232,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 +250,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 +271,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 +292,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 {

View file

@ -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 <http://www.gnu.org/licenses/>.
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
}

267
internal/flags/flags.go Normal file
View file

@ -0,0 +1,267 @@
// 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 <http://www.gnu.org/licenses/>.
package flags
import (
"errors"
"flag"
"fmt"
"math/big"
"os"
"os/user"
"path/filepath"
"strings"
"syscall"
"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
EnvVars []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 {
for _, envVar := range f.EnvVars {
envVar = strings.TrimSpace(envVar)
if value, found := syscall.Getenv(envVar); found {
f.Value.Set(value)
f.HasBeenSet = true
break
}
}
eachName(f, func(name string) {
set.Var(&f.Value, 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 f.EnvVars }
func (f *DirectoryFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
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
defaultValue *big.Int
Aliases []string
EnvVars []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 {
// Set default value so that environment wont be able to overwrite it
if f.Value != nil {
f.defaultValue = new(big.Int).Set(f.Value)
}
for _, envVar := range f.EnvVars {
envVar = strings.TrimSpace(envVar)
if value, found := syscall.Getenv(envVar); found {
if _, ok := f.Value.SetString(value, 10); !ok {
return fmt.Errorf("could not parse %q from environment variable %q for flag %s", value, envVar, f.Name)
}
f.HasBeenSet = true
break
}
}
eachName(f, func(name string) {
f.Value = new(big.Int)
set.Var((*bigValue)(f.Value), 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 f.EnvVars }
func (f *BigFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.defaultValue.String()
}
// 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 {
// Named pipes are not file paths on windows, ignore
if strings.HasPrefix(p, `\\.\pipe`) {
return p
}
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
if home := HomeDir(); home != "" {
p = home + p[1:]
}
}
return filepath.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)
}
}

View file

@ -0,0 +1,61 @@
// 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 <http://www.gnu.org/licenses/>.
package flags
import (
"os"
"os/user"
"runtime"
"testing"
)
func TestPathExpansion(t *testing.T) {
user, _ := user.Current()
var tests map[string]string
if runtime.GOOS == "windows" {
tests = map[string]string{
`/home/someuser/tmp`: `\home\someuser\tmp`,
`~/tmp`: user.HomeDir + `\tmp`,
`~thisOtherUser/b/`: `~thisOtherUser\b`,
`$DDDXXX/a/b`: `\tmp\a\b`,
`/a/b/`: `\a\b`,
`C:\Documents\Newsletters\`: `C:\Documents\Newsletters`,
`C:\`: `C:\`,
`\\.\pipe\\pipe\geth621383`: `\\.\pipe\\pipe\geth621383`,
}
} else {
tests = map[string]string{
`/home/someuser/tmp`: `/home/someuser/tmp`,
`~/tmp`: user.HomeDir + `/tmp`,
`~thisOtherUser/b/`: `~thisOtherUser/b`,
`$DDDXXX/a/b`: `/tmp/a/b`,
`/a/b/`: `/a/b`,
`C:\Documents\Newsletters\`: `C:\Documents\Newsletters\`,
`C:\`: `C:\`,
`\\.\pipe\\pipe\geth621383`: `\\.\pipe\\pipe\geth621383`,
}
}
os.Setenv(`DDDXXX`, `/tmp`)
for test, expected := range tests {
got := expandPath(test)
if got != expected {
t.Errorf(`test %s, got %s, expected %s\n`, test, got, expected)
}
}
}

296
internal/flags/helpers.go Normal file
View file

@ -0,0 +1,296 @@
// 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 <http://www.gnu.org/licenses/>.
package flags
import (
"fmt"
"os"
"regexp"
"sort"
"strings"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/params"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
)
// usecolor defines whether the CLI help should use colored output or normal dumb
// colorless terminal formatting.
var usecolor = (isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())) && os.Getenv("TERM") != "dumb"
// 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) {
if cmd.Action == nil {
return
}
action := cmd.Action
cmd.Action = func(ctx *cli.Context) error {
doMigrateFlags(ctx)
return action(ctx)
}
})
}
func doMigrateFlags(ctx *cli.Context) {
// Figure out if there are any aliases of commands. If there are, we want
// to ignore them when iterating over the flags.
aliases := make(map[string]bool)
for _, fl := range ctx.Command.Flags {
for _, alias := range fl.Names()[1:] {
aliases[alias] = true
}
}
for _, name := range ctx.FlagNames() {
for _, parent := range ctx.Lineage()[1:] {
if parent.IsSet(name) {
// When iterating across the lineage, we will be served both
// the 'canon' and alias formats of all commmands. In most cases,
// it's fine to set it in the ctx multiple times (one for each
// name), however, the Slice-flags are not fine.
// The slice-flags accumulate, so if we set it once as
// "foo" and once as alias "F", then both will be present in the slice.
if _, isAlias := aliases[name]; isAlias {
continue
}
// If it is a string-slice, we need to set it as
// "alfa, beta, gamma" instead of "[alfa beta gamma]", in order
// for the backing StringSlice to parse it properly.
if result := parent.StringSlice(name); len(result) > 0 {
ctx.Set(name, strings.Join(result, ","))
} else {
ctx.Set(name, parent.String(name))
}
break
}
}
}
}
func init() {
if usecolor {
// Annotate all help categories with colors
cli.AppHelpTemplate = regexp.MustCompile("[A-Z ]+:").ReplaceAllString(cli.AppHelpTemplate, "\u001B[33m$0\u001B[0m")
// Annotate flag categories with colors (private template, so need to
// copy-paste the entire thing here...)
cli.AppHelpTemplate = strings.ReplaceAll(cli.AppHelpTemplate, "{{template \"visibleFlagCategoryTemplate\" .}}", "{{range .VisibleFlagCategories}}\n {{if .Name}}\u001B[33m{{.Name}}\u001B[0m\n\n {{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}}\n{{else}}{{$e}}\n {{end}}{{end}}{{end}}")
}
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 := cli.FlagNamePrefixer(df.Names(), placeholder)
defaultValueString := ""
if s := df.GetDefaultText(); s != "" {
defaultValueString = " (default: " + s + ")"
}
envHint := strings.TrimSpace(cli.FlagEnvHinter(df.GetEnvVars(), ""))
if envHint != "" {
envHint = " (" + envHint[1:len(envHint)-1] + ")"
}
usage := strings.TrimSpace(df.GetUsage())
usage = wordWrap(usage, 80)
usage = indent(usage, 10)
if usecolor {
return fmt.Sprintf("\n \u001B[32m%-35s%-35s\u001B[0m%s\n%s", namesText, defaultValueString, envHint, usage)
} else {
return fmt.Sprintf("\n %-35s%-35s%s\n%s", namesText, defaultValueString, envHint, usage)
}
}
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()
}
// AutoEnvVars extends all the specific CLI flags with automatically generated
// env vars by capitalizing the flag, replacing . with _ and prefixing it with
// the specified string.
//
// Note, the prefix should *not* contain the separator underscore, that will be
// added automatically.
func AutoEnvVars(flags []cli.Flag, prefix string) {
for _, flag := range flags {
envvar := strings.ToUpper(prefix + "_" + strings.ReplaceAll(strings.ReplaceAll(flag.Names()[0], ".", "_"), "-", "_"))
switch flag := flag.(type) {
case *cli.StringFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.StringSliceFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.BoolFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.IntFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.Int64Flag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.Uint64Flag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.Float64Flag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.DurationFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.PathFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *BigFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *DirectoryFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
}
}
}
// CheckEnvVars iterates over all the environment variables and checks if any of
// them look like a CLI flag but is not consumed. This can be used to detect old
// or mistyped names.
func CheckEnvVars(ctx *cli.Context, flags []cli.Flag, prefix string) {
known := make(map[string]string)
for _, flag := range flags {
docflag, ok := flag.(cli.DocGenerationFlag)
if !ok {
continue
}
for _, envvar := range docflag.GetEnvVars() {
known[envvar] = flag.Names()[0]
}
}
keyvals := os.Environ()
sort.Strings(keyvals)
for _, keyval := range keyvals {
key := strings.Split(keyval, "=")[0]
if !strings.HasPrefix(key, prefix) {
continue
}
if flag, ok := known[key]; ok {
if ctx.Count(flag) > 0 {
log.Info("Config environment variable found", "envvar", key, "shadowedby", "--"+flag)
} else {
log.Info("Config environment variable found", "envvar", key)
}
} else {
log.Warn("Unknown config environment variable", "envvar", key)
}
}
}