mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Merge pull request #741 from gzliudan/cli-v2
cmd: migrate to urfave/cli/v2
This commit is contained in:
commit
4278930885
45 changed files with 2436 additions and 1976 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
20
cmd/XDC/testdata/config.toml
vendored
20
cmd/XDC/testdata/config.toml
vendored
|
|
@ -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
|
||||
|
||||
|
|
|
|||
329
cmd/XDC/usage.go
329
cmd/XDC/usage.go
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
157
cmd/evm/main.go
157
cmd/evm/main.go
|
|
@ -22,101 +22,126 @@ import (
|
|||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
|
||||
var (
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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{}{
|
||||
|
|
|
|||
|
|
@ -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 && \
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
1595
cmd/utils/flags.go
1595
cmd/utils/flags.go
File diff suppressed because it is too large
Load diff
84
cmd/utils/flags_legacy.go
Normal file
84
cmd/utils/flags_legacy.go
Normal 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
|
||||
}
|
||||
|
|
@ -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
6
go.mod
|
|
@ -41,7 +41,6 @@ require (
|
|||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
|
||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772
|
||||
gopkg.in/urfave/cli.v1 v1.20.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
@ -50,13 +49,14 @@ require (
|
|||
github.com/kylelemons/godebug v1.1.0
|
||||
github.com/mattn/go-isatty v0.0.17
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
|
||||
github.com/urfave/cli/v2 v2.27.5
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
|
|
@ -69,7 +69,9 @@ require (
|
|||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
golang.org/x/mod v0.13.0 // indirect
|
||||
golang.org/x/term v0.14.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
|
|
|
|||
12
go.sum
12
go.sum
|
|
@ -13,6 +13,8 @@ github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW
|
|||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
|
@ -132,6 +134,8 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV
|
|||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
|
||||
|
|
@ -144,12 +148,14 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
|
|||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -215,8 +221,6 @@ gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 h1:hhsSf/5z74
|
|||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
45
internal/flags/categories.go
Normal file
45
internal/flags/categories.go
Normal 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
267
internal/flags/flags.go
Normal 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)
|
||||
}
|
||||
}
|
||||
61
internal/flags/flags_test.go
Normal file
61
internal/flags/flags_test.go
Normal 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
296
internal/flags/helpers.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue