cmd: migrate to urfave/cli/v2 (#24751)
This change updates our urfave/cli dependency to the v2 branch of the library. There are some Go API changes in cli v2: - Flag values can now be accessed using the methods ctx.Bool, ctx.Int, ctx.String, ... regardless of whether the flag is 'local' or 'global'. - v2 has built-in support for flag categories. Our home-grown category system is removed and the categories of flags are assigned as part of the flag definition. For users, there is only one observable difference with cli v2: flags must now strictly appear before regular arguments. For example, the following command is now invalid: geth account import mykey.json --password file.txt Instead, the command must be invoked as follows: geth account import --password file.txt mykey.json
This commit is contained in:
parent
119f955686
commit
52ed3570c4
|
@ -224,6 +224,9 @@ func doInstall(cmdline []string) {
|
||||||
gobuild.Args = append(gobuild.Args, "-p", "1")
|
gobuild.Args = append(gobuild.Args, "-p", "1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable CLI markdown doc generation in release builds.
|
||||||
|
gobuild.Args = append(gobuild.Args, "-tags", "urfave_cli_no_docs")
|
||||||
|
|
||||||
// We use -trimpath to avoid leaking local paths into the built executables.
|
// We use -trimpath to avoid leaking local paths into the built executables.
|
||||||
gobuild.Args = append(gobuild.Args, "-trimpath")
|
gobuild.Args = append(gobuild.Args, "-trimpath")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
: ${PROG:=$(basename ${BASH_SOURCE})}
|
||||||
|
|
||||||
|
_cli_bash_autocomplete() {
|
||||||
|
if [[ "${COMP_WORDS[0]}" != "source" ]]; then
|
||||||
|
local cur opts base
|
||||||
|
COMPREPLY=()
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
if [[ "$cur" == "-"* ]]; then
|
||||||
|
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion )
|
||||||
|
else
|
||||||
|
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
||||||
|
fi
|
||||||
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete $PROG
|
||||||
|
unset PROG
|
|
@ -0,0 +1,20 @@
|
||||||
|
#compdef $PROG
|
||||||
|
|
||||||
|
_cli_zsh_autocomplete() {
|
||||||
|
local -a opts
|
||||||
|
local cur
|
||||||
|
cur=${words[-1]}
|
||||||
|
if [[ "$cur" == "-"* ]]; then
|
||||||
|
opts=("${(@f)$(${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}")
|
||||||
|
else
|
||||||
|
opts=("${(@f)$(${words[@]:0:#words[@]-1} --generate-bash-completion)}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${opts[1]}" != "" ]]; then
|
||||||
|
_describe 'values' opts
|
||||||
|
else
|
||||||
|
_files
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
compdef _cli_zsh_autocomplete $PROG
|
|
@ -30,7 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -39,42 +39,44 @@ var (
|
||||||
gitDate = ""
|
gitDate = ""
|
||||||
|
|
||||||
app *cli.App
|
app *cli.App
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
// Flags needed by abigen
|
// Flags needed by abigen
|
||||||
abiFlag = cli.StringFlag{
|
abiFlag = &cli.StringFlag{
|
||||||
Name: "abi",
|
Name: "abi",
|
||||||
Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN",
|
Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN",
|
||||||
}
|
}
|
||||||
binFlag = cli.StringFlag{
|
binFlag = &cli.StringFlag{
|
||||||
Name: "bin",
|
Name: "bin",
|
||||||
Usage: "Path to the Ethereum contract bytecode (generate deploy method)",
|
Usage: "Path to the Ethereum contract bytecode (generate deploy method)",
|
||||||
}
|
}
|
||||||
typeFlag = cli.StringFlag{
|
typeFlag = &cli.StringFlag{
|
||||||
Name: "type",
|
Name: "type",
|
||||||
Usage: "Struct name for the binding (default = package name)",
|
Usage: "Struct name for the binding (default = package name)",
|
||||||
}
|
}
|
||||||
jsonFlag = cli.StringFlag{
|
jsonFlag = &cli.StringFlag{
|
||||||
Name: "combined-json",
|
Name: "combined-json",
|
||||||
Usage: "Path to the combined-json file generated by compiler, - for STDIN",
|
Usage: "Path to the combined-json file generated by compiler, - for STDIN",
|
||||||
}
|
}
|
||||||
excFlag = cli.StringFlag{
|
excFlag = &cli.StringFlag{
|
||||||
Name: "exc",
|
Name: "exc",
|
||||||
Usage: "Comma separated types to exclude from binding",
|
Usage: "Comma separated types to exclude from binding",
|
||||||
}
|
}
|
||||||
pkgFlag = cli.StringFlag{
|
pkgFlag = &cli.StringFlag{
|
||||||
Name: "pkg",
|
Name: "pkg",
|
||||||
Usage: "Package name to generate the binding into",
|
Usage: "Package name to generate the binding into",
|
||||||
}
|
}
|
||||||
outFlag = cli.StringFlag{
|
outFlag = &cli.StringFlag{
|
||||||
Name: "out",
|
Name: "out",
|
||||||
Usage: "Output file for the generated binding (default = stdout)",
|
Usage: "Output file for the generated binding (default = stdout)",
|
||||||
}
|
}
|
||||||
langFlag = cli.StringFlag{
|
langFlag = &cli.StringFlag{
|
||||||
Name: "lang",
|
Name: "lang",
|
||||||
Usage: "Destination language for the bindings (go, java, objc)",
|
Usage: "Destination language for the bindings (go, java, objc)",
|
||||||
Value: "go",
|
Value: "go",
|
||||||
}
|
}
|
||||||
aliasFlag = cli.StringFlag{
|
aliasFlag = &cli.StringFlag{
|
||||||
Name: "alias",
|
Name: "alias",
|
||||||
Usage: "Comma separated aliases for function and event renaming, e.g. original1=alias1, original2=alias2",
|
Usage: "Comma separated aliases for function and event renaming, e.g. original1=alias1, original2=alias2",
|
||||||
}
|
}
|
||||||
|
@ -82,6 +84,7 @@ var (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app = flags.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
|
app = flags.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
|
||||||
|
app.Name = "abigen"
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
abiFlag,
|
abiFlag,
|
||||||
binFlag,
|
binFlag,
|
||||||
|
@ -93,17 +96,17 @@ func init() {
|
||||||
langFlag,
|
langFlag,
|
||||||
aliasFlag,
|
aliasFlag,
|
||||||
}
|
}
|
||||||
app.Action = utils.MigrateFlags(abigen)
|
app.Action = abigen
|
||||||
cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func abigen(c *cli.Context) error {
|
func abigen(c *cli.Context) error {
|
||||||
utils.CheckExclusive(c, abiFlag, jsonFlag) // Only one source can be selected.
|
utils.CheckExclusive(c, abiFlag, jsonFlag) // Only one source can be selected.
|
||||||
if c.GlobalString(pkgFlag.Name) == "" {
|
|
||||||
|
if c.String(pkgFlag.Name) == "" {
|
||||||
utils.Fatalf("No destination package specified (--pkg)")
|
utils.Fatalf("No destination package specified (--pkg)")
|
||||||
}
|
}
|
||||||
var lang bind.Lang
|
var lang bind.Lang
|
||||||
switch c.GlobalString(langFlag.Name) {
|
switch c.String(langFlag.Name) {
|
||||||
case "go":
|
case "go":
|
||||||
lang = bind.LangGo
|
lang = bind.LangGo
|
||||||
case "java":
|
case "java":
|
||||||
|
@ -112,7 +115,7 @@ func abigen(c *cli.Context) error {
|
||||||
lang = bind.LangObjC
|
lang = bind.LangObjC
|
||||||
utils.Fatalf("Objc binding generation is uncompleted")
|
utils.Fatalf("Objc binding generation is uncompleted")
|
||||||
default:
|
default:
|
||||||
utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.GlobalString(langFlag.Name))
|
utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.String(langFlag.Name))
|
||||||
}
|
}
|
||||||
// If the entire solidity code was specified, build and bind based on that
|
// If the entire solidity code was specified, build and bind based on that
|
||||||
var (
|
var (
|
||||||
|
@ -123,13 +126,13 @@ func abigen(c *cli.Context) error {
|
||||||
libs = make(map[string]string)
|
libs = make(map[string]string)
|
||||||
aliases = make(map[string]string)
|
aliases = make(map[string]string)
|
||||||
)
|
)
|
||||||
if c.GlobalString(abiFlag.Name) != "" {
|
if c.String(abiFlag.Name) != "" {
|
||||||
// Load up the ABI, optional bytecode and type name from the parameters
|
// Load up the ABI, optional bytecode and type name from the parameters
|
||||||
var (
|
var (
|
||||||
abi []byte
|
abi []byte
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
input := c.GlobalString(abiFlag.Name)
|
input := c.String(abiFlag.Name)
|
||||||
if input == "-" {
|
if input == "-" {
|
||||||
abi, err = io.ReadAll(os.Stdin)
|
abi, err = io.ReadAll(os.Stdin)
|
||||||
} else {
|
} else {
|
||||||
|
@ -141,7 +144,7 @@ func abigen(c *cli.Context) error {
|
||||||
abis = append(abis, string(abi))
|
abis = append(abis, string(abi))
|
||||||
|
|
||||||
var bin []byte
|
var bin []byte
|
||||||
if binFile := c.GlobalString(binFlag.Name); binFile != "" {
|
if binFile := c.String(binFlag.Name); binFile != "" {
|
||||||
if bin, err = os.ReadFile(binFile); err != nil {
|
if bin, err = os.ReadFile(binFile); err != nil {
|
||||||
utils.Fatalf("Failed to read input bytecode: %v", err)
|
utils.Fatalf("Failed to read input bytecode: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -151,22 +154,22 @@ func abigen(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
bins = append(bins, string(bin))
|
bins = append(bins, string(bin))
|
||||||
|
|
||||||
kind := c.GlobalString(typeFlag.Name)
|
kind := c.String(typeFlag.Name)
|
||||||
if kind == "" {
|
if kind == "" {
|
||||||
kind = c.GlobalString(pkgFlag.Name)
|
kind = c.String(pkgFlag.Name)
|
||||||
}
|
}
|
||||||
types = append(types, kind)
|
types = append(types, kind)
|
||||||
} else {
|
} else {
|
||||||
// Generate the list of types to exclude from binding
|
// Generate the list of types to exclude from binding
|
||||||
exclude := make(map[string]bool)
|
exclude := make(map[string]bool)
|
||||||
for _, kind := range strings.Split(c.GlobalString(excFlag.Name), ",") {
|
for _, kind := range strings.Split(c.String(excFlag.Name), ",") {
|
||||||
exclude[strings.ToLower(kind)] = true
|
exclude[strings.ToLower(kind)] = true
|
||||||
}
|
}
|
||||||
var contracts map[string]*compiler.Contract
|
var contracts map[string]*compiler.Contract
|
||||||
|
|
||||||
if c.GlobalIsSet(jsonFlag.Name) {
|
if c.IsSet(jsonFlag.Name) {
|
||||||
var (
|
var (
|
||||||
input = c.GlobalString(jsonFlag.Name)
|
input = c.String(jsonFlag.Name)
|
||||||
jsonOutput []byte
|
jsonOutput []byte
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
@ -207,28 +210,28 @@ func abigen(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Extract all aliases from the flags
|
// Extract all aliases from the flags
|
||||||
if c.GlobalIsSet(aliasFlag.Name) {
|
if c.IsSet(aliasFlag.Name) {
|
||||||
// We support multi-versions for aliasing
|
// We support multi-versions for aliasing
|
||||||
// e.g.
|
// e.g.
|
||||||
// foo=bar,foo2=bar2
|
// foo=bar,foo2=bar2
|
||||||
// foo:bar,foo2:bar2
|
// foo:bar,foo2:bar2
|
||||||
re := regexp.MustCompile(`(?:(\w+)[:=](\w+))`)
|
re := regexp.MustCompile(`(?:(\w+)[:=](\w+))`)
|
||||||
submatches := re.FindAllStringSubmatch(c.GlobalString(aliasFlag.Name), -1)
|
submatches := re.FindAllStringSubmatch(c.String(aliasFlag.Name), -1)
|
||||||
for _, match := range submatches {
|
for _, match := range submatches {
|
||||||
aliases[match[1]] = match[2]
|
aliases[match[1]] = match[2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Generate the contract binding
|
// Generate the contract binding
|
||||||
code, err := bind.Bind(types, abis, bins, sigs, c.GlobalString(pkgFlag.Name), lang, libs, aliases)
|
code, err := bind.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), lang, libs, aliases)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to generate ABI binding: %v", err)
|
utils.Fatalf("Failed to generate ABI binding: %v", err)
|
||||||
}
|
}
|
||||||
// Either flush it out to a file or display on the standard output
|
// Either flush it out to a file or display on the standard output
|
||||||
if !c.GlobalIsSet(outFlag.Name) {
|
if !c.IsSet(outFlag.Name) {
|
||||||
fmt.Printf("%s\n", code)
|
fmt.Printf("%s\n", code)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := os.WriteFile(c.GlobalString(outFlag.Name), []byte(code), 0600); err != nil {
|
if err := os.WriteFile(c.String(outFlag.Name), []byte(code), 0600); err != nil {
|
||||||
utils.Fatalf("Failed to write ABI binding: %v", err)
|
utils.Fatalf("Failed to write ABI binding: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -28,12 +28,12 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newClient creates a client with specified remote URL.
|
// newClient creates a client with specified remote URL.
|
||||||
func newClient(ctx *cli.Context) *ethclient.Client {
|
func newClient(ctx *cli.Context) *ethclient.Client {
|
||||||
client, err := ethclient.Dial(ctx.GlobalString(nodeURLFlag.Name))
|
client, err := ethclient.Dial(ctx.String(nodeURLFlag.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to connect to Ethereum node: %v", err)
|
utils.Fatalf("Failed to connect to Ethereum node: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ func getContractAddr(client *rpc.Client) common.Address {
|
||||||
func getCheckpoint(ctx *cli.Context, client *rpc.Client) *params.TrustedCheckpoint {
|
func getCheckpoint(ctx *cli.Context, client *rpc.Client) *params.TrustedCheckpoint {
|
||||||
var checkpoint *params.TrustedCheckpoint
|
var checkpoint *params.TrustedCheckpoint
|
||||||
|
|
||||||
if ctx.GlobalIsSet(indexFlag.Name) {
|
if ctx.IsSet(indexFlag.Name) {
|
||||||
var result [3]string
|
var result [3]string
|
||||||
index := uint64(ctx.GlobalInt64(indexFlag.Name))
|
index := uint64(ctx.Int64(indexFlag.Name))
|
||||||
if err := client.Call(&result, "les_getCheckpoint", index); err != nil {
|
if err := client.Call(&result, "les_getCheckpoint", index); err != nil {
|
||||||
utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err)
|
utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,10 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var commandDeploy = cli.Command{
|
var commandDeploy = &cli.Command{
|
||||||
Name: "deploy",
|
Name: "deploy",
|
||||||
Usage: "Deploy a new checkpoint oracle contract",
|
Usage: "Deploy a new checkpoint oracle contract",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
|
@ -49,10 +49,10 @@ var commandDeploy = cli.Command{
|
||||||
signersFlag,
|
signersFlag,
|
||||||
thresholdFlag,
|
thresholdFlag,
|
||||||
},
|
},
|
||||||
Action: utils.MigrateFlags(deploy),
|
Action: deploy,
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandSign = cli.Command{
|
var commandSign = &cli.Command{
|
||||||
Name: "sign",
|
Name: "sign",
|
||||||
Usage: "Sign the checkpoint with the specified key",
|
Usage: "Sign the checkpoint with the specified key",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
|
@ -63,10 +63,10 @@ var commandSign = cli.Command{
|
||||||
hashFlag,
|
hashFlag,
|
||||||
oracleFlag,
|
oracleFlag,
|
||||||
},
|
},
|
||||||
Action: utils.MigrateFlags(sign),
|
Action: sign,
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandPublish = cli.Command{
|
var commandPublish = &cli.Command{
|
||||||
Name: "publish",
|
Name: "publish",
|
||||||
Usage: "Publish a checkpoint into the oracle",
|
Usage: "Publish a checkpoint into the oracle",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
|
@ -76,7 +76,7 @@ var commandPublish = cli.Command{
|
||||||
indexFlag,
|
indexFlag,
|
||||||
signaturesFlag,
|
signaturesFlag,
|
||||||
},
|
},
|
||||||
Action: utils.MigrateFlags(publish),
|
Action: publish,
|
||||||
}
|
}
|
||||||
|
|
||||||
// deploy deploys the checkpoint registrar contract.
|
// deploy deploys the checkpoint registrar contract.
|
||||||
|
@ -132,7 +132,7 @@ func sign(ctx *cli.Context) error {
|
||||||
node *rpc.Client
|
node *rpc.Client
|
||||||
oracle *checkpointoracle.CheckpointOracle
|
oracle *checkpointoracle.CheckpointOracle
|
||||||
)
|
)
|
||||||
if !ctx.GlobalIsSet(nodeURLFlag.Name) {
|
if !ctx.IsSet(nodeURLFlag.Name) {
|
||||||
// Offline mode signing
|
// Offline mode signing
|
||||||
offline = true
|
offline = true
|
||||||
if !ctx.IsSet(hashFlag.Name) {
|
if !ctx.IsSet(hashFlag.Name) {
|
||||||
|
@ -151,7 +151,7 @@ func sign(ctx *cli.Context) error {
|
||||||
address = common.HexToAddress(ctx.String(oracleFlag.Name))
|
address = common.HexToAddress(ctx.String(oracleFlag.Name))
|
||||||
} else {
|
} else {
|
||||||
// Interactive mode signing, retrieve the data from the remote node
|
// Interactive mode signing, retrieve the data from the remote node
|
||||||
node = newRPCClient(ctx.GlobalString(nodeURLFlag.Name))
|
node = newRPCClient(ctx.String(nodeURLFlag.Name))
|
||||||
|
|
||||||
checkpoint := getCheckpoint(ctx, node)
|
checkpoint := getCheckpoint(ctx, node)
|
||||||
chash, cindex, address = checkpoint.Hash(), checkpoint.SectionIndex, getContractAddr(node)
|
chash, cindex, address = checkpoint.Hash(), checkpoint.SectionIndex, getContractAddr(node)
|
||||||
|
@ -265,7 +265,7 @@ func publish(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
// Retrieve the checkpoint we want to sign to sort the signatures
|
// Retrieve the checkpoint we want to sign to sort the signatures
|
||||||
var (
|
var (
|
||||||
client = newRPCClient(ctx.GlobalString(nodeURLFlag.Name))
|
client = newRPCClient(ctx.String(nodeURLFlag.Name))
|
||||||
addr, oracle = newContract(client)
|
addr, oracle = newContract(client)
|
||||||
checkpoint = getCheckpoint(ctx, client)
|
checkpoint = getCheckpoint(ctx, client)
|
||||||
sighash = sighash(checkpoint.SectionIndex, addr, checkpoint.Hash())
|
sighash = sighash(checkpoint.SectionIndex, addr, checkpoint.Hash())
|
||||||
|
|
|
@ -25,20 +25,20 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Git SHA1 commit hash of the release (set via linker flags)
|
// Git SHA1 commit hash of the release (set via linker flags)
|
||||||
gitCommit = ""
|
gitCommit = ""
|
||||||
gitDate = ""
|
gitDate = ""
|
||||||
)
|
|
||||||
|
|
||||||
var app *cli.App
|
app *cli.App
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app = flags.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
|
app = flags.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
commandStatus,
|
commandStatus,
|
||||||
commandDeploy,
|
commandDeploy,
|
||||||
commandSign,
|
commandSign,
|
||||||
|
@ -48,46 +48,45 @@ func init() {
|
||||||
oracleFlag,
|
oracleFlag,
|
||||||
nodeURLFlag,
|
nodeURLFlag,
|
||||||
}
|
}
|
||||||
cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commonly used command line flags.
|
// Commonly used command line flags.
|
||||||
var (
|
var (
|
||||||
indexFlag = cli.Int64Flag{
|
indexFlag = &cli.Int64Flag{
|
||||||
Name: "index",
|
Name: "index",
|
||||||
Usage: "Checkpoint index (query latest from remote node if not specified)",
|
Usage: "Checkpoint index (query latest from remote node if not specified)",
|
||||||
}
|
}
|
||||||
hashFlag = cli.StringFlag{
|
hashFlag = &cli.StringFlag{
|
||||||
Name: "hash",
|
Name: "hash",
|
||||||
Usage: "Checkpoint hash (query latest from remote node if not specified)",
|
Usage: "Checkpoint hash (query latest from remote node if not specified)",
|
||||||
}
|
}
|
||||||
oracleFlag = cli.StringFlag{
|
oracleFlag = &cli.StringFlag{
|
||||||
Name: "oracle",
|
Name: "oracle",
|
||||||
Usage: "Checkpoint oracle address (query from remote node if not specified)",
|
Usage: "Checkpoint oracle address (query from remote node if not specified)",
|
||||||
}
|
}
|
||||||
thresholdFlag = cli.Int64Flag{
|
thresholdFlag = &cli.Int64Flag{
|
||||||
Name: "threshold",
|
Name: "threshold",
|
||||||
Usage: "Minimal number of signatures required to approve a checkpoint",
|
Usage: "Minimal number of signatures required to approve a checkpoint",
|
||||||
}
|
}
|
||||||
nodeURLFlag = cli.StringFlag{
|
nodeURLFlag = &cli.StringFlag{
|
||||||
Name: "rpc",
|
Name: "rpc",
|
||||||
Value: "http://localhost:8545",
|
Value: "http://localhost:8545",
|
||||||
Usage: "The rpc endpoint of a local or remote geth node",
|
Usage: "The rpc endpoint of a local or remote geth node",
|
||||||
}
|
}
|
||||||
clefURLFlag = cli.StringFlag{
|
clefURLFlag = &cli.StringFlag{
|
||||||
Name: "clef",
|
Name: "clef",
|
||||||
Value: "http://localhost:8550",
|
Value: "http://localhost:8550",
|
||||||
Usage: "The rpc endpoint of clef",
|
Usage: "The rpc endpoint of clef",
|
||||||
}
|
}
|
||||||
signerFlag = cli.StringFlag{
|
signerFlag = &cli.StringFlag{
|
||||||
Name: "signer",
|
Name: "signer",
|
||||||
Usage: "Signer address for clef signing",
|
Usage: "Signer address for clef signing",
|
||||||
}
|
}
|
||||||
signersFlag = cli.StringFlag{
|
signersFlag = &cli.StringFlag{
|
||||||
Name: "signers",
|
Name: "signers",
|
||||||
Usage: "Comma separated accounts of trusted checkpoint signers",
|
Usage: "Comma separated accounts of trusted checkpoint signers",
|
||||||
}
|
}
|
||||||
signaturesFlag = cli.StringFlag{
|
signaturesFlag = &cli.StringFlag{
|
||||||
Name: "signatures",
|
Name: "signatures",
|
||||||
Usage: "Comma separated checkpoint signatures to submit",
|
Usage: "Comma separated checkpoint signatures to submit",
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,24 +19,23 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var commandStatus = cli.Command{
|
var commandStatus = &cli.Command{
|
||||||
Name: "status",
|
Name: "status",
|
||||||
Usage: "Fetches the signers and checkpoint status of the oracle contract",
|
Usage: "Fetches the signers and checkpoint status of the oracle contract",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
nodeURLFlag,
|
nodeURLFlag,
|
||||||
},
|
},
|
||||||
Action: utils.MigrateFlags(status),
|
Action: status,
|
||||||
}
|
}
|
||||||
|
|
||||||
// status fetches the admin list of specified registrar contract.
|
// status fetches the admin list of specified registrar contract.
|
||||||
func status(ctx *cli.Context) error {
|
func status(ctx *cli.Context) error {
|
||||||
// Create a wrapper around the checkpoint oracle contract
|
// Create a wrapper around the checkpoint oracle contract
|
||||||
addr, oracle := newContract(newRPCClient(ctx.GlobalString(nodeURLFlag.Name)))
|
addr, oracle := newContract(newRPCClient(ctx.String(nodeURLFlag.Name)))
|
||||||
fmt.Printf("Oracle => %s\n", addr.Hex())
|
fmt.Printf("Oracle => %s\n", addr.Hex())
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
|
|
206
cmd/clef/main.go
206
cmd/clef/main.go
|
@ -30,7 +30,6 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/signer/storage"
|
"github.com/ethereum/go-ethereum/signer/storage"
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const legalWarning = `
|
const legalWarning = `
|
||||||
|
@ -73,70 +72,70 @@ PURPOSE. See the GNU General Public License for more details.
|
||||||
`
|
`
|
||||||
|
|
||||||
var (
|
var (
|
||||||
logLevelFlag = cli.IntFlag{
|
logLevelFlag = &cli.IntFlag{
|
||||||
Name: "loglevel",
|
Name: "loglevel",
|
||||||
Value: 4,
|
Value: 4,
|
||||||
Usage: "log level to emit to the screen",
|
Usage: "log level to emit to the screen",
|
||||||
}
|
}
|
||||||
advancedMode = cli.BoolFlag{
|
advancedMode = &cli.BoolFlag{
|
||||||
Name: "advanced",
|
Name: "advanced",
|
||||||
Usage: "If enabled, issues warnings instead of rejections for suspicious requests. Default off",
|
Usage: "If enabled, issues warnings instead of rejections for suspicious requests. Default off",
|
||||||
}
|
}
|
||||||
acceptFlag = cli.BoolFlag{
|
acceptFlag = &cli.BoolFlag{
|
||||||
Name: "suppress-bootwarn",
|
Name: "suppress-bootwarn",
|
||||||
Usage: "If set, does not show the warning during boot",
|
Usage: "If set, does not show the warning during boot",
|
||||||
}
|
}
|
||||||
keystoreFlag = cli.StringFlag{
|
keystoreFlag = &cli.StringFlag{
|
||||||
Name: "keystore",
|
Name: "keystore",
|
||||||
Value: filepath.Join(node.DefaultDataDir(), "keystore"),
|
Value: filepath.Join(node.DefaultDataDir(), "keystore"),
|
||||||
Usage: "Directory for the keystore",
|
Usage: "Directory for the keystore",
|
||||||
}
|
}
|
||||||
configdirFlag = cli.StringFlag{
|
configdirFlag = &cli.StringFlag{
|
||||||
Name: "configdir",
|
Name: "configdir",
|
||||||
Value: DefaultConfigDir(),
|
Value: DefaultConfigDir(),
|
||||||
Usage: "Directory for Clef configuration",
|
Usage: "Directory for Clef configuration",
|
||||||
}
|
}
|
||||||
chainIdFlag = cli.Int64Flag{
|
chainIdFlag = &cli.Int64Flag{
|
||||||
Name: "chainid",
|
Name: "chainid",
|
||||||
Value: params.MainnetChainConfig.ChainID.Int64(),
|
Value: params.MainnetChainConfig.ChainID.Int64(),
|
||||||
Usage: "Chain id to use for signing (1=mainnet, 3=Ropsten, 4=Rinkeby, 5=Goerli)",
|
Usage: "Chain id to use for signing (1=mainnet, 3=Ropsten, 4=Rinkeby, 5=Goerli)",
|
||||||
}
|
}
|
||||||
rpcPortFlag = cli.IntFlag{
|
rpcPortFlag = &cli.IntFlag{
|
||||||
Name: "http.port",
|
Name: "http.port",
|
||||||
Usage: "HTTP-RPC server listening port",
|
Usage: "HTTP-RPC server listening port",
|
||||||
Value: node.DefaultHTTPPort + 5,
|
Value: node.DefaultHTTPPort + 5,
|
||||||
|
Category: flags.APICategory,
|
||||||
}
|
}
|
||||||
signerSecretFlag = cli.StringFlag{
|
signerSecretFlag = &cli.StringFlag{
|
||||||
Name: "signersecret",
|
Name: "signersecret",
|
||||||
Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash",
|
Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash",
|
||||||
}
|
}
|
||||||
customDBFlag = cli.StringFlag{
|
customDBFlag = &cli.StringFlag{
|
||||||
Name: "4bytedb-custom",
|
Name: "4bytedb-custom",
|
||||||
Usage: "File used for writing new 4byte-identifiers submitted via API",
|
Usage: "File used for writing new 4byte-identifiers submitted via API",
|
||||||
Value: "./4byte-custom.json",
|
Value: "./4byte-custom.json",
|
||||||
}
|
}
|
||||||
auditLogFlag = cli.StringFlag{
|
auditLogFlag = &cli.StringFlag{
|
||||||
Name: "auditlog",
|
Name: "auditlog",
|
||||||
Usage: "File used to emit audit logs. Set to \"\" to disable",
|
Usage: "File used to emit audit logs. Set to \"\" to disable",
|
||||||
Value: "audit.log",
|
Value: "audit.log",
|
||||||
}
|
}
|
||||||
ruleFlag = cli.StringFlag{
|
ruleFlag = &cli.StringFlag{
|
||||||
Name: "rules",
|
Name: "rules",
|
||||||
Usage: "Path to the rule file to auto-authorize requests with",
|
Usage: "Path to the rule file to auto-authorize requests with",
|
||||||
}
|
}
|
||||||
stdiouiFlag = cli.BoolFlag{
|
stdiouiFlag = &cli.BoolFlag{
|
||||||
Name: "stdio-ui",
|
Name: "stdio-ui",
|
||||||
Usage: "Use STDIN/STDOUT as a channel for an external UI. " +
|
Usage: "Use STDIN/STDOUT as a channel for an external UI. " +
|
||||||
"This means that an STDIN/STDOUT is used for RPC-communication with a e.g. a graphical user " +
|
"This means that an STDIN/STDOUT is used for RPC-communication with a e.g. a graphical user " +
|
||||||
"interface, and can be used when Clef is started by an external process.",
|
"interface, and can be used when Clef is started by an external process.",
|
||||||
}
|
}
|
||||||
testFlag = cli.BoolFlag{
|
testFlag = &cli.BoolFlag{
|
||||||
Name: "stdio-ui-test",
|
Name: "stdio-ui-test",
|
||||||
Usage: "Mechanism to test interface between Clef and UI. Requires 'stdio-ui'.",
|
Usage: "Mechanism to test interface between Clef and UI. Requires 'stdio-ui'.",
|
||||||
}
|
}
|
||||||
app = cli.NewApp()
|
initCommand = &cli.Command{
|
||||||
initCommand = cli.Command{
|
Action: initializeSecrets,
|
||||||
Action: utils.MigrateFlags(initializeSecrets),
|
|
||||||
Name: "init",
|
Name: "init",
|
||||||
Usage: "Initialize the signer, generate secret storage",
|
Usage: "Initialize the signer, generate secret storage",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
|
@ -148,8 +147,8 @@ var (
|
||||||
The init command generates a master seed which Clef can use to store credentials and data needed for
|
The init command generates a master seed which Clef can use to store credentials and data needed for
|
||||||
the rule-engine to work.`,
|
the rule-engine to work.`,
|
||||||
}
|
}
|
||||||
attestCommand = cli.Command{
|
attestCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(attestFile),
|
Action: attestFile,
|
||||||
Name: "attest",
|
Name: "attest",
|
||||||
Usage: "Attest that a js-file is to be used",
|
Usage: "Attest that a js-file is to be used",
|
||||||
ArgsUsage: "<sha256sum>",
|
ArgsUsage: "<sha256sum>",
|
||||||
|
@ -165,8 +164,8 @@ incoming requests.
|
||||||
Whenever you make an edit to the rule file, you need to use attestation to tell
|
Whenever you make an edit to the rule file, you need to use attestation to tell
|
||||||
Clef that the file is 'safe' to execute.`,
|
Clef that the file is 'safe' to execute.`,
|
||||||
}
|
}
|
||||||
setCredentialCommand = cli.Command{
|
setCredentialCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(setCredential),
|
Action: setCredential,
|
||||||
Name: "setpw",
|
Name: "setpw",
|
||||||
Usage: "Store a credential for a keystore file",
|
Usage: "Store a credential for a keystore file",
|
||||||
ArgsUsage: "<address>",
|
ArgsUsage: "<address>",
|
||||||
|
@ -178,8 +177,8 @@ Clef that the file is 'safe' to execute.`,
|
||||||
Description: `
|
Description: `
|
||||||
The setpw command stores a password for a given address (keyfile).
|
The setpw command stores a password for a given address (keyfile).
|
||||||
`}
|
`}
|
||||||
delCredentialCommand = cli.Command{
|
delCredentialCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(removeCredential),
|
Action: removeCredential,
|
||||||
Name: "delpw",
|
Name: "delpw",
|
||||||
Usage: "Remove a credential for a keystore file",
|
Usage: "Remove a credential for a keystore file",
|
||||||
ArgsUsage: "<address>",
|
ArgsUsage: "<address>",
|
||||||
|
@ -191,8 +190,8 @@ The setpw command stores a password for a given address (keyfile).
|
||||||
Description: `
|
Description: `
|
||||||
The delpw command removes a password for a given address (keyfile).
|
The delpw command removes a password for a given address (keyfile).
|
||||||
`}
|
`}
|
||||||
newAccountCommand = cli.Command{
|
newAccountCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(newAccount),
|
Action: newAccount,
|
||||||
Name: "newaccount",
|
Name: "newaccount",
|
||||||
Usage: "Create a new account",
|
Usage: "Create a new account",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
|
@ -207,7 +206,7 @@ The newaccount command creates a new keystore-backed account. It is a convenienc
|
||||||
which can be used in lieu of an external UI.`,
|
which can be used in lieu of an external UI.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
gendocCommand = cli.Command{
|
gendocCommand = &cli.Command{
|
||||||
Action: GenDoc,
|
Action: GenDoc,
|
||||||
Name: "gendoc",
|
Name: "gendoc",
|
||||||
Usage: "Generate documentation about json-rpc format",
|
Usage: "Generate documentation about json-rpc format",
|
||||||
|
@ -216,39 +215,16 @@ The gendoc generates example structures of the json-rpc communication types.
|
||||||
`}
|
`}
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppHelpFlagGroups is the application flags, grouped by functionality.
|
var (
|
||||||
var AppHelpFlagGroups = []flags.FlagGroup{
|
// Git SHA1 commit hash of the release (set via linker flags)
|
||||||
{
|
gitCommit = ""
|
||||||
Name: "FLAGS",
|
gitDate = ""
|
||||||
Flags: []cli.Flag{
|
|
||||||
logLevelFlag,
|
app = flags.NewApp(gitCommit, gitDate, "Manage Ethereum account operations")
|
||||||
keystoreFlag,
|
)
|
||||||
configdirFlag,
|
|
||||||
chainIdFlag,
|
|
||||||
utils.LightKDFFlag,
|
|
||||||
utils.NoUSBFlag,
|
|
||||||
utils.SmartCardDaemonPathFlag,
|
|
||||||
utils.HTTPListenAddrFlag,
|
|
||||||
utils.HTTPVirtualHostsFlag,
|
|
||||||
utils.IPCDisabledFlag,
|
|
||||||
utils.IPCPathFlag,
|
|
||||||
utils.HTTPEnabledFlag,
|
|
||||||
rpcPortFlag,
|
|
||||||
signerSecretFlag,
|
|
||||||
customDBFlag,
|
|
||||||
auditLogFlag,
|
|
||||||
ruleFlag,
|
|
||||||
stdiouiFlag,
|
|
||||||
testFlag,
|
|
||||||
advancedMode,
|
|
||||||
acceptFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app.Name = "Clef"
|
app.Name = "Clef"
|
||||||
app.Usage = "Manage Ethereum account operations"
|
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
logLevelFlag,
|
logLevelFlag,
|
||||||
keystoreFlag,
|
keystoreFlag,
|
||||||
|
@ -273,46 +249,12 @@ func init() {
|
||||||
acceptFlag,
|
acceptFlag,
|
||||||
}
|
}
|
||||||
app.Action = signer
|
app.Action = signer
|
||||||
app.Commands = []cli.Command{initCommand,
|
app.Commands = []*cli.Command{initCommand,
|
||||||
attestCommand,
|
attestCommand,
|
||||||
setCredentialCommand,
|
setCredentialCommand,
|
||||||
delCredentialCommand,
|
delCredentialCommand,
|
||||||
newAccountCommand,
|
newAccountCommand,
|
||||||
gendocCommand}
|
gendocCommand,
|
||||||
cli.CommandHelpTemplate = flags.CommandHelpTemplate
|
|
||||||
// Override the default app help template
|
|
||||||
cli.AppHelpTemplate = flags.ClefAppHelpTemplate
|
|
||||||
|
|
||||||
// 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 == flags.ClefAppHelpTemplate {
|
|
||||||
// Render out custom usage screen
|
|
||||||
originalHelpPrinter(w, tmpl, flags.HelpData{App: data, FlagGroups: AppHelpFlagGroups})
|
|
||||||
} else if tmpl == flags.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[flags.FlagCategory(flag, AppHelpFlagGroups)] = append(categorized[flags.FlagCategory(flag, AppHelpFlagGroups)], flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort to get a stable ordering
|
|
||||||
sorted := make([]flags.FlagGroup, 0, len(categorized))
|
|
||||||
for cat, flgs := range categorized {
|
|
||||||
sorted = append(sorted, flags.FlagGroup{Name: cat, Flags: flgs})
|
|
||||||
}
|
|
||||||
sort.Sort(flags.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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +271,7 @@ func initializeSecrets(c *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Ensure the master key does not yet exist, we're not willing to overwrite
|
// Ensure the master key does not yet exist, we're not willing to overwrite
|
||||||
configDir := c.GlobalString(configdirFlag.Name)
|
configDir := c.String(configdirFlag.Name)
|
||||||
if err := os.Mkdir(configDir, 0700); err != nil && !os.IsExist(err) {
|
if err := os.Mkdir(configDir, 0700); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -347,7 +289,7 @@ func initializeSecrets(c *cli.Context) error {
|
||||||
return fmt.Errorf("failed to read enough random")
|
return fmt.Errorf("failed to read enough random")
|
||||||
}
|
}
|
||||||
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
||||||
if c.GlobalBool(utils.LightKDFFlag.Name) {
|
if c.Bool(utils.LightKDFFlag.Name) {
|
||||||
n, p = keystore.LightScryptN, keystore.LightScryptP
|
n, p = keystore.LightScryptN, keystore.LightScryptP
|
||||||
}
|
}
|
||||||
text := "The master seed of clef will be locked with a password.\nPlease specify a password. Do not forget this password!"
|
text := "The master seed of clef will be locked with a password.\nPlease specify a password. Do not forget this password!"
|
||||||
|
@ -390,8 +332,9 @@ You should treat 'masterseed.json' with utmost secrecy and make a backup of it!
|
||||||
`)
|
`)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func attestFile(ctx *cli.Context) error {
|
func attestFile(ctx *cli.Context) error {
|
||||||
if len(ctx.Args()) < 1 {
|
if ctx.NArg() < 1 {
|
||||||
utils.Fatalf("This command requires an argument.")
|
utils.Fatalf("This command requires an argument.")
|
||||||
}
|
}
|
||||||
if err := initialize(ctx); err != nil {
|
if err := initialize(ctx); err != nil {
|
||||||
|
@ -402,7 +345,7 @@ func attestFile(ctx *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
configDir := ctx.GlobalString(configdirFlag.Name)
|
configDir := ctx.String(configdirFlag.Name)
|
||||||
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
||||||
confKey := crypto.Keccak256([]byte("config"), stretchedKey)
|
confKey := crypto.Keccak256([]byte("config"), stretchedKey)
|
||||||
|
|
||||||
|
@ -415,7 +358,7 @@ func attestFile(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setCredential(ctx *cli.Context) error {
|
func setCredential(ctx *cli.Context) error {
|
||||||
if len(ctx.Args()) < 1 {
|
if ctx.NArg() < 1 {
|
||||||
utils.Fatalf("This command requires an address to be passed as an argument")
|
utils.Fatalf("This command requires an address to be passed as an argument")
|
||||||
}
|
}
|
||||||
if err := initialize(ctx); err != nil {
|
if err := initialize(ctx); err != nil {
|
||||||
|
@ -433,7 +376,7 @@ func setCredential(ctx *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
configDir := ctx.GlobalString(configdirFlag.Name)
|
configDir := ctx.String(configdirFlag.Name)
|
||||||
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
||||||
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
|
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
|
||||||
|
|
||||||
|
@ -445,7 +388,7 @@ func setCredential(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeCredential(ctx *cli.Context) error {
|
func removeCredential(ctx *cli.Context) error {
|
||||||
if len(ctx.Args()) < 1 {
|
if ctx.NArg() < 1 {
|
||||||
utils.Fatalf("This command requires an address to be passed as an argument")
|
utils.Fatalf("This command requires an address to be passed as an argument")
|
||||||
}
|
}
|
||||||
if err := initialize(ctx); err != nil {
|
if err := initialize(ctx); err != nil {
|
||||||
|
@ -461,7 +404,7 @@ func removeCredential(ctx *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
configDir := ctx.GlobalString(configdirFlag.Name)
|
configDir := ctx.String(configdirFlag.Name)
|
||||||
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
||||||
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
|
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
|
||||||
|
|
||||||
|
@ -481,8 +424,8 @@ func newAccount(c *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
ui = core.NewCommandlineUI()
|
ui = core.NewCommandlineUI()
|
||||||
pwStorage storage.Storage = &storage.NoStorage{}
|
pwStorage storage.Storage = &storage.NoStorage{}
|
||||||
ksLoc = c.GlobalString(keystoreFlag.Name)
|
ksLoc = c.String(keystoreFlag.Name)
|
||||||
lightKdf = c.GlobalBool(utils.LightKDFFlag.Name)
|
lightKdf = c.Bool(utils.LightKDFFlag.Name)
|
||||||
)
|
)
|
||||||
log.Info("Starting clef", "keystore", ksLoc, "light-kdf", lightKdf)
|
log.Info("Starting clef", "keystore", ksLoc, "light-kdf", lightKdf)
|
||||||
am := core.StartClefAccountManager(ksLoc, true, lightKdf, "")
|
am := core.StartClefAccountManager(ksLoc, true, lightKdf, "")
|
||||||
|
@ -500,13 +443,13 @@ func newAccount(c *cli.Context) error {
|
||||||
func initialize(c *cli.Context) error {
|
func initialize(c *cli.Context) error {
|
||||||
// Set up the logger to print everything
|
// Set up the logger to print everything
|
||||||
logOutput := os.Stdout
|
logOutput := os.Stdout
|
||||||
if c.GlobalBool(stdiouiFlag.Name) {
|
if c.Bool(stdiouiFlag.Name) {
|
||||||
logOutput = os.Stderr
|
logOutput = os.Stderr
|
||||||
// If using the stdioui, we can't do the 'confirm'-flow
|
// If using the stdioui, we can't do the 'confirm'-flow
|
||||||
if !c.GlobalBool(acceptFlag.Name) {
|
if !c.Bool(acceptFlag.Name) {
|
||||||
fmt.Fprint(logOutput, legalWarning)
|
fmt.Fprint(logOutput, legalWarning)
|
||||||
}
|
}
|
||||||
} else if !c.GlobalBool(acceptFlag.Name) {
|
} else if !c.Bool(acceptFlag.Name) {
|
||||||
if !confirm(legalWarning) {
|
if !confirm(legalWarning) {
|
||||||
return fmt.Errorf("aborted by user")
|
return fmt.Errorf("aborted by user")
|
||||||
}
|
}
|
||||||
|
@ -545,8 +488,8 @@ func ipcEndpoint(ipcPath, datadir string) string {
|
||||||
|
|
||||||
func signer(c *cli.Context) error {
|
func signer(c *cli.Context) error {
|
||||||
// If we have some unrecognized command, bail out
|
// If we have some unrecognized command, bail out
|
||||||
if args := c.Args(); len(args) > 0 {
|
if c.NArg() > 0 {
|
||||||
return fmt.Errorf("invalid command: %q", args[0])
|
return fmt.Errorf("invalid command: %q", c.Args().First())
|
||||||
}
|
}
|
||||||
if err := initialize(c); err != nil {
|
if err := initialize(c); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -554,7 +497,7 @@ func signer(c *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
ui core.UIClientAPI
|
ui core.UIClientAPI
|
||||||
)
|
)
|
||||||
if c.GlobalBool(stdiouiFlag.Name) {
|
if c.Bool(stdiouiFlag.Name) {
|
||||||
log.Info("Using stdin/stdout as UI-channel")
|
log.Info("Using stdin/stdout as UI-channel")
|
||||||
ui = core.NewStdIOUI()
|
ui = core.NewStdIOUI()
|
||||||
} else {
|
} else {
|
||||||
|
@ -562,7 +505,7 @@ func signer(c *cli.Context) error {
|
||||||
ui = core.NewCommandlineUI()
|
ui = core.NewCommandlineUI()
|
||||||
}
|
}
|
||||||
// 4bytedb data
|
// 4bytedb data
|
||||||
fourByteLocal := c.GlobalString(customDBFlag.Name)
|
fourByteLocal := c.String(customDBFlag.Name)
|
||||||
db, err := fourbyte.NewWithFile(fourByteLocal)
|
db, err := fourbyte.NewWithFile(fourByteLocal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
|
@ -574,7 +517,7 @@ func signer(c *cli.Context) error {
|
||||||
api core.ExternalAPI
|
api core.ExternalAPI
|
||||||
pwStorage storage.Storage = &storage.NoStorage{}
|
pwStorage storage.Storage = &storage.NoStorage{}
|
||||||
)
|
)
|
||||||
configDir := c.GlobalString(configdirFlag.Name)
|
configDir := c.String(configdirFlag.Name)
|
||||||
if stretchedKey, err := readMasterKey(c, ui); err != nil {
|
if stretchedKey, err := readMasterKey(c, ui); err != nil {
|
||||||
log.Warn("Failed to open master, rules disabled", "err", err)
|
log.Warn("Failed to open master, rules disabled", "err", err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -591,7 +534,7 @@ func signer(c *cli.Context) error {
|
||||||
configStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "config.json"), confkey)
|
configStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "config.json"), confkey)
|
||||||
|
|
||||||
// Do we have a rule-file?
|
// Do we have a rule-file?
|
||||||
if ruleFile := c.GlobalString(ruleFlag.Name); ruleFile != "" {
|
if ruleFile := c.String(ruleFlag.Name); ruleFile != "" {
|
||||||
ruleJS, err := os.ReadFile(ruleFile)
|
ruleJS, err := os.ReadFile(ruleFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Could not load rules, disabling", "file", ruleFile, "err", err)
|
log.Warn("Could not load rules, disabling", "file", ruleFile, "err", err)
|
||||||
|
@ -615,12 +558,12 @@ func signer(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
chainId = c.GlobalInt64(chainIdFlag.Name)
|
chainId = c.Int64(chainIdFlag.Name)
|
||||||
ksLoc = c.GlobalString(keystoreFlag.Name)
|
ksLoc = c.String(keystoreFlag.Name)
|
||||||
lightKdf = c.GlobalBool(utils.LightKDFFlag.Name)
|
lightKdf = c.Bool(utils.LightKDFFlag.Name)
|
||||||
advanced = c.GlobalBool(advancedMode.Name)
|
advanced = c.Bool(advancedMode.Name)
|
||||||
nousb = c.GlobalBool(utils.NoUSBFlag.Name)
|
nousb = c.Bool(utils.NoUSBFlag.Name)
|
||||||
scpath = c.GlobalString(utils.SmartCardDaemonPathFlag.Name)
|
scpath = c.String(utils.SmartCardDaemonPathFlag.Name)
|
||||||
)
|
)
|
||||||
log.Info("Starting signer", "chainid", chainId, "keystore", ksLoc,
|
log.Info("Starting signer", "chainid", chainId, "keystore", ksLoc,
|
||||||
"light-kdf", lightKdf, "advanced", advanced)
|
"light-kdf", lightKdf, "advanced", advanced)
|
||||||
|
@ -632,7 +575,7 @@ func signer(c *cli.Context) error {
|
||||||
ui.RegisterUIServer(core.NewUIServerAPI(apiImpl))
|
ui.RegisterUIServer(core.NewUIServerAPI(apiImpl))
|
||||||
api = apiImpl
|
api = apiImpl
|
||||||
// Audit logging
|
// Audit logging
|
||||||
if logfile := c.GlobalString(auditLogFlag.Name); logfile != "" {
|
if logfile := c.String(auditLogFlag.Name); logfile != "" {
|
||||||
api, err = core.NewAuditLogger(logfile, api)
|
api, err = core.NewAuditLogger(logfile, api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
|
@ -650,9 +593,9 @@ func signer(c *cli.Context) error {
|
||||||
Service: api,
|
Service: api,
|
||||||
Version: "1.0"},
|
Version: "1.0"},
|
||||||
}
|
}
|
||||||
if c.GlobalBool(utils.HTTPEnabledFlag.Name) {
|
if c.Bool(utils.HTTPEnabledFlag.Name) {
|
||||||
vhosts := utils.SplitAndTrim(c.GlobalString(utils.HTTPVirtualHostsFlag.Name))
|
vhosts := utils.SplitAndTrim(c.String(utils.HTTPVirtualHostsFlag.Name))
|
||||||
cors := utils.SplitAndTrim(c.GlobalString(utils.HTTPCORSDomainFlag.Name))
|
cors := utils.SplitAndTrim(c.String(utils.HTTPCORSDomainFlag.Name))
|
||||||
|
|
||||||
srv := rpc.NewServer()
|
srv := rpc.NewServer()
|
||||||
err := node.RegisterApis(rpcAPI, []string{"account"}, srv)
|
err := node.RegisterApis(rpcAPI, []string{"account"}, srv)
|
||||||
|
@ -665,7 +608,7 @@ func signer(c *cli.Context) error {
|
||||||
port := c.Int(rpcPortFlag.Name)
|
port := c.Int(rpcPortFlag.Name)
|
||||||
|
|
||||||
// start http server
|
// start http server
|
||||||
httpEndpoint := fmt.Sprintf("%s:%d", c.GlobalString(utils.HTTPListenAddrFlag.Name), port)
|
httpEndpoint := fmt.Sprintf("%s:%d", c.String(utils.HTTPListenAddrFlag.Name), port)
|
||||||
httpServer, addr, err := node.StartHTTPEndpoint(httpEndpoint, rpc.DefaultHTTPTimeouts, handler)
|
httpServer, addr, err := node.StartHTTPEndpoint(httpEndpoint, rpc.DefaultHTTPTimeouts, handler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Could not start RPC api: %v", err)
|
utils.Fatalf("Could not start RPC api: %v", err)
|
||||||
|
@ -679,8 +622,8 @@ func signer(c *cli.Context) error {
|
||||||
log.Info("HTTP endpoint closed", "url", extapiURL)
|
log.Info("HTTP endpoint closed", "url", extapiURL)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
if !c.GlobalBool(utils.IPCDisabledFlag.Name) {
|
if !c.Bool(utils.IPCDisabledFlag.Name) {
|
||||||
givenPath := c.GlobalString(utils.IPCPathFlag.Name)
|
givenPath := c.String(utils.IPCPathFlag.Name)
|
||||||
ipcapiURL = ipcEndpoint(filepath.Join(givenPath, "clef.ipc"), configDir)
|
ipcapiURL = ipcEndpoint(filepath.Join(givenPath, "clef.ipc"), configDir)
|
||||||
listener, _, err := rpc.StartIPCEndpoint(ipcapiURL, rpcAPI)
|
listener, _, err := rpc.StartIPCEndpoint(ipcapiURL, rpcAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -693,7 +636,7 @@ func signer(c *cli.Context) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.GlobalBool(testFlag.Name) {
|
if c.Bool(testFlag.Name) {
|
||||||
log.Info("Performing UI test")
|
log.Info("Performing UI test")
|
||||||
go testExternalUI(apiImpl)
|
go testExternalUI(apiImpl)
|
||||||
}
|
}
|
||||||
|
@ -719,7 +662,7 @@ func signer(c *cli.Context) error {
|
||||||
// persistence requirements.
|
// persistence requirements.
|
||||||
func DefaultConfigDir() string {
|
func DefaultConfigDir() string {
|
||||||
// Try to place the data folder in the user's home dir
|
// Try to place the data folder in the user's home dir
|
||||||
home := utils.HomeDir()
|
home := flags.HomeDir()
|
||||||
if home != "" {
|
if home != "" {
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
return filepath.Join(home, "Library", "Signer")
|
return filepath.Join(home, "Library", "Signer")
|
||||||
|
@ -739,10 +682,10 @@ func DefaultConfigDir() string {
|
||||||
func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) {
|
func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) {
|
||||||
var (
|
var (
|
||||||
file string
|
file string
|
||||||
configDir = ctx.GlobalString(configdirFlag.Name)
|
configDir = ctx.String(configdirFlag.Name)
|
||||||
)
|
)
|
||||||
if ctx.GlobalIsSet(signerSecretFlag.Name) {
|
if ctx.IsSet(signerSecretFlag.Name) {
|
||||||
file = ctx.GlobalString(signerSecretFlag.Name)
|
file = ctx.String(signerSecretFlag.Name)
|
||||||
} else {
|
} else {
|
||||||
file = filepath.Join(configDir, "masterseed.json")
|
file = filepath.Join(configDir, "masterseed.json")
|
||||||
}
|
}
|
||||||
|
@ -995,7 +938,7 @@ func decryptSeed(keyjson []byte, auth string) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenDoc outputs examples of all structures used in json-rpc communication
|
// GenDoc outputs examples of all structures used in json-rpc communication
|
||||||
func GenDoc(ctx *cli.Context) {
|
func GenDoc(ctx *cli.Context) error {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
a = common.HexToAddress("0xdeadbeef000000000000000000000000deadbeef")
|
a = common.HexToAddress("0xdeadbeef000000000000000000000000deadbeef")
|
||||||
|
@ -1145,4 +1088,5 @@ These data types are defined in the channel between clef and the UI`)
|
||||||
for _, elem := range output {
|
for _, elem := range output {
|
||||||
fmt.Println(elem)
|
fmt.Println(elem)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,14 +28,14 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
discv4Command = cli.Command{
|
discv4Command = &cli.Command{
|
||||||
Name: "discv4",
|
Name: "discv4",
|
||||||
Usage: "Node Discovery v4 tools",
|
Usage: "Node Discovery v4 tools",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
discv4PingCommand,
|
discv4PingCommand,
|
||||||
discv4RequestRecordCommand,
|
discv4RequestRecordCommand,
|
||||||
discv4ResolveCommand,
|
discv4ResolveCommand,
|
||||||
|
@ -44,39 +44,39 @@ var (
|
||||||
discv4TestCommand,
|
discv4TestCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
discv4PingCommand = cli.Command{
|
discv4PingCommand = &cli.Command{
|
||||||
Name: "ping",
|
Name: "ping",
|
||||||
Usage: "Sends ping to a node",
|
Usage: "Sends ping to a node",
|
||||||
Action: discv4Ping,
|
Action: discv4Ping,
|
||||||
ArgsUsage: "<node>",
|
ArgsUsage: "<node>",
|
||||||
}
|
}
|
||||||
discv4RequestRecordCommand = cli.Command{
|
discv4RequestRecordCommand = &cli.Command{
|
||||||
Name: "requestenr",
|
Name: "requestenr",
|
||||||
Usage: "Requests a node record using EIP-868 enrRequest",
|
Usage: "Requests a node record using EIP-868 enrRequest",
|
||||||
Action: discv4RequestRecord,
|
Action: discv4RequestRecord,
|
||||||
ArgsUsage: "<node>",
|
ArgsUsage: "<node>",
|
||||||
}
|
}
|
||||||
discv4ResolveCommand = cli.Command{
|
discv4ResolveCommand = &cli.Command{
|
||||||
Name: "resolve",
|
Name: "resolve",
|
||||||
Usage: "Finds a node in the DHT",
|
Usage: "Finds a node in the DHT",
|
||||||
Action: discv4Resolve,
|
Action: discv4Resolve,
|
||||||
ArgsUsage: "<node>",
|
ArgsUsage: "<node>",
|
||||||
Flags: []cli.Flag{bootnodesFlag},
|
Flags: []cli.Flag{bootnodesFlag},
|
||||||
}
|
}
|
||||||
discv4ResolveJSONCommand = cli.Command{
|
discv4ResolveJSONCommand = &cli.Command{
|
||||||
Name: "resolve-json",
|
Name: "resolve-json",
|
||||||
Usage: "Re-resolves nodes in a nodes.json file",
|
Usage: "Re-resolves nodes in a nodes.json file",
|
||||||
Action: discv4ResolveJSON,
|
Action: discv4ResolveJSON,
|
||||||
Flags: []cli.Flag{bootnodesFlag},
|
Flags: []cli.Flag{bootnodesFlag},
|
||||||
ArgsUsage: "<nodes.json file>",
|
ArgsUsage: "<nodes.json file>",
|
||||||
}
|
}
|
||||||
discv4CrawlCommand = cli.Command{
|
discv4CrawlCommand = &cli.Command{
|
||||||
Name: "crawl",
|
Name: "crawl",
|
||||||
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
||||||
Action: discv4Crawl,
|
Action: discv4Crawl,
|
||||||
Flags: []cli.Flag{bootnodesFlag, crawlTimeoutFlag},
|
Flags: []cli.Flag{bootnodesFlag, crawlTimeoutFlag},
|
||||||
}
|
}
|
||||||
discv4TestCommand = cli.Command{
|
discv4TestCommand = &cli.Command{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Usage: "Runs tests against a node",
|
Usage: "Runs tests against a node",
|
||||||
Action: discv4Test,
|
Action: discv4Test,
|
||||||
|
@ -91,31 +91,31 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bootnodesFlag = cli.StringFlag{
|
bootnodesFlag = &cli.StringFlag{
|
||||||
Name: "bootnodes",
|
Name: "bootnodes",
|
||||||
Usage: "Comma separated nodes used for bootstrapping",
|
Usage: "Comma separated nodes used for bootstrapping",
|
||||||
}
|
}
|
||||||
nodekeyFlag = cli.StringFlag{
|
nodekeyFlag = &cli.StringFlag{
|
||||||
Name: "nodekey",
|
Name: "nodekey",
|
||||||
Usage: "Hex-encoded node key",
|
Usage: "Hex-encoded node key",
|
||||||
}
|
}
|
||||||
nodedbFlag = cli.StringFlag{
|
nodedbFlag = &cli.StringFlag{
|
||||||
Name: "nodedb",
|
Name: "nodedb",
|
||||||
Usage: "Nodes database location",
|
Usage: "Nodes database location",
|
||||||
}
|
}
|
||||||
listenAddrFlag = cli.StringFlag{
|
listenAddrFlag = &cli.StringFlag{
|
||||||
Name: "addr",
|
Name: "addr",
|
||||||
Usage: "Listening address",
|
Usage: "Listening address",
|
||||||
}
|
}
|
||||||
crawlTimeoutFlag = cli.DurationFlag{
|
crawlTimeoutFlag = &cli.DurationFlag{
|
||||||
Name: "timeout",
|
Name: "timeout",
|
||||||
Usage: "Time limit for the crawl.",
|
Usage: "Time limit for the crawl.",
|
||||||
Value: 30 * time.Minute,
|
Value: 30 * time.Minute,
|
||||||
}
|
}
|
||||||
remoteEnodeFlag = cli.StringFlag{
|
remoteEnodeFlag = &cli.StringFlag{
|
||||||
Name: "remote",
|
Name: "remote",
|
||||||
Usage: "Enode of the remote node under test",
|
Usage: "Enode of the remote node under test",
|
||||||
EnvVar: "REMOTE_ENODE",
|
EnvVars: []string{"REMOTE_ENODE"},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,14 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
|
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
discv5Command = cli.Command{
|
discv5Command = &cli.Command{
|
||||||
Name: "discv5",
|
Name: "discv5",
|
||||||
Usage: "Node Discovery v5 tools",
|
Usage: "Node Discovery v5 tools",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
discv5PingCommand,
|
discv5PingCommand,
|
||||||
discv5ResolveCommand,
|
discv5ResolveCommand,
|
||||||
discv5CrawlCommand,
|
discv5CrawlCommand,
|
||||||
|
@ -38,24 +38,24 @@ var (
|
||||||
discv5ListenCommand,
|
discv5ListenCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
discv5PingCommand = cli.Command{
|
discv5PingCommand = &cli.Command{
|
||||||
Name: "ping",
|
Name: "ping",
|
||||||
Usage: "Sends ping to a node",
|
Usage: "Sends ping to a node",
|
||||||
Action: discv5Ping,
|
Action: discv5Ping,
|
||||||
}
|
}
|
||||||
discv5ResolveCommand = cli.Command{
|
discv5ResolveCommand = &cli.Command{
|
||||||
Name: "resolve",
|
Name: "resolve",
|
||||||
Usage: "Finds a node in the DHT",
|
Usage: "Finds a node in the DHT",
|
||||||
Action: discv5Resolve,
|
Action: discv5Resolve,
|
||||||
Flags: []cli.Flag{bootnodesFlag},
|
Flags: []cli.Flag{bootnodesFlag},
|
||||||
}
|
}
|
||||||
discv5CrawlCommand = cli.Command{
|
discv5CrawlCommand = &cli.Command{
|
||||||
Name: "crawl",
|
Name: "crawl",
|
||||||
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
||||||
Action: discv5Crawl,
|
Action: discv5Crawl,
|
||||||
Flags: []cli.Flag{bootnodesFlag, crawlTimeoutFlag},
|
Flags: []cli.Flag{bootnodesFlag, crawlTimeoutFlag},
|
||||||
}
|
}
|
||||||
discv5TestCommand = cli.Command{
|
discv5TestCommand = &cli.Command{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Usage: "Runs protocol tests against a node",
|
Usage: "Runs protocol tests against a node",
|
||||||
Action: discv5Test,
|
Action: discv5Test,
|
||||||
|
@ -66,7 +66,7 @@ var (
|
||||||
testListen2Flag,
|
testListen2Flag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
discv5ListenCommand = cli.Command{
|
discv5ListenCommand = &cli.Command{
|
||||||
Name: "listen",
|
Name: "listen",
|
||||||
Usage: "Runs a node",
|
Usage: "Runs a node",
|
||||||
Action: discv5Listen,
|
Action: discv5Listen,
|
||||||
|
|
|
@ -24,16 +24,16 @@ import (
|
||||||
"github.com/cloudflare/cloudflare-go"
|
"github.com/cloudflare/cloudflare-go"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cloudflareTokenFlag = cli.StringFlag{
|
cloudflareTokenFlag = &cli.StringFlag{
|
||||||
Name: "token",
|
Name: "token",
|
||||||
Usage: "CloudFlare API token",
|
Usage: "CloudFlare API token",
|
||||||
EnvVar: "CLOUDFLARE_API_TOKEN",
|
EnvVars: []string{"CLOUDFLARE_API_TOKEN"},
|
||||||
}
|
}
|
||||||
cloudflareZoneIDFlag = cli.StringFlag{
|
cloudflareZoneIDFlag = &cli.StringFlag{
|
||||||
Name: "zoneid",
|
Name: "zoneid",
|
||||||
Usage: "CloudFlare Zone ID (optional)",
|
Usage: "CloudFlare Zone ID (optional)",
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import (
|
||||||
"github.com/aws/aws-sdk-go-v2/service/route53/types"
|
"github.com/aws/aws-sdk-go-v2/service/route53/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -45,21 +45,21 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
route53AccessKeyFlag = cli.StringFlag{
|
route53AccessKeyFlag = &cli.StringFlag{
|
||||||
Name: "access-key-id",
|
Name: "access-key-id",
|
||||||
Usage: "AWS Access Key ID",
|
Usage: "AWS Access Key ID",
|
||||||
EnvVar: "AWS_ACCESS_KEY_ID",
|
EnvVars: []string{"AWS_ACCESS_KEY_ID"},
|
||||||
}
|
}
|
||||||
route53AccessSecretFlag = cli.StringFlag{
|
route53AccessSecretFlag = &cli.StringFlag{
|
||||||
Name: "access-key-secret",
|
Name: "access-key-secret",
|
||||||
Usage: "AWS Access Key Secret",
|
Usage: "AWS Access Key Secret",
|
||||||
EnvVar: "AWS_SECRET_ACCESS_KEY",
|
EnvVars: []string{"AWS_SECRET_ACCESS_KEY"},
|
||||||
}
|
}
|
||||||
route53ZoneIDFlag = cli.StringFlag{
|
route53ZoneIDFlag = &cli.StringFlag{
|
||||||
Name: "zone-id",
|
Name: "zone-id",
|
||||||
Usage: "Route53 Zone ID",
|
Usage: "Route53 Zone ID",
|
||||||
}
|
}
|
||||||
route53RegionFlag = cli.StringFlag{
|
route53RegionFlag = &cli.StringFlag{
|
||||||
Name: "aws-region",
|
Name: "aws-region",
|
||||||
Usage: "AWS Region",
|
Usage: "AWS Region",
|
||||||
Value: "eu-central-1",
|
Value: "eu-central-1",
|
||||||
|
|
|
@ -29,14 +29,14 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/console/prompt"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dnsCommand = cli.Command{
|
dnsCommand = &cli.Command{
|
||||||
Name: "dns",
|
Name: "dns",
|
||||||
Usage: "DNS Discovery Commands",
|
Usage: "DNS Discovery Commands",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
dnsSyncCommand,
|
dnsSyncCommand,
|
||||||
dnsSignCommand,
|
dnsSignCommand,
|
||||||
dnsTXTCommand,
|
dnsTXTCommand,
|
||||||
|
@ -45,34 +45,34 @@ var (
|
||||||
dnsRoute53NukeCommand,
|
dnsRoute53NukeCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dnsSyncCommand = cli.Command{
|
dnsSyncCommand = &cli.Command{
|
||||||
Name: "sync",
|
Name: "sync",
|
||||||
Usage: "Download a DNS discovery tree",
|
Usage: "Download a DNS discovery tree",
|
||||||
ArgsUsage: "<url> [ <directory> ]",
|
ArgsUsage: "<url> [ <directory> ]",
|
||||||
Action: dnsSync,
|
Action: dnsSync,
|
||||||
Flags: []cli.Flag{dnsTimeoutFlag},
|
Flags: []cli.Flag{dnsTimeoutFlag},
|
||||||
}
|
}
|
||||||
dnsSignCommand = cli.Command{
|
dnsSignCommand = &cli.Command{
|
||||||
Name: "sign",
|
Name: "sign",
|
||||||
Usage: "Sign a DNS discovery tree",
|
Usage: "Sign a DNS discovery tree",
|
||||||
ArgsUsage: "<tree-directory> <key-file>",
|
ArgsUsage: "<tree-directory> <key-file>",
|
||||||
Action: dnsSign,
|
Action: dnsSign,
|
||||||
Flags: []cli.Flag{dnsDomainFlag, dnsSeqFlag},
|
Flags: []cli.Flag{dnsDomainFlag, dnsSeqFlag},
|
||||||
}
|
}
|
||||||
dnsTXTCommand = cli.Command{
|
dnsTXTCommand = &cli.Command{
|
||||||
Name: "to-txt",
|
Name: "to-txt",
|
||||||
Usage: "Create a DNS TXT records for a discovery tree",
|
Usage: "Create a DNS TXT records for a discovery tree",
|
||||||
ArgsUsage: "<tree-directory> <output-file>",
|
ArgsUsage: "<tree-directory> <output-file>",
|
||||||
Action: dnsToTXT,
|
Action: dnsToTXT,
|
||||||
}
|
}
|
||||||
dnsCloudflareCommand = cli.Command{
|
dnsCloudflareCommand = &cli.Command{
|
||||||
Name: "to-cloudflare",
|
Name: "to-cloudflare",
|
||||||
Usage: "Deploy DNS TXT records to CloudFlare",
|
Usage: "Deploy DNS TXT records to CloudFlare",
|
||||||
ArgsUsage: "<tree-directory>",
|
ArgsUsage: "<tree-directory>",
|
||||||
Action: dnsToCloudflare,
|
Action: dnsToCloudflare,
|
||||||
Flags: []cli.Flag{cloudflareTokenFlag, cloudflareZoneIDFlag},
|
Flags: []cli.Flag{cloudflareTokenFlag, cloudflareZoneIDFlag},
|
||||||
}
|
}
|
||||||
dnsRoute53Command = cli.Command{
|
dnsRoute53Command = &cli.Command{
|
||||||
Name: "to-route53",
|
Name: "to-route53",
|
||||||
Usage: "Deploy DNS TXT records to Amazon Route53",
|
Usage: "Deploy DNS TXT records to Amazon Route53",
|
||||||
ArgsUsage: "<tree-directory>",
|
ArgsUsage: "<tree-directory>",
|
||||||
|
@ -84,7 +84,7 @@ var (
|
||||||
route53RegionFlag,
|
route53RegionFlag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dnsRoute53NukeCommand = cli.Command{
|
dnsRoute53NukeCommand = &cli.Command{
|
||||||
Name: "nuke-route53",
|
Name: "nuke-route53",
|
||||||
Usage: "Deletes DNS TXT records of a subdomain on Amazon Route53",
|
Usage: "Deletes DNS TXT records of a subdomain on Amazon Route53",
|
||||||
ArgsUsage: "<domain>",
|
ArgsUsage: "<domain>",
|
||||||
|
@ -99,15 +99,15 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dnsTimeoutFlag = cli.DurationFlag{
|
dnsTimeoutFlag = &cli.DurationFlag{
|
||||||
Name: "timeout",
|
Name: "timeout",
|
||||||
Usage: "Timeout for DNS lookups",
|
Usage: "Timeout for DNS lookups",
|
||||||
}
|
}
|
||||||
dnsDomainFlag = cli.StringFlag{
|
dnsDomainFlag = &cli.StringFlag{
|
||||||
Name: "domain",
|
Name: "domain",
|
||||||
Usage: "Domain name of the tree",
|
Usage: "Domain name of the tree",
|
||||||
}
|
}
|
||||||
dnsSeqFlag = cli.UintFlag{
|
dnsSeqFlag = &cli.UintFlag{
|
||||||
Name: "seq",
|
Name: "seq",
|
||||||
Usage: "New sequence number of the tree",
|
Usage: "New sequence number of the tree",
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,12 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fileFlag = cli.StringFlag{Name: "file"}
|
var fileFlag = &cli.StringFlag{Name: "file"}
|
||||||
|
|
||||||
var enrdumpCommand = cli.Command{
|
var enrdumpCommand = &cli.Command{
|
||||||
Name: "enrdump",
|
Name: "enrdump",
|
||||||
Usage: "Pretty-prints node records",
|
Usage: "Pretty-prints node records",
|
||||||
Action: enrdump,
|
Action: enrdump,
|
||||||
|
@ -62,7 +62,7 @@ func enrdump(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
source = string(b)
|
source = string(b)
|
||||||
} else if ctx.NArg() == 1 {
|
} else if ctx.NArg() == 1 {
|
||||||
source = ctx.Args()[0]
|
source = ctx.Args().First()
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("need record as argument")
|
return fmt.Errorf("need record as argument")
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,25 +22,25 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
keyCommand = cli.Command{
|
keyCommand = &cli.Command{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Usage: "Operations on node keys",
|
Usage: "Operations on node keys",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
keyGenerateCommand,
|
keyGenerateCommand,
|
||||||
keyToNodeCommand,
|
keyToNodeCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
keyGenerateCommand = cli.Command{
|
keyGenerateCommand = &cli.Command{
|
||||||
Name: "generate",
|
Name: "generate",
|
||||||
Usage: "Generates node key files",
|
Usage: "Generates node key files",
|
||||||
ArgsUsage: "keyfile",
|
ArgsUsage: "keyfile",
|
||||||
Action: genkey,
|
Action: genkey,
|
||||||
}
|
}
|
||||||
keyToNodeCommand = cli.Command{
|
keyToNodeCommand = &cli.Command{
|
||||||
Name: "to-enode",
|
Name: "to-enode",
|
||||||
Usage: "Creates an enode URL from a node key file",
|
Usage: "Creates an enode URL from a node key file",
|
||||||
ArgsUsage: "keyfile",
|
ArgsUsage: "keyfile",
|
||||||
|
@ -50,17 +50,17 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hostFlag = cli.StringFlag{
|
hostFlag = &cli.StringFlag{
|
||||||
Name: "ip",
|
Name: "ip",
|
||||||
Usage: "IP address of the node",
|
Usage: "IP address of the node",
|
||||||
Value: "127.0.0.1",
|
Value: "127.0.0.1",
|
||||||
}
|
}
|
||||||
tcpPortFlag = cli.IntFlag{
|
tcpPortFlag = &cli.IntFlag{
|
||||||
Name: "tcp",
|
Name: "tcp",
|
||||||
Usage: "TCP port of the node",
|
Usage: "TCP port of the node",
|
||||||
Value: 30303,
|
Value: 30303,
|
||||||
}
|
}
|
||||||
udpPortFlag = cli.IntFlag{
|
udpPortFlag = &cli.IntFlag{
|
||||||
Name: "udp",
|
Name: "udp",
|
||||||
Usage: "UDP port of the node",
|
Usage: "UDP port of the node",
|
||||||
Value: 30303,
|
Value: 30303,
|
||||||
|
|
|
@ -20,12 +20,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/debug"
|
"github.com/ethereum/go-ethereum/internal/debug"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -45,6 +45,7 @@ func init() {
|
||||||
// Set up the CLI app.
|
// Set up the CLI app.
|
||||||
app.Flags = append(app.Flags, debug.Flags...)
|
app.Flags = append(app.Flags, debug.Flags...)
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
|
flags.MigrateGlobalFlags(ctx)
|
||||||
return debug.Setup(ctx)
|
return debug.Setup(ctx)
|
||||||
}
|
}
|
||||||
app.After = func(ctx *cli.Context) error {
|
app.After = func(ctx *cli.Context) error {
|
||||||
|
@ -56,7 +57,7 @@ func init() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
// Add subcommands.
|
// Add subcommands.
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
enrdumpCommand,
|
enrdumpCommand,
|
||||||
keyCommand,
|
keyCommand,
|
||||||
discv4Command,
|
discv4Command,
|
||||||
|
@ -73,10 +74,17 @@ func main() {
|
||||||
|
|
||||||
// commandHasFlag returns true if the current command supports the given flag.
|
// commandHasFlag returns true if the current command supports the given flag.
|
||||||
func commandHasFlag(ctx *cli.Context, flag cli.Flag) bool {
|
func commandHasFlag(ctx *cli.Context, flag cli.Flag) bool {
|
||||||
flags := ctx.FlagNames()
|
names := flag.Names()
|
||||||
sort.Strings(flags)
|
set := make(map[string]struct{}, len(names))
|
||||||
i := sort.SearchStrings(flags, flag.GetName())
|
for _, name := range names {
|
||||||
return i != len(flags) && flags[i] == flag.GetName()
|
set[name] = struct{}{}
|
||||||
|
}
|
||||||
|
for _, fn := range ctx.FlagNames() {
|
||||||
|
if _, ok := set[fn]; ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// getNodeArg handles the common case of a single node descriptor argument.
|
// getNodeArg handles the common case of a single node descriptor argument.
|
||||||
|
@ -84,7 +92,7 @@ func getNodeArg(ctx *cli.Context) *enode.Node {
|
||||||
if ctx.NArg() < 1 {
|
if ctx.NArg() < 1 {
|
||||||
exit("missing node as command-line argument")
|
exit("missing node as command-line argument")
|
||||||
}
|
}
|
||||||
n, err := parseNode(ctx.Args()[0])
|
n, err := parseNode(ctx.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,25 +29,25 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
nodesetCommand = cli.Command{
|
nodesetCommand = &cli.Command{
|
||||||
Name: "nodeset",
|
Name: "nodeset",
|
||||||
Usage: "Node set tools",
|
Usage: "Node set tools",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
nodesetInfoCommand,
|
nodesetInfoCommand,
|
||||||
nodesetFilterCommand,
|
nodesetFilterCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
nodesetInfoCommand = cli.Command{
|
nodesetInfoCommand = &cli.Command{
|
||||||
Name: "info",
|
Name: "info",
|
||||||
Usage: "Shows statistics about a node set",
|
Usage: "Shows statistics about a node set",
|
||||||
Action: nodesetInfo,
|
Action: nodesetInfo,
|
||||||
ArgsUsage: "<nodes.json>",
|
ArgsUsage: "<nodes.json>",
|
||||||
}
|
}
|
||||||
nodesetFilterCommand = cli.Command{
|
nodesetFilterCommand = &cli.Command{
|
||||||
Name: "filter",
|
Name: "filter",
|
||||||
Usage: "Filters a node set",
|
Usage: "Filters a node set",
|
||||||
Action: nodesetFilter,
|
Action: nodesetFilter,
|
||||||
|
|
|
@ -26,25 +26,25 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/rlpx"
|
"github.com/ethereum/go-ethereum/p2p/rlpx"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rlpxCommand = cli.Command{
|
rlpxCommand = &cli.Command{
|
||||||
Name: "rlpx",
|
Name: "rlpx",
|
||||||
Usage: "RLPx Commands",
|
Usage: "RLPx Commands",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
rlpxPingCommand,
|
rlpxPingCommand,
|
||||||
rlpxEthTestCommand,
|
rlpxEthTestCommand,
|
||||||
rlpxSnapTestCommand,
|
rlpxSnapTestCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
rlpxPingCommand = cli.Command{
|
rlpxPingCommand = &cli.Command{
|
||||||
Name: "ping",
|
Name: "ping",
|
||||||
Usage: "ping <node>",
|
Usage: "ping <node>",
|
||||||
Action: rlpxPing,
|
Action: rlpxPing,
|
||||||
}
|
}
|
||||||
rlpxEthTestCommand = cli.Command{
|
rlpxEthTestCommand = &cli.Command{
|
||||||
Name: "eth-test",
|
Name: "eth-test",
|
||||||
Usage: "Runs tests against a node",
|
Usage: "Runs tests against a node",
|
||||||
ArgsUsage: "<node> <chain.rlp> <genesis.json>",
|
ArgsUsage: "<node> <chain.rlp> <genesis.json>",
|
||||||
|
@ -54,7 +54,7 @@ var (
|
||||||
testTAPFlag,
|
testTAPFlag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
rlpxSnapTestCommand = cli.Command{
|
rlpxSnapTestCommand = &cli.Command{
|
||||||
Name: "snap-test",
|
Name: "snap-test",
|
||||||
Usage: "Runs tests against a node",
|
Usage: "Runs tests against a node",
|
||||||
ArgsUsage: "<node> <chain.rlp> <genesis.json>",
|
ArgsUsage: "<node> <chain.rlp> <genesis.json>",
|
||||||
|
@ -106,7 +106,7 @@ func rlpxEthTest(ctx *cli.Context) error {
|
||||||
if ctx.NArg() < 3 {
|
if ctx.NArg() < 3 {
|
||||||
exit("missing path to chain.rlp as command-line argument")
|
exit("missing path to chain.rlp as command-line argument")
|
||||||
}
|
}
|
||||||
suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args()[1], ctx.Args()[2])
|
suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ func rlpxSnapTest(ctx *cli.Context) error {
|
||||||
if ctx.NArg() < 3 {
|
if ctx.NArg() < 3 {
|
||||||
exit("missing path to chain.rlp as command-line argument")
|
exit("missing path to chain.rlp as command-line argument")
|
||||||
}
|
}
|
||||||
suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args()[1], ctx.Args()[2])
|
suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,25 +22,25 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
|
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
|
||||||
"github.com/ethereum/go-ethereum/internal/utesting"
|
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testPatternFlag = cli.StringFlag{
|
testPatternFlag = &cli.StringFlag{
|
||||||
Name: "run",
|
Name: "run",
|
||||||
Usage: "Pattern of test suite(s) to run",
|
Usage: "Pattern of test suite(s) to run",
|
||||||
}
|
}
|
||||||
testTAPFlag = cli.BoolFlag{
|
testTAPFlag = &cli.BoolFlag{
|
||||||
Name: "tap",
|
Name: "tap",
|
||||||
Usage: "Output TAP",
|
Usage: "Output TAP",
|
||||||
}
|
}
|
||||||
// These two are specific to the discovery tests.
|
// These two are specific to the discovery tests.
|
||||||
testListen1Flag = cli.StringFlag{
|
testListen1Flag = &cli.StringFlag{
|
||||||
Name: "listen1",
|
Name: "listen1",
|
||||||
Usage: "IP address of the first tester",
|
Usage: "IP address of the first tester",
|
||||||
Value: v4test.Listen1,
|
Value: v4test.Listen1,
|
||||||
}
|
}
|
||||||
testListen2Flag = cli.StringFlag{
|
testListen2Flag = &cli.StringFlag{
|
||||||
Name: "listen2",
|
Name: "listen2",
|
||||||
Usage: "IP address of the second tester",
|
Usage: "IP address of the second tester",
|
||||||
Value: v4test.Listen2,
|
Value: v4test.Listen2,
|
||||||
|
@ -53,7 +53,7 @@ func runTests(ctx *cli.Context, tests []utesting.Test) error {
|
||||||
tests = utesting.MatchTests(tests, ctx.String(testPatternFlag.Name))
|
tests = utesting.MatchTests(tests, ctx.String(testPatternFlag.Name))
|
||||||
}
|
}
|
||||||
// Disable logging unless explicitly enabled.
|
// Disable logging unless explicitly enabled.
|
||||||
if !ctx.GlobalIsSet("verbosity") && !ctx.GlobalIsSet("vmodule") {
|
if !ctx.IsSet("verbosity") && !ctx.IsSet("vmodule") {
|
||||||
log.Root().SetHandler(log.DiscardHandler())
|
log.Root().SetHandler(log.DiscardHandler())
|
||||||
}
|
}
|
||||||
// Run the tests.
|
// Run the tests.
|
||||||
|
|
|
@ -23,15 +23,15 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var newPassphraseFlag = cli.StringFlag{
|
var newPassphraseFlag = &cli.StringFlag{
|
||||||
Name: "newpasswordfile",
|
Name: "newpasswordfile",
|
||||||
Usage: "the file that contains the new password for the keyfile",
|
Usage: "the file that contains the new password for the keyfile",
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandChangePassphrase = cli.Command{
|
var commandChangePassphrase = &cli.Command{
|
||||||
Name: "changepassword",
|
Name: "changepassword",
|
||||||
Usage: "change the password on a keyfile",
|
Usage: "change the password on a keyfile",
|
||||||
ArgsUsage: "<keyfile>",
|
ArgsUsage: "<keyfile>",
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type outputGenerate struct {
|
type outputGenerate struct {
|
||||||
|
@ -35,17 +35,17 @@ type outputGenerate struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
privateKeyFlag = cli.StringFlag{
|
privateKeyFlag = &cli.StringFlag{
|
||||||
Name: "privatekey",
|
Name: "privatekey",
|
||||||
Usage: "file containing a raw private key to encrypt",
|
Usage: "file containing a raw private key to encrypt",
|
||||||
}
|
}
|
||||||
lightKDFFlag = cli.BoolFlag{
|
lightKDFFlag = &cli.BoolFlag{
|
||||||
Name: "lightkdf",
|
Name: "lightkdf",
|
||||||
Usage: "use less secure scrypt parameters",
|
Usage: "use less secure scrypt parameters",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var commandGenerate = cli.Command{
|
var commandGenerate = &cli.Command{
|
||||||
Name: "generate",
|
Name: "generate",
|
||||||
Usage: "generate new keyfile",
|
Usage: "generate new keyfile",
|
||||||
ArgsUsage: "[ <keyfile> ]",
|
ArgsUsage: "[ <keyfile> ]",
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type outputInspect struct {
|
type outputInspect struct {
|
||||||
|
@ -34,13 +34,13 @@ type outputInspect struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
privateFlag = cli.BoolFlag{
|
privateFlag = &cli.BoolFlag{
|
||||||
Name: "private",
|
Name: "private",
|
||||||
Usage: "include the private key in the output",
|
Usage: "include the private key in the output",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var commandInspect = cli.Command{
|
var commandInspect = &cli.Command{
|
||||||
Name: "inspect",
|
Name: "inspect",
|
||||||
Usage: "inspect a keyfile",
|
Usage: "inspect a keyfile",
|
||||||
ArgsUsage: "<keyfile>",
|
ArgsUsage: "<keyfile>",
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -36,23 +36,22 @@ var app *cli.App
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app = flags.NewApp(gitCommit, gitDate, "an Ethereum key manager")
|
app = flags.NewApp(gitCommit, gitDate, "an Ethereum key manager")
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
commandGenerate,
|
commandGenerate,
|
||||||
commandInspect,
|
commandInspect,
|
||||||
commandChangePassphrase,
|
commandChangePassphrase,
|
||||||
commandSignMessage,
|
commandSignMessage,
|
||||||
commandVerifyMessage,
|
commandVerifyMessage,
|
||||||
}
|
}
|
||||||
cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commonly used command line flags.
|
// Commonly used command line flags.
|
||||||
var (
|
var (
|
||||||
passphraseFlag = cli.StringFlag{
|
passphraseFlag = &cli.StringFlag{
|
||||||
Name: "passwordfile",
|
Name: "passwordfile",
|
||||||
Usage: "the file that contains the password for the keyfile",
|
Usage: "the file that contains the password for the keyfile",
|
||||||
}
|
}
|
||||||
jsonFlag = cli.BoolFlag{
|
jsonFlag = &cli.BoolFlag{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Usage: "output JSON instead of human-readable format",
|
Usage: "output JSON instead of human-readable format",
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,19 +26,19 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type outputSign struct {
|
type outputSign struct {
|
||||||
Signature string
|
Signature string
|
||||||
}
|
}
|
||||||
|
|
||||||
var msgfileFlag = cli.StringFlag{
|
var msgfileFlag = &cli.StringFlag{
|
||||||
Name: "msgfile",
|
Name: "msgfile",
|
||||||
Usage: "file containing the message to sign/verify",
|
Usage: "file containing the message to sign/verify",
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandSignMessage = cli.Command{
|
var commandSignMessage = &cli.Command{
|
||||||
Name: "signmessage",
|
Name: "signmessage",
|
||||||
Usage: "sign a message",
|
Usage: "sign a message",
|
||||||
ArgsUsage: "<keyfile> <message>",
|
ArgsUsage: "<keyfile> <message>",
|
||||||
|
@ -89,7 +89,7 @@ type outputVerify struct {
|
||||||
RecoveredPublicKey string
|
RecoveredPublicKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandVerifyMessage = cli.Command{
|
var commandVerifyMessage = &cli.Command{
|
||||||
Name: "verifymessage",
|
Name: "verifymessage",
|
||||||
Usage: "verify the signature of a signed message",
|
Usage: "verify the signature of a signed message",
|
||||||
ArgsUsage: "<address> <signature> <message>",
|
ArgsUsage: "<address> <signature> <message>",
|
||||||
|
@ -144,7 +144,7 @@ It is possible to refer to a file containing the message.`,
|
||||||
|
|
||||||
func getMessage(ctx *cli.Context, msgarg int) []byte {
|
func getMessage(ctx *cli.Context, msgarg int) []byte {
|
||||||
if file := ctx.String(msgfileFlag.Name); file != "" {
|
if file := ctx.String(msgfileFlag.Name); file != "" {
|
||||||
if len(ctx.Args()) > msgarg {
|
if ctx.NArg() > msgarg {
|
||||||
utils.Fatalf("Can't use --msgfile and message argument at the same time.")
|
utils.Fatalf("Can't use --msgfile and message argument at the same time.")
|
||||||
}
|
}
|
||||||
msg, err := os.ReadFile(file)
|
msg, err := os.ReadFile(file)
|
||||||
|
@ -152,9 +152,9 @@ func getMessage(ctx *cli.Context, msgarg int) []byte {
|
||||||
utils.Fatalf("Can't read message file: %v", err)
|
utils.Fatalf("Can't read message file: %v", err)
|
||||||
}
|
}
|
||||||
return msg
|
return msg
|
||||||
} else if len(ctx.Args()) == msgarg+1 {
|
} else if ctx.NArg() == msgarg+1 {
|
||||||
return []byte(ctx.Args().Get(msgarg))
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getPassphrase obtains a passphrase given by the user. It first checks the
|
// getPassphrase obtains a passphrase given by the user. It first checks the
|
||||||
|
|
|
@ -23,10 +23,10 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
|
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
|
||||||
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var compileCommand = cli.Command{
|
var compileCommand = &cli.Command{
|
||||||
Action: compileCmd,
|
Action: compileCmd,
|
||||||
Name: "compile",
|
Name: "compile",
|
||||||
Usage: "compiles easm source to evm binary",
|
Usage: "compiles easm source to evm binary",
|
||||||
|
@ -34,7 +34,7 @@ var compileCommand = cli.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileCmd(ctx *cli.Context) error {
|
func compileCmd(ctx *cli.Context) error {
|
||||||
debug := ctx.GlobalBool(DebugFlag.Name)
|
debug := ctx.Bool(DebugFlag.Name)
|
||||||
|
|
||||||
if len(ctx.Args().First()) == 0 {
|
if len(ctx.Args().First()) == 0 {
|
||||||
return errors.New("filename required")
|
return errors.New("filename required")
|
||||||
|
|
|
@ -23,10 +23,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/asm"
|
"github.com/ethereum/go-ethereum/core/asm"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var disasmCommand = cli.Command{
|
var disasmCommand = &cli.Command{
|
||||||
Action: disasmCmd,
|
Action: disasmCmd,
|
||||||
Name: "disasm",
|
Name: "disasm",
|
||||||
Usage: "disassembles evm binary",
|
Usage: "disassembles evm binary",
|
||||||
|
@ -43,8 +43,8 @@ func disasmCmd(ctx *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
in = string(input)
|
in = string(input)
|
||||||
case ctx.GlobalIsSet(InputFlag.Name):
|
case ctx.IsSet(InputFlag.Name):
|
||||||
in = ctx.GlobalString(InputFlag.Name)
|
in = ctx.String(InputFlag.Name)
|
||||||
default:
|
default:
|
||||||
return errors.New("missing filename or --input value")
|
return errors.New("missing filename or --input value")
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go
|
//go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go
|
||||||
|
|
|
@ -22,45 +22,47 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
TraceFlag = cli.BoolFlag{
|
TraceFlag = &cli.BoolFlag{
|
||||||
Name: "trace",
|
Name: "trace",
|
||||||
Usage: "Output full trace logs to files <txhash>.jsonl",
|
Usage: "Output full trace logs to files <txhash>.jsonl",
|
||||||
}
|
}
|
||||||
TraceDisableMemoryFlag = cli.BoolTFlag{
|
TraceDisableMemoryFlag = &cli.BoolFlag{
|
||||||
Name: "trace.nomemory",
|
Name: "trace.nomemory",
|
||||||
|
Value: true,
|
||||||
Usage: "Disable full memory dump in traces (deprecated)",
|
Usage: "Disable full memory dump in traces (deprecated)",
|
||||||
}
|
}
|
||||||
TraceEnableMemoryFlag = cli.BoolFlag{
|
TraceEnableMemoryFlag = &cli.BoolFlag{
|
||||||
Name: "trace.memory",
|
Name: "trace.memory",
|
||||||
Usage: "Enable full memory dump in traces",
|
Usage: "Enable full memory dump in traces",
|
||||||
}
|
}
|
||||||
TraceDisableStackFlag = cli.BoolFlag{
|
TraceDisableStackFlag = &cli.BoolFlag{
|
||||||
Name: "trace.nostack",
|
Name: "trace.nostack",
|
||||||
Usage: "Disable stack output in traces",
|
Usage: "Disable stack output in traces",
|
||||||
}
|
}
|
||||||
TraceDisableReturnDataFlag = cli.BoolTFlag{
|
TraceDisableReturnDataFlag = &cli.BoolFlag{
|
||||||
Name: "trace.noreturndata",
|
Name: "trace.noreturndata",
|
||||||
|
Value: true,
|
||||||
Usage: "Disable return data output in traces (deprecated)",
|
Usage: "Disable return data output in traces (deprecated)",
|
||||||
}
|
}
|
||||||
TraceEnableReturnDataFlag = cli.BoolFlag{
|
TraceEnableReturnDataFlag = &cli.BoolFlag{
|
||||||
Name: "trace.returndata",
|
Name: "trace.returndata",
|
||||||
Usage: "Enable return data output in traces",
|
Usage: "Enable return data output in traces",
|
||||||
}
|
}
|
||||||
OutputBasedir = cli.StringFlag{
|
OutputBasedir = &cli.StringFlag{
|
||||||
Name: "output.basedir",
|
Name: "output.basedir",
|
||||||
Usage: "Specifies where output files are placed. Will be created if it does not exist.",
|
Usage: "Specifies where output files are placed. Will be created if it does not exist.",
|
||||||
Value: "",
|
Value: "",
|
||||||
}
|
}
|
||||||
OutputBodyFlag = cli.StringFlag{
|
OutputBodyFlag = &cli.StringFlag{
|
||||||
Name: "output.body",
|
Name: "output.body",
|
||||||
Usage: "If set, the RLP of the transactions (block body) will be written to this file.",
|
Usage: "If set, the RLP of the transactions (block body) will be written to this file.",
|
||||||
Value: "",
|
Value: "",
|
||||||
}
|
}
|
||||||
OutputAllocFlag = cli.StringFlag{
|
OutputAllocFlag = &cli.StringFlag{
|
||||||
Name: "output.alloc",
|
Name: "output.alloc",
|
||||||
Usage: "Determines where to put the `alloc` of the post-state.\n" +
|
Usage: "Determines where to put the `alloc` of the post-state.\n" +
|
||||||
"\t`stdout` - into the stdout output\n" +
|
"\t`stdout` - into the stdout output\n" +
|
||||||
|
@ -68,7 +70,7 @@ var (
|
||||||
"\t<file> - into the file <file> ",
|
"\t<file> - into the file <file> ",
|
||||||
Value: "alloc.json",
|
Value: "alloc.json",
|
||||||
}
|
}
|
||||||
OutputResultFlag = cli.StringFlag{
|
OutputResultFlag = &cli.StringFlag{
|
||||||
Name: "output.result",
|
Name: "output.result",
|
||||||
Usage: "Determines where to put the `result` (stateroot, txroot etc) of the post-state.\n" +
|
Usage: "Determines where to put the `result` (stateroot, txroot etc) of the post-state.\n" +
|
||||||
"\t`stdout` - into the stdout output\n" +
|
"\t`stdout` - into the stdout output\n" +
|
||||||
|
@ -76,7 +78,7 @@ var (
|
||||||
"\t<file> - into the file <file> ",
|
"\t<file> - into the file <file> ",
|
||||||
Value: "result.json",
|
Value: "result.json",
|
||||||
}
|
}
|
||||||
OutputBlockFlag = cli.StringFlag{
|
OutputBlockFlag = &cli.StringFlag{
|
||||||
Name: "output.block",
|
Name: "output.block",
|
||||||
Usage: "Determines where to put the `block` after building.\n" +
|
Usage: "Determines where to put the `block` after building.\n" +
|
||||||
"\t`stdout` - into the stdout output\n" +
|
"\t`stdout` - into the stdout output\n" +
|
||||||
|
@ -84,65 +86,65 @@ var (
|
||||||
"\t<file> - into the file <file> ",
|
"\t<file> - into the file <file> ",
|
||||||
Value: "block.json",
|
Value: "block.json",
|
||||||
}
|
}
|
||||||
InputAllocFlag = cli.StringFlag{
|
InputAllocFlag = &cli.StringFlag{
|
||||||
Name: "input.alloc",
|
Name: "input.alloc",
|
||||||
Usage: "`stdin` or file name of where to find the prestate alloc to use.",
|
Usage: "`stdin` or file name of where to find the prestate alloc to use.",
|
||||||
Value: "alloc.json",
|
Value: "alloc.json",
|
||||||
}
|
}
|
||||||
InputEnvFlag = cli.StringFlag{
|
InputEnvFlag = &cli.StringFlag{
|
||||||
Name: "input.env",
|
Name: "input.env",
|
||||||
Usage: "`stdin` or file name of where to find the prestate env to use.",
|
Usage: "`stdin` or file name of where to find the prestate env to use.",
|
||||||
Value: "env.json",
|
Value: "env.json",
|
||||||
}
|
}
|
||||||
InputTxsFlag = cli.StringFlag{
|
InputTxsFlag = &cli.StringFlag{
|
||||||
Name: "input.txs",
|
Name: "input.txs",
|
||||||
Usage: "`stdin` or file name of where to find the transactions to apply. " +
|
Usage: "`stdin` or file name of where to find the transactions to apply. " +
|
||||||
"If the file extension is '.rlp', then the data is interpreted as an RLP list of signed transactions." +
|
"If the file extension is '.rlp', then the data is interpreted as an RLP list of signed transactions." +
|
||||||
"The '.rlp' format is identical to the output.body format.",
|
"The '.rlp' format is identical to the output.body format.",
|
||||||
Value: "txs.json",
|
Value: "txs.json",
|
||||||
}
|
}
|
||||||
InputHeaderFlag = cli.StringFlag{
|
InputHeaderFlag = &cli.StringFlag{
|
||||||
Name: "input.header",
|
Name: "input.header",
|
||||||
Usage: "`stdin` or file name of where to find the block header to use.",
|
Usage: "`stdin` or file name of where to find the block header to use.",
|
||||||
Value: "header.json",
|
Value: "header.json",
|
||||||
}
|
}
|
||||||
InputOmmersFlag = cli.StringFlag{
|
InputOmmersFlag = &cli.StringFlag{
|
||||||
Name: "input.ommers",
|
Name: "input.ommers",
|
||||||
Usage: "`stdin` or file name of where to find the list of ommer header RLPs to use.",
|
Usage: "`stdin` or file name of where to find the list of ommer header RLPs to use.",
|
||||||
}
|
}
|
||||||
InputTxsRlpFlag = cli.StringFlag{
|
InputTxsRlpFlag = &cli.StringFlag{
|
||||||
Name: "input.txs",
|
Name: "input.txs",
|
||||||
Usage: "`stdin` or file name of where to find the transactions list in RLP form.",
|
Usage: "`stdin` or file name of where to find the transactions list in RLP form.",
|
||||||
Value: "txs.rlp",
|
Value: "txs.rlp",
|
||||||
}
|
}
|
||||||
SealCliqueFlag = cli.StringFlag{
|
SealCliqueFlag = &cli.StringFlag{
|
||||||
Name: "seal.clique",
|
Name: "seal.clique",
|
||||||
Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.",
|
Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.",
|
||||||
}
|
}
|
||||||
SealEthashFlag = cli.BoolFlag{
|
SealEthashFlag = &cli.BoolFlag{
|
||||||
Name: "seal.ethash",
|
Name: "seal.ethash",
|
||||||
Usage: "Seal block with ethash.",
|
Usage: "Seal block with ethash.",
|
||||||
}
|
}
|
||||||
SealEthashDirFlag = cli.StringFlag{
|
SealEthashDirFlag = &cli.StringFlag{
|
||||||
Name: "seal.ethash.dir",
|
Name: "seal.ethash.dir",
|
||||||
Usage: "Path to ethash DAG. If none exists, a new DAG will be generated.",
|
Usage: "Path to ethash DAG. If none exists, a new DAG will be generated.",
|
||||||
}
|
}
|
||||||
SealEthashModeFlag = cli.StringFlag{
|
SealEthashModeFlag = &cli.StringFlag{
|
||||||
Name: "seal.ethash.mode",
|
Name: "seal.ethash.mode",
|
||||||
Usage: "Defines the type and amount of PoW verification an ethash engine makes.",
|
Usage: "Defines the type and amount of PoW verification an ethash engine makes.",
|
||||||
Value: "normal",
|
Value: "normal",
|
||||||
}
|
}
|
||||||
RewardFlag = cli.Int64Flag{
|
RewardFlag = &cli.Int64Flag{
|
||||||
Name: "state.reward",
|
Name: "state.reward",
|
||||||
Usage: "Mining reward. Set to -1 to disable",
|
Usage: "Mining reward. Set to -1 to disable",
|
||||||
Value: 0,
|
Value: 0,
|
||||||
}
|
}
|
||||||
ChainIDFlag = cli.Int64Flag{
|
ChainIDFlag = &cli.Int64Flag{
|
||||||
Name: "state.chainid",
|
Name: "state.chainid",
|
||||||
Usage: "ChainID to use",
|
Usage: "ChainID to use",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
}
|
}
|
||||||
ForknameFlag = cli.StringFlag{
|
ForknameFlag = &cli.StringFlag{
|
||||||
Name: "state.fork",
|
Name: "state.fork",
|
||||||
Usage: fmt.Sprintf("Name of ruleset to use."+
|
Usage: fmt.Sprintf("Name of ruleset to use."+
|
||||||
"\n\tAvailable forknames:"+
|
"\n\tAvailable forknames:"+
|
||||||
|
@ -154,7 +156,7 @@ var (
|
||||||
strings.Join(vm.ActivateableEips(), ", ")),
|
strings.Join(vm.ActivateableEips(), ", ")),
|
||||||
Value: "GrayGlacier",
|
Value: "GrayGlacier",
|
||||||
}
|
}
|
||||||
VerbosityFlag = cli.IntFlag{
|
VerbosityFlag = &cli.IntFlag{
|
||||||
Name: "verbosity",
|
Name: "verbosity",
|
||||||
Usage: "sets the verbosity level",
|
Usage: "sets the verbosity level",
|
||||||
Value: 3,
|
Value: 3,
|
||||||
|
|
|
@ -32,7 +32,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
|
|
|
@ -38,7 +38,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// readFile reads the json-data in the provided path and marshals into dest.
|
// readFile reads the json-data in the provided path and marshals into dest.
|
||||||
|
|
|
@ -23,115 +23,118 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
|
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
|
var (
|
||||||
var gitDate = ""
|
gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
|
||||||
|
gitDate = ""
|
||||||
|
|
||||||
|
app = flags.NewApp(gitCommit, gitDate, "the evm command line interface")
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
app = flags.NewApp(gitCommit, gitDate, "the evm command line interface")
|
DebugFlag = &cli.BoolFlag{
|
||||||
|
|
||||||
DebugFlag = cli.BoolFlag{
|
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
Usage: "output full trace logs",
|
Usage: "output full trace logs",
|
||||||
}
|
}
|
||||||
MemProfileFlag = cli.StringFlag{
|
MemProfileFlag = &cli.StringFlag{
|
||||||
Name: "memprofile",
|
Name: "memprofile",
|
||||||
Usage: "creates a memory profile at the given path",
|
Usage: "creates a memory profile at the given path",
|
||||||
}
|
}
|
||||||
CPUProfileFlag = cli.StringFlag{
|
CPUProfileFlag = &cli.StringFlag{
|
||||||
Name: "cpuprofile",
|
Name: "cpuprofile",
|
||||||
Usage: "creates a CPU profile at the given path",
|
Usage: "creates a CPU profile at the given path",
|
||||||
}
|
}
|
||||||
StatDumpFlag = cli.BoolFlag{
|
StatDumpFlag = &cli.BoolFlag{
|
||||||
Name: "statdump",
|
Name: "statdump",
|
||||||
Usage: "displays stack and heap memory information",
|
Usage: "displays stack and heap memory information",
|
||||||
}
|
}
|
||||||
CodeFlag = cli.StringFlag{
|
CodeFlag = &cli.StringFlag{
|
||||||
Name: "code",
|
Name: "code",
|
||||||
Usage: "EVM code",
|
Usage: "EVM code",
|
||||||
}
|
}
|
||||||
CodeFileFlag = cli.StringFlag{
|
CodeFileFlag = &cli.StringFlag{
|
||||||
Name: "codefile",
|
Name: "codefile",
|
||||||
Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
|
Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
|
||||||
}
|
}
|
||||||
GasFlag = cli.Uint64Flag{
|
GasFlag = &cli.Uint64Flag{
|
||||||
Name: "gas",
|
Name: "gas",
|
||||||
Usage: "gas limit for the evm",
|
Usage: "gas limit for the evm",
|
||||||
Value: 10000000000,
|
Value: 10000000000,
|
||||||
}
|
}
|
||||||
PriceFlag = utils.BigFlag{
|
PriceFlag = &flags.BigFlag{
|
||||||
Name: "price",
|
Name: "price",
|
||||||
Usage: "price set for the evm",
|
Usage: "price set for the evm",
|
||||||
Value: new(big.Int),
|
Value: new(big.Int),
|
||||||
}
|
}
|
||||||
ValueFlag = utils.BigFlag{
|
ValueFlag = &flags.BigFlag{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
Usage: "value set for the evm",
|
Usage: "value set for the evm",
|
||||||
Value: new(big.Int),
|
Value: new(big.Int),
|
||||||
}
|
}
|
||||||
DumpFlag = cli.BoolFlag{
|
DumpFlag = &cli.BoolFlag{
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "dumps the state after the run",
|
Usage: "dumps the state after the run",
|
||||||
}
|
}
|
||||||
InputFlag = cli.StringFlag{
|
InputFlag = &cli.StringFlag{
|
||||||
Name: "input",
|
Name: "input",
|
||||||
Usage: "input for the EVM",
|
Usage: "input for the EVM",
|
||||||
}
|
}
|
||||||
InputFileFlag = cli.StringFlag{
|
InputFileFlag = &cli.StringFlag{
|
||||||
Name: "inputfile",
|
Name: "inputfile",
|
||||||
Usage: "file containing input for the EVM",
|
Usage: "file containing input for the EVM",
|
||||||
}
|
}
|
||||||
VerbosityFlag = cli.IntFlag{
|
VerbosityFlag = &cli.IntFlag{
|
||||||
Name: "verbosity",
|
Name: "verbosity",
|
||||||
Usage: "sets the verbosity level",
|
Usage: "sets the verbosity level",
|
||||||
}
|
}
|
||||||
BenchFlag = cli.BoolFlag{
|
BenchFlag = &cli.BoolFlag{
|
||||||
Name: "bench",
|
Name: "bench",
|
||||||
Usage: "benchmark the execution",
|
Usage: "benchmark the execution",
|
||||||
}
|
}
|
||||||
CreateFlag = cli.BoolFlag{
|
CreateFlag = &cli.BoolFlag{
|
||||||
Name: "create",
|
Name: "create",
|
||||||
Usage: "indicates the action should be create rather than call",
|
Usage: "indicates the action should be create rather than call",
|
||||||
}
|
}
|
||||||
GenesisFlag = cli.StringFlag{
|
GenesisFlag = &cli.StringFlag{
|
||||||
Name: "prestate",
|
Name: "prestate",
|
||||||
Usage: "JSON file with prestate (genesis) config",
|
Usage: "JSON file with prestate (genesis) config",
|
||||||
}
|
}
|
||||||
MachineFlag = cli.BoolFlag{
|
MachineFlag = &cli.BoolFlag{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Usage: "output trace logs in machine readable format (json)",
|
Usage: "output trace logs in machine readable format (json)",
|
||||||
}
|
}
|
||||||
SenderFlag = cli.StringFlag{
|
SenderFlag = &cli.StringFlag{
|
||||||
Name: "sender",
|
Name: "sender",
|
||||||
Usage: "The transaction origin",
|
Usage: "The transaction origin",
|
||||||
}
|
}
|
||||||
ReceiverFlag = cli.StringFlag{
|
ReceiverFlag = &cli.StringFlag{
|
||||||
Name: "receiver",
|
Name: "receiver",
|
||||||
Usage: "The transaction receiver (execution context)",
|
Usage: "The transaction receiver (execution context)",
|
||||||
}
|
}
|
||||||
DisableMemoryFlag = cli.BoolTFlag{
|
DisableMemoryFlag = &cli.BoolFlag{
|
||||||
Name: "nomemory",
|
Name: "nomemory",
|
||||||
|
Value: true,
|
||||||
Usage: "disable memory output",
|
Usage: "disable memory output",
|
||||||
}
|
}
|
||||||
DisableStackFlag = cli.BoolFlag{
|
DisableStackFlag = &cli.BoolFlag{
|
||||||
Name: "nostack",
|
Name: "nostack",
|
||||||
Usage: "disable stack output",
|
Usage: "disable stack output",
|
||||||
}
|
}
|
||||||
DisableStorageFlag = cli.BoolFlag{
|
DisableStorageFlag = &cli.BoolFlag{
|
||||||
Name: "nostorage",
|
Name: "nostorage",
|
||||||
Usage: "disable storage output",
|
Usage: "disable storage output",
|
||||||
}
|
}
|
||||||
DisableReturnDataFlag = cli.BoolTFlag{
|
DisableReturnDataFlag = &cli.BoolFlag{
|
||||||
Name: "noreturndata",
|
Name: "noreturndata",
|
||||||
|
Value: true,
|
||||||
Usage: "enable return data output",
|
Usage: "enable return data output",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var stateTransitionCommand = cli.Command{
|
var stateTransitionCommand = &cli.Command{
|
||||||
Name: "transition",
|
Name: "transition",
|
||||||
Aliases: []string{"t8n"},
|
Aliases: []string{"t8n"},
|
||||||
Usage: "executes a full state transition",
|
Usage: "executes a full state transition",
|
||||||
|
@ -156,7 +159,8 @@ var stateTransitionCommand = cli.Command{
|
||||||
t8ntool.VerbosityFlag,
|
t8ntool.VerbosityFlag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
var transactionCommand = cli.Command{
|
|
||||||
|
var transactionCommand = &cli.Command{
|
||||||
Name: "transaction",
|
Name: "transaction",
|
||||||
Aliases: []string{"t9n"},
|
Aliases: []string{"t9n"},
|
||||||
Usage: "performs transaction validation",
|
Usage: "performs transaction validation",
|
||||||
|
@ -169,7 +173,7 @@ var transactionCommand = cli.Command{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var blockBuilderCommand = cli.Command{
|
var blockBuilderCommand = &cli.Command{
|
||||||
Name: "block-builder",
|
Name: "block-builder",
|
||||||
Aliases: []string{"b11r"},
|
Aliases: []string{"b11r"},
|
||||||
Usage: "builds a block",
|
Usage: "builds a block",
|
||||||
|
@ -214,7 +218,7 @@ func init() {
|
||||||
DisableStorageFlag,
|
DisableStorageFlag,
|
||||||
DisableReturnDataFlag,
|
DisableReturnDataFlag,
|
||||||
}
|
}
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
compileCommand,
|
compileCommand,
|
||||||
disasmCommand,
|
disasmCommand,
|
||||||
runCommand,
|
runCommand,
|
||||||
|
@ -223,7 +227,6 @@ func init() {
|
||||||
transactionCommand,
|
transactionCommand,
|
||||||
blockBuilderCommand,
|
blockBuilderCommand,
|
||||||
}
|
}
|
||||||
cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
@ -37,12 +37,13 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/core/vm/runtime"
|
"github.com/ethereum/go-ethereum/core/vm/runtime"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var runCommand = cli.Command{
|
var runCommand = &cli.Command{
|
||||||
Action: runCmd,
|
Action: runCmd,
|
||||||
Name: "run",
|
Name: "run",
|
||||||
Usage: "run arbitrary evm binary",
|
Usage: "run arbitrary evm binary",
|
||||||
|
@ -106,14 +107,14 @@ func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []by
|
||||||
|
|
||||||
func runCmd(ctx *cli.Context) error {
|
func runCmd(ctx *cli.Context) error {
|
||||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
||||||
glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name)))
|
glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
|
||||||
log.Root().SetHandler(glogger)
|
log.Root().SetHandler(glogger)
|
||||||
logconfig := &logger.Config{
|
logconfig := &logger.Config{
|
||||||
EnableMemory: !ctx.GlobalBool(DisableMemoryFlag.Name),
|
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
|
||||||
DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
|
DisableStack: ctx.Bool(DisableStackFlag.Name),
|
||||||
DisableStorage: ctx.GlobalBool(DisableStorageFlag.Name),
|
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
|
||||||
EnableReturnData: !ctx.GlobalBool(DisableReturnDataFlag.Name),
|
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
|
||||||
Debug: ctx.GlobalBool(DebugFlag.Name),
|
Debug: ctx.Bool(DebugFlag.Name),
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -125,16 +126,16 @@ func runCmd(ctx *cli.Context) error {
|
||||||
receiver = common.BytesToAddress([]byte("receiver"))
|
receiver = common.BytesToAddress([]byte("receiver"))
|
||||||
genesisConfig *core.Genesis
|
genesisConfig *core.Genesis
|
||||||
)
|
)
|
||||||
if ctx.GlobalBool(MachineFlag.Name) {
|
if ctx.Bool(MachineFlag.Name) {
|
||||||
tracer = logger.NewJSONLogger(logconfig, os.Stdout)
|
tracer = logger.NewJSONLogger(logconfig, os.Stdout)
|
||||||
} else if ctx.GlobalBool(DebugFlag.Name) {
|
} else if ctx.Bool(DebugFlag.Name) {
|
||||||
debugLogger = logger.NewStructLogger(logconfig)
|
debugLogger = logger.NewStructLogger(logconfig)
|
||||||
tracer = debugLogger
|
tracer = debugLogger
|
||||||
} else {
|
} else {
|
||||||
debugLogger = logger.NewStructLogger(logconfig)
|
debugLogger = logger.NewStructLogger(logconfig)
|
||||||
}
|
}
|
||||||
if ctx.GlobalString(GenesisFlag.Name) != "" {
|
if ctx.String(GenesisFlag.Name) != "" {
|
||||||
gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
|
gen := readGenesis(ctx.String(GenesisFlag.Name))
|
||||||
genesisConfig = gen
|
genesisConfig = gen
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
genesis := gen.ToBlock(db)
|
genesis := gen.ToBlock(db)
|
||||||
|
@ -144,18 +145,18 @@ func runCmd(ctx *cli.Context) error {
|
||||||
statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||||
genesisConfig = new(core.Genesis)
|
genesisConfig = new(core.Genesis)
|
||||||
}
|
}
|
||||||
if ctx.GlobalString(SenderFlag.Name) != "" {
|
if ctx.String(SenderFlag.Name) != "" {
|
||||||
sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name))
|
sender = common.HexToAddress(ctx.String(SenderFlag.Name))
|
||||||
}
|
}
|
||||||
statedb.CreateAccount(sender)
|
statedb.CreateAccount(sender)
|
||||||
|
|
||||||
if ctx.GlobalString(ReceiverFlag.Name) != "" {
|
if ctx.String(ReceiverFlag.Name) != "" {
|
||||||
receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name))
|
receiver = common.HexToAddress(ctx.String(ReceiverFlag.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
var code []byte
|
var code []byte
|
||||||
codeFileFlag := ctx.GlobalString(CodeFileFlag.Name)
|
codeFileFlag := ctx.String(CodeFileFlag.Name)
|
||||||
codeFlag := ctx.GlobalString(CodeFlag.Name)
|
codeFlag := ctx.String(CodeFlag.Name)
|
||||||
|
|
||||||
// The '--code' or '--codefile' flag overrides code in state
|
// The '--code' or '--codefile' flag overrides code in state
|
||||||
if codeFileFlag != "" || codeFlag != "" {
|
if codeFileFlag != "" || codeFlag != "" {
|
||||||
|
@ -197,7 +198,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
code = common.Hex2Bytes(bin)
|
code = common.Hex2Bytes(bin)
|
||||||
}
|
}
|
||||||
initialGas := ctx.GlobalUint64(GasFlag.Name)
|
initialGas := ctx.Uint64(GasFlag.Name)
|
||||||
if genesisConfig.GasLimit != 0 {
|
if genesisConfig.GasLimit != 0 {
|
||||||
initialGas = genesisConfig.GasLimit
|
initialGas = genesisConfig.GasLimit
|
||||||
}
|
}
|
||||||
|
@ -205,19 +206,19 @@ func runCmd(ctx *cli.Context) error {
|
||||||
Origin: sender,
|
Origin: sender,
|
||||||
State: statedb,
|
State: statedb,
|
||||||
GasLimit: initialGas,
|
GasLimit: initialGas,
|
||||||
GasPrice: utils.GlobalBig(ctx, PriceFlag.Name),
|
GasPrice: flags.GlobalBig(ctx, PriceFlag.Name),
|
||||||
Value: utils.GlobalBig(ctx, ValueFlag.Name),
|
Value: flags.GlobalBig(ctx, ValueFlag.Name),
|
||||||
Difficulty: genesisConfig.Difficulty,
|
Difficulty: genesisConfig.Difficulty,
|
||||||
Time: new(big.Int).SetUint64(genesisConfig.Timestamp),
|
Time: new(big.Int).SetUint64(genesisConfig.Timestamp),
|
||||||
Coinbase: genesisConfig.Coinbase,
|
Coinbase: genesisConfig.Coinbase,
|
||||||
BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
|
BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
|
||||||
EVMConfig: vm.Config{
|
EVMConfig: vm.Config{
|
||||||
Tracer: tracer,
|
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)
|
f, err := os.Create(cpuProfilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("could not create CPU profile: ", err)
|
fmt.Println("could not create CPU profile: ", err)
|
||||||
|
@ -237,14 +238,14 @@ func runCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var hexInput []byte
|
var hexInput []byte
|
||||||
if inputFileFlag := ctx.GlobalString(InputFileFlag.Name); inputFileFlag != "" {
|
if inputFileFlag := ctx.String(InputFileFlag.Name); inputFileFlag != "" {
|
||||||
var err error
|
var err error
|
||||||
if hexInput, err = os.ReadFile(inputFileFlag); err != nil {
|
if hexInput, err = os.ReadFile(inputFileFlag); err != nil {
|
||||||
fmt.Printf("could not load input from file: %v\n", err)
|
fmt.Printf("could not load input from file: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hexInput = []byte(ctx.GlobalString(InputFlag.Name))
|
hexInput = []byte(ctx.String(InputFlag.Name))
|
||||||
}
|
}
|
||||||
hexInput = bytes.TrimSpace(hexInput)
|
hexInput = bytes.TrimSpace(hexInput)
|
||||||
if len(hexInput)%2 != 0 {
|
if len(hexInput)%2 != 0 {
|
||||||
|
@ -254,7 +255,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
input := common.FromHex(string(hexInput))
|
input := common.FromHex(string(hexInput))
|
||||||
|
|
||||||
var execFunc func() ([]byte, uint64, error)
|
var execFunc func() ([]byte, uint64, error)
|
||||||
if ctx.GlobalBool(CreateFlag.Name) {
|
if ctx.Bool(CreateFlag.Name) {
|
||||||
input = append(code, input...)
|
input = append(code, input...)
|
||||||
execFunc = func() ([]byte, uint64, error) {
|
execFunc = func() ([]byte, uint64, error) {
|
||||||
output, _, gasLeft, err := runtime.Create(input, &runtimeConfig)
|
output, _, gasLeft, err := runtime.Create(input, &runtimeConfig)
|
||||||
|
@ -269,16 +270,16 @@ func runCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bench := ctx.GlobalBool(BenchFlag.Name)
|
bench := ctx.Bool(BenchFlag.Name)
|
||||||
output, leftOverGas, stats, err := timedExec(bench, execFunc)
|
output, leftOverGas, stats, err := timedExec(bench, execFunc)
|
||||||
|
|
||||||
if ctx.GlobalBool(DumpFlag.Name) {
|
if ctx.Bool(DumpFlag.Name) {
|
||||||
statedb.Commit(true)
|
statedb.Commit(true)
|
||||||
statedb.IntermediateRoot(true)
|
statedb.IntermediateRoot(true)
|
||||||
fmt.Println(string(statedb.Dump(nil)))
|
fmt.Println(string(statedb.Dump(nil)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if memProfilePath := ctx.GlobalString(MemProfileFlag.Name); memProfilePath != "" {
|
if memProfilePath := ctx.String(MemProfileFlag.Name); memProfilePath != "" {
|
||||||
f, err := os.Create(memProfilePath)
|
f, err := os.Create(memProfilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("could not create memory profile: ", err)
|
fmt.Println("could not create memory profile: ", err)
|
||||||
|
@ -291,7 +292,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.GlobalBool(DebugFlag.Name) {
|
if ctx.Bool(DebugFlag.Name) {
|
||||||
if debugLogger != nil {
|
if debugLogger != nil {
|
||||||
fmt.Fprintln(os.Stderr, "#### TRACE ####")
|
fmt.Fprintln(os.Stderr, "#### TRACE ####")
|
||||||
logger.WriteTrace(os.Stderr, debugLogger.StructLogs())
|
logger.WriteTrace(os.Stderr, debugLogger.StructLogs())
|
||||||
|
@ -300,7 +301,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
logger.WriteLogs(os.Stderr, statedb.Logs())
|
logger.WriteLogs(os.Stderr, statedb.Logs())
|
||||||
}
|
}
|
||||||
|
|
||||||
if bench || ctx.GlobalBool(StatDumpFlag.Name) {
|
if bench || ctx.Bool(StatDumpFlag.Name) {
|
||||||
fmt.Fprintf(os.Stderr, `EVM gas used: %d
|
fmt.Fprintf(os.Stderr, `EVM gas used: %d
|
||||||
execution time: %v
|
execution time: %v
|
||||||
allocations: %d
|
allocations: %d
|
||||||
|
|
|
@ -28,10 +28,10 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var stateTestCommand = cli.Command{
|
var stateTestCommand = &cli.Command{
|
||||||
Action: stateTestCmd,
|
Action: stateTestCmd,
|
||||||
Name: "statetest",
|
Name: "statetest",
|
||||||
Usage: "executes the given state tests",
|
Usage: "executes the given state tests",
|
||||||
|
@ -54,25 +54,25 @@ func stateTestCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
// Configure the go-ethereum logger
|
// Configure the go-ethereum logger
|
||||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
||||||
glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name)))
|
glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
|
||||||
log.Root().SetHandler(glogger)
|
log.Root().SetHandler(glogger)
|
||||||
|
|
||||||
// Configure the EVM logger
|
// Configure the EVM logger
|
||||||
config := &logger.Config{
|
config := &logger.Config{
|
||||||
EnableMemory: !ctx.GlobalBool(DisableMemoryFlag.Name),
|
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
|
||||||
DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
|
DisableStack: ctx.Bool(DisableStackFlag.Name),
|
||||||
DisableStorage: ctx.GlobalBool(DisableStorageFlag.Name),
|
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
|
||||||
EnableReturnData: !ctx.GlobalBool(DisableReturnDataFlag.Name),
|
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
tracer vm.EVMLogger
|
tracer vm.EVMLogger
|
||||||
debugger *logger.StructLogger
|
debugger *logger.StructLogger
|
||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
case ctx.GlobalBool(MachineFlag.Name):
|
case ctx.Bool(MachineFlag.Name):
|
||||||
tracer = logger.NewJSONLogger(config, os.Stderr)
|
tracer = logger.NewJSONLogger(config, os.Stderr)
|
||||||
|
|
||||||
case ctx.GlobalBool(DebugFlag.Name):
|
case ctx.Bool(DebugFlag.Name):
|
||||||
debugger = logger.NewStructLogger(config)
|
debugger = logger.NewStructLogger(config)
|
||||||
tracer = debugger
|
tracer = debugger
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ func stateTestCmd(ctx *cli.Context) error {
|
||||||
// Iterate over all the tests, run them and aggregate the results
|
// Iterate over all the tests, run them and aggregate the results
|
||||||
cfg := vm.Config{
|
cfg := vm.Config{
|
||||||
Tracer: tracer,
|
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))
|
results := make([]StatetestResult, 0, len(tests))
|
||||||
for key, test := range tests {
|
for key, test := range tests {
|
||||||
|
@ -100,13 +100,13 @@ func stateTestCmd(ctx *cli.Context) error {
|
||||||
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
|
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
|
||||||
_, s, err := test.Run(st, cfg, false)
|
_, s, err := test.Run(st, cfg, false)
|
||||||
// print state root for evmlab tracing
|
// print state root for evmlab tracing
|
||||||
if ctx.GlobalBool(MachineFlag.Name) && s != nil {
|
if ctx.Bool(MachineFlag.Name) && s != nil {
|
||||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", s.IntermediateRoot(false))
|
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", s.IntermediateRoot(false))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Test failed, mark as so and dump any state to aid debugging
|
// Test failed, mark as so and dump any state to aid debugging
|
||||||
result.Pass, result.Error = false, err.Error()
|
result.Pass, result.Error = false, err.Error()
|
||||||
if ctx.GlobalBool(DumpFlag.Name) && s != nil {
|
if ctx.Bool(DumpFlag.Name) && s != nil {
|
||||||
dump := s.RawDump(nil)
|
dump := s.RawDump(nil)
|
||||||
result.State = &dump
|
result.State = &dump
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ func stateTestCmd(ctx *cli.Context) error {
|
||||||
results = append(results, *result)
|
results = append(results, *result)
|
||||||
|
|
||||||
// Print any structured logs collected
|
// Print any structured logs collected
|
||||||
if ctx.GlobalBool(DebugFlag.Name) {
|
if ctx.Bool(DebugFlag.Name) {
|
||||||
if debugger != nil {
|
if debugger != nil {
|
||||||
fmt.Fprintln(os.Stderr, "#### TRACE ####")
|
fmt.Fprintln(os.Stderr, "#### TRACE ####")
|
||||||
logger.WriteTrace(os.Stderr, debugger.StructLogs())
|
logger.WriteTrace(os.Stderr, debugger.StructLogs())
|
||||||
|
|
|
@ -25,29 +25,27 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
walletCommand = cli.Command{
|
walletCommand = &cli.Command{
|
||||||
Name: "wallet",
|
Name: "wallet",
|
||||||
Usage: "Manage Ethereum presale wallets",
|
Usage: "Manage Ethereum presale wallets",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Category: "ACCOUNT COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
geth wallet import /path/to/my/presale.wallet
|
geth wallet import /path/to/my/presale.wallet
|
||||||
|
|
||||||
will prompt for your password and imports your ether presale account.
|
will prompt for your password and imports your ether presale account.
|
||||||
It can be used non-interactively with the --password option taking a
|
It can be used non-interactively with the --password option taking a
|
||||||
passwordfile as argument containing the wallet password in plaintext.`,
|
passwordfile as argument containing the wallet password in plaintext.`,
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
{
|
{
|
||||||
|
|
||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Import Ethereum presale wallet",
|
Usage: "Import Ethereum presale wallet",
|
||||||
ArgsUsage: "<keyFile>",
|
ArgsUsage: "<keyFile>",
|
||||||
Action: utils.MigrateFlags(importWallet),
|
Action: importWallet,
|
||||||
Category: "ACCOUNT COMMANDS",
|
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
utils.KeyStoreDirFlag,
|
utils.KeyStoreDirFlag,
|
||||||
|
@ -64,10 +62,9 @@ passwordfile as argument containing the wallet password in plaintext.`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
accountCommand = cli.Command{
|
accountCommand = &cli.Command{
|
||||||
Name: "account",
|
Name: "account",
|
||||||
Usage: "Manage accounts",
|
Usage: "Manage accounts",
|
||||||
Category: "ACCOUNT COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
|
|
||||||
Manage accounts, list all existing accounts, import a private key into a new
|
Manage accounts, list all existing accounts, import a private key into a new
|
||||||
|
@ -88,11 +85,11 @@ It is safe to transfer the entire directory or the individual keys therein
|
||||||
between ethereum nodes by simply copying.
|
between ethereum nodes by simply copying.
|
||||||
|
|
||||||
Make sure you backup your keys regularly.`,
|
Make sure you backup your keys regularly.`,
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "Print summary of existing accounts",
|
Usage: "Print summary of existing accounts",
|
||||||
Action: utils.MigrateFlags(accountList),
|
Action: accountList,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
utils.KeyStoreDirFlag,
|
utils.KeyStoreDirFlag,
|
||||||
|
@ -103,7 +100,7 @@ Print a short summary of all accounts`,
|
||||||
{
|
{
|
||||||
Name: "new",
|
Name: "new",
|
||||||
Usage: "Create a new account",
|
Usage: "Create a new account",
|
||||||
Action: utils.MigrateFlags(accountCreate),
|
Action: accountCreate,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
utils.KeyStoreDirFlag,
|
utils.KeyStoreDirFlag,
|
||||||
|
@ -128,7 +125,7 @@ password to file or expose in any other way.
|
||||||
{
|
{
|
||||||
Name: "update",
|
Name: "update",
|
||||||
Usage: "Update an existing account",
|
Usage: "Update an existing account",
|
||||||
Action: utils.MigrateFlags(accountUpdate),
|
Action: accountUpdate,
|
||||||
ArgsUsage: "<address>",
|
ArgsUsage: "<address>",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
|
@ -157,7 +154,7 @@ changing your password is only possible interactively.
|
||||||
{
|
{
|
||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Import a private key into a new account",
|
Usage: "Import a private key into a new account",
|
||||||
Action: utils.MigrateFlags(accountImport),
|
Action: accountImport,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
utils.KeyStoreDirFlag,
|
utils.KeyStoreDirFlag,
|
||||||
|
@ -263,7 +260,7 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr
|
||||||
func accountCreate(ctx *cli.Context) error {
|
func accountCreate(ctx *cli.Context) error {
|
||||||
cfg := gethConfig{Node: defaultNodeConfig()}
|
cfg := gethConfig{Node: defaultNodeConfig()}
|
||||||
// Load config file.
|
// Load config file.
|
||||||
if file := ctx.GlobalString(configFileFlag.Name); file != "" {
|
if file := ctx.String(configFileFlag.Name); file != "" {
|
||||||
if err := loadConfig(file, &cfg); err != nil {
|
if err := loadConfig(file, &cfg); err != nil {
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
@ -300,13 +297,13 @@ func accountCreate(ctx *cli.Context) error {
|
||||||
// accountUpdate transitions an account from a previous format to the current
|
// accountUpdate transitions an account from a previous format to the current
|
||||||
// one, also providing the possibility to change the pass-phrase.
|
// one, also providing the possibility to change the pass-phrase.
|
||||||
func accountUpdate(ctx *cli.Context) error {
|
func accountUpdate(ctx *cli.Context) error {
|
||||||
if len(ctx.Args()) == 0 {
|
if ctx.Args().Len() == 0 {
|
||||||
utils.Fatalf("No accounts specified to update")
|
utils.Fatalf("No accounts specified to update")
|
||||||
}
|
}
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
|
ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
|
||||||
|
|
||||||
for _, addr := range ctx.Args() {
|
for _, addr := range ctx.Args().Slice() {
|
||||||
account, oldPassword := unlockAccount(ks, addr, 0, nil)
|
account, oldPassword := unlockAccount(ks, addr, 0, nil)
|
||||||
newPassword := utils.GetPassPhraseWithList("Please give a new password. Do not forget this password.", true, 0, nil)
|
newPassword := utils.GetPassPhraseWithList("Please give a new password. Do not forget this password.", true, 0, nil)
|
||||||
if err := ks.Update(account, oldPassword, newPassword); err != nil {
|
if err := ks.Update(account, oldPassword, newPassword); err != nil {
|
||||||
|
@ -317,10 +314,10 @@ func accountUpdate(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func importWallet(ctx *cli.Context) error {
|
func importWallet(ctx *cli.Context) error {
|
||||||
keyfile := ctx.Args().First()
|
if ctx.Args().Len() != 1 {
|
||||||
if len(keyfile) == 0 {
|
utils.Fatalf("keyfile must be given as the only argument")
|
||||||
utils.Fatalf("keyfile must be given as argument")
|
|
||||||
}
|
}
|
||||||
|
keyfile := ctx.Args().First()
|
||||||
keyJSON, err := os.ReadFile(keyfile)
|
keyJSON, err := os.ReadFile(keyfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Could not read wallet file: %v", err)
|
utils.Fatalf("Could not read wallet file: %v", err)
|
||||||
|
@ -339,10 +336,10 @@ func importWallet(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func accountImport(ctx *cli.Context) error {
|
func accountImport(ctx *cli.Context) error {
|
||||||
keyfile := ctx.Args().First()
|
if ctx.Args().Len() != 1 {
|
||||||
if len(keyfile) == 0 {
|
utils.Fatalf("keyfile must be given as the only argument")
|
||||||
utils.Fatalf("keyfile must be given as argument")
|
|
||||||
}
|
}
|
||||||
|
keyfile := ctx.Args().First()
|
||||||
key, err := crypto.LoadECDSA(keyfile)
|
key, err := crypto.LoadECDSA(keyfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to load the private key: %v", err)
|
utils.Fatalf("Failed to load the private key: %v", err)
|
||||||
|
|
|
@ -49,20 +49,27 @@ func TestAccountListEmpty(t *testing.T) {
|
||||||
|
|
||||||
func TestAccountList(t *testing.T) {
|
func TestAccountList(t *testing.T) {
|
||||||
datadir := tmpDatadirWithKeystore(t)
|
datadir := tmpDatadirWithKeystore(t)
|
||||||
geth := runGeth(t, "account", "list", "--datadir", datadir)
|
var want = `
|
||||||
defer geth.ExpectExit()
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
geth.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 {
|
|
||||||
geth.Expect(`
|
|
||||||
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
|
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
|
||||||
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa
|
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa
|
||||||
Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}/keystore/zzz
|
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 := runGeth(t, "account", "list", "--datadir", datadir)
|
||||||
|
geth.Expect(want)
|
||||||
|
geth.ExpectExit()
|
||||||
|
}
|
||||||
|
{
|
||||||
|
geth := runGeth(t, "--datadir", datadir, "account", "list")
|
||||||
|
geth.Expect(want)
|
||||||
|
geth.ExpectExit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +117,20 @@ func TestAccountImport(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccountHelp(t *testing.T) {
|
||||||
|
geth := runGeth(t, "account", "-h")
|
||||||
|
geth.WaitExit()
|
||||||
|
if have, want := geth.ExitStatus(), 0; have != want {
|
||||||
|
t.Errorf("exit error, have %d want %d", have, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
geth = runGeth(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) {
|
func importAccountWithExpect(t *testing.T, key string, expected string) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
keyfile := filepath.Join(dir, "key.prv")
|
keyfile := filepath.Join(dir, "key.prv")
|
||||||
|
@ -120,7 +141,7 @@ func importAccountWithExpect(t *testing.T, key string, expected string) {
|
||||||
if err := os.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil {
|
if err := os.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
geth := runGeth(t, "--lightkdf", "account", "import", keyfile, "-password", passwordFile)
|
geth := runGeth(t, "--lightkdf", "account", "import", "-password", passwordFile, keyfile)
|
||||||
defer geth.ExpectExit()
|
defer geth.ExpectExit()
|
||||||
geth.Expect(expected)
|
geth.Expect(expected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,17 +38,16 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
initCommand = cli.Command{
|
initCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(initGenesis),
|
Action: initGenesis,
|
||||||
Name: "init",
|
Name: "init",
|
||||||
Usage: "Bootstrap and initialize a new genesis block",
|
Usage: "Bootstrap and initialize a new genesis block",
|
||||||
ArgsUsage: "<genesisPath>",
|
ArgsUsage: "<genesisPath>",
|
||||||
Flags: utils.DatabasePathFlags,
|
Flags: utils.DatabasePathFlags,
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The init command initializes a new genesis block and definition for the network.
|
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
|
This is a destructive action and changes the network in which you will be
|
||||||
|
@ -56,18 +55,17 @@ participating.
|
||||||
|
|
||||||
It expects the genesis file as argument.`,
|
It expects the genesis file as argument.`,
|
||||||
}
|
}
|
||||||
dumpGenesisCommand = cli.Command{
|
dumpGenesisCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dumpGenesis),
|
Action: dumpGenesis,
|
||||||
Name: "dumpgenesis",
|
Name: "dumpgenesis",
|
||||||
Usage: "Dumps genesis block JSON configuration to stdout",
|
Usage: "Dumps genesis block JSON configuration to stdout",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Flags: utils.NetworkFlags,
|
Flags: utils.NetworkFlags,
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The dumpgenesis command dumps the genesis block configuration in JSON format to stdout.`,
|
The dumpgenesis command dumps the genesis block configuration in JSON format to stdout.`,
|
||||||
}
|
}
|
||||||
importCommand = cli.Command{
|
importCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(importChain),
|
Action: importChain,
|
||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Import a blockchain file",
|
Usage: "Import a blockchain file",
|
||||||
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
||||||
|
@ -94,7 +92,6 @@ The dumpgenesis command dumps the genesis block configuration in JSON format to
|
||||||
utils.MetricsInfluxDBOrganizationFlag,
|
utils.MetricsInfluxDBOrganizationFlag,
|
||||||
utils.TxLookupLimitFlag,
|
utils.TxLookupLimitFlag,
|
||||||
}, utils.DatabasePathFlags...),
|
}, utils.DatabasePathFlags...),
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The import command imports blocks from an RLP-encoded form. The form can be one file
|
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.
|
with several RLP-encoded blocks, or several files can be used.
|
||||||
|
@ -102,8 +99,8 @@ 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,
|
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.`,
|
processing will proceed even if an individual RLP-file import failure occurs.`,
|
||||||
}
|
}
|
||||||
exportCommand = cli.Command{
|
exportCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(exportChain),
|
Action: exportChain,
|
||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "Export blockchain into file",
|
Usage: "Export blockchain into file",
|
||||||
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
||||||
|
@ -111,7 +108,6 @@ processing will proceed even if an individual RLP-file import failure occurs.`,
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabasePathFlags...),
|
}, utils.DatabasePathFlags...),
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
Requires a first argument of the file to write to.
|
Requires a first argument of the file to write to.
|
||||||
Optional second and third arguments control the first and
|
Optional second and third arguments control the first and
|
||||||
|
@ -119,8 +115,8 @@ last block to write. In this mode, the file will be appended
|
||||||
if already existing. If the file ends with .gz, the output will
|
if already existing. If the file ends with .gz, the output will
|
||||||
be gzipped.`,
|
be gzipped.`,
|
||||||
}
|
}
|
||||||
importPreimagesCommand = cli.Command{
|
importPreimagesCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(importPreimages),
|
Action: importPreimages,
|
||||||
Name: "import-preimages",
|
Name: "import-preimages",
|
||||||
Usage: "Import the preimage database from an RLP stream",
|
Usage: "Import the preimage database from an RLP stream",
|
||||||
ArgsUsage: "<datafile>",
|
ArgsUsage: "<datafile>",
|
||||||
|
@ -128,14 +124,13 @@ be gzipped.`,
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabasePathFlags...),
|
}, utils.DatabasePathFlags...),
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The import-preimages command imports hash preimages from an RLP encoded stream.
|
The import-preimages command imports hash preimages from an RLP encoded stream.
|
||||||
It's deprecated, please use "geth db import" instead.
|
It's deprecated, please use "geth db import" instead.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
exportPreimagesCommand = cli.Command{
|
exportPreimagesCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(exportPreimages),
|
Action: exportPreimages,
|
||||||
Name: "export-preimages",
|
Name: "export-preimages",
|
||||||
Usage: "Export the preimage database into an RLP stream",
|
Usage: "Export the preimage database into an RLP stream",
|
||||||
ArgsUsage: "<dumpfile>",
|
ArgsUsage: "<dumpfile>",
|
||||||
|
@ -143,14 +138,13 @@ It's deprecated, please use "geth db import" instead.
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabasePathFlags...),
|
}, utils.DatabasePathFlags...),
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The export-preimages command exports hash preimages to an RLP encoded stream.
|
The export-preimages command exports hash preimages to an RLP encoded stream.
|
||||||
It's deprecated, please use "geth db export" instead.
|
It's deprecated, please use "geth db export" instead.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
dumpCommand = cli.Command{
|
dumpCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dump),
|
Action: dump,
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "Dump a specific block from storage",
|
Usage: "Dump a specific block from storage",
|
||||||
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
||||||
|
@ -163,7 +157,6 @@ It's deprecated, please use "geth db export" instead.
|
||||||
utils.StartKeyFlag,
|
utils.StartKeyFlag,
|
||||||
utils.DumpLimitFlag,
|
utils.DumpLimitFlag,
|
||||||
}, utils.DatabasePathFlags...),
|
}, utils.DatabasePathFlags...),
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
This command dumps out the state for a given block (or latest, if none provided).
|
This command dumps out the state for a given block (or latest, if none provided).
|
||||||
`,
|
`,
|
||||||
|
@ -192,7 +185,7 @@ func initGenesis(ctx *cli.Context) error {
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
for _, name := range []string{"chaindata", "lightchaindata"} {
|
for _, name := range []string{"chaindata", "lightchaindata"} {
|
||||||
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.GlobalString(utils.AncientFlag.Name), "", false)
|
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to open database: %v", err)
|
utils.Fatalf("Failed to open database: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -219,7 +212,7 @@ func dumpGenesis(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func importChain(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.")
|
utils.Fatalf("This command requires an argument.")
|
||||||
}
|
}
|
||||||
// Start metrics export if enabled
|
// Start metrics export if enabled
|
||||||
|
@ -253,13 +246,13 @@ func importChain(ctx *cli.Context) error {
|
||||||
|
|
||||||
var importErr error
|
var importErr error
|
||||||
|
|
||||||
if len(ctx.Args()) == 1 {
|
if ctx.Args().Len() == 1 {
|
||||||
if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
|
if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
|
||||||
importErr = err
|
importErr = err
|
||||||
log.Error("Import error", "err", err)
|
log.Error("Import error", "err", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, arg := range ctx.Args() {
|
for _, arg := range ctx.Args().Slice() {
|
||||||
if err := utils.ImportChain(chain, arg); err != nil {
|
if err := utils.ImportChain(chain, arg); err != nil {
|
||||||
importErr = err
|
importErr = err
|
||||||
log.Error("Import error", "file", arg, "err", err)
|
log.Error("Import error", "file", arg, "err", err)
|
||||||
|
@ -281,7 +274,7 @@ func importChain(ctx *cli.Context) error {
|
||||||
fmt.Printf("Allocations: %.3f million\n", float64(mem.Mallocs)/1000000)
|
fmt.Printf("Allocations: %.3f million\n", float64(mem.Mallocs)/1000000)
|
||||||
fmt.Printf("GC pause: %v\n\n", time.Duration(mem.PauseTotalNs))
|
fmt.Printf("GC pause: %v\n\n", time.Duration(mem.PauseTotalNs))
|
||||||
|
|
||||||
if ctx.GlobalBool(utils.NoCompactionFlag.Name) {
|
if ctx.Bool(utils.NoCompactionFlag.Name) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +291,7 @@ func importChain(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportChain(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.")
|
utils.Fatalf("This command requires an argument.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +303,7 @@ func exportChain(ctx *cli.Context) error {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
fp := ctx.Args().First()
|
fp := ctx.Args().First()
|
||||||
if len(ctx.Args()) < 3 {
|
if ctx.Args().Len() < 3 {
|
||||||
err = utils.ExportChain(chain, fp)
|
err = utils.ExportChain(chain, fp)
|
||||||
} else {
|
} else {
|
||||||
// This can be improved to allow for numbers larger than 9223372036854775807
|
// This can be improved to allow for numbers larger than 9223372036854775807
|
||||||
|
@ -337,7 +330,7 @@ func exportChain(ctx *cli.Context) error {
|
||||||
|
|
||||||
// importPreimages imports preimage data from the specified file.
|
// importPreimages imports preimage data from the specified file.
|
||||||
func importPreimages(ctx *cli.Context) error {
|
func importPreimages(ctx *cli.Context) error {
|
||||||
if len(ctx.Args()) < 1 {
|
if ctx.Args().Len() < 1 {
|
||||||
utils.Fatalf("This command requires an argument.")
|
utils.Fatalf("This command requires an argument.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +349,7 @@ func importPreimages(ctx *cli.Context) error {
|
||||||
|
|
||||||
// exportPreimages dumps the preimage data to specified json file in streaming way.
|
// exportPreimages dumps the preimage data to specified json file in streaming way.
|
||||||
func exportPreimages(ctx *cli.Context) error {
|
func exportPreimages(ctx *cli.Context) error {
|
||||||
if len(ctx.Args()) < 1 {
|
if ctx.Args().Len() < 1 {
|
||||||
utils.Fatalf("This command requires an argument.")
|
utils.Fatalf("This command requires an argument.")
|
||||||
}
|
}
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/external"
|
"github.com/ethereum/go-ethereum/accounts/external"
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
|
@ -35,6 +35,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
@ -43,19 +44,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dumpConfigCommand = cli.Command{
|
dumpConfigCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dumpConfig),
|
Action: dumpConfig,
|
||||||
Name: "dumpconfig",
|
Name: "dumpconfig",
|
||||||
Usage: "Show configuration values",
|
Usage: "Show configuration values",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Flags: utils.GroupFlags(nodeFlags, rpcFlags),
|
Flags: utils.GroupFlags(nodeFlags, rpcFlags),
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Description: `The dumpconfig command shows configuration values.`,
|
Description: `The dumpconfig command shows configuration values.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
configFileFlag = cli.StringFlag{
|
configFileFlag = &cli.StringFlag{
|
||||||
Name: "config",
|
Name: "config",
|
||||||
Usage: "TOML configuration file",
|
Usage: "TOML configuration file",
|
||||||
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load config file.
|
// Load config file.
|
||||||
if file := ctx.GlobalString(configFileFlag.Name); file != "" {
|
if file := ctx.String(configFileFlag.Name); file != "" {
|
||||||
if err := loadConfig(file, &cfg); err != nil {
|
if err := loadConfig(file, &cfg); err != nil {
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
@ -145,8 +146,8 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.SetEthConfig(ctx, stack, &cfg.Eth)
|
utils.SetEthConfig(ctx, stack, &cfg.Eth)
|
||||||
if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) {
|
if ctx.IsSet(utils.EthStatsURLFlag.Name) {
|
||||||
cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name)
|
cfg.Ethstats.URL = ctx.String(utils.EthStatsURLFlag.Name)
|
||||||
}
|
}
|
||||||
applyMetricConfig(ctx, &cfg)
|
applyMetricConfig(ctx, &cfg)
|
||||||
|
|
||||||
|
@ -156,15 +157,15 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
|
||||||
// makeFullNode loads geth configuration and creates the Ethereum backend.
|
// makeFullNode loads geth configuration and creates the Ethereum backend.
|
||||||
func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||||
stack, cfg := makeConfigNode(ctx)
|
stack, cfg := makeConfigNode(ctx)
|
||||||
if ctx.GlobalIsSet(utils.OverrideGrayGlacierFlag.Name) {
|
if ctx.IsSet(utils.OverrideGrayGlacierFlag.Name) {
|
||||||
cfg.Eth.OverrideGrayGlacier = new(big.Int).SetUint64(ctx.GlobalUint64(utils.OverrideGrayGlacierFlag.Name))
|
cfg.Eth.OverrideGrayGlacier = new(big.Int).SetUint64(ctx.Uint64(utils.OverrideGrayGlacierFlag.Name))
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.OverrideTerminalTotalDifficulty.Name) {
|
if ctx.IsSet(utils.OverrideTerminalTotalDifficulty.Name) {
|
||||||
cfg.Eth.OverrideTerminalTotalDifficulty = utils.GlobalBig(ctx, utils.OverrideTerminalTotalDifficulty.Name)
|
cfg.Eth.OverrideTerminalTotalDifficulty = flags.GlobalBig(ctx, utils.OverrideTerminalTotalDifficulty.Name)
|
||||||
}
|
}
|
||||||
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
|
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
|
||||||
// Warn users to migrate if they have a legacy freezer format.
|
// Warn users to migrate if they have a legacy freezer format.
|
||||||
if eth != nil && !ctx.GlobalIsSet(utils.IgnoreLegacyReceiptsFlag.Name) {
|
if eth != nil && !ctx.IsSet(utils.IgnoreLegacyReceiptsFlag.Name) {
|
||||||
firstIdx := uint64(0)
|
firstIdx := uint64(0)
|
||||||
// Hack to speed up check for mainnet because we know
|
// Hack to speed up check for mainnet because we know
|
||||||
// the first non-empty block.
|
// the first non-empty block.
|
||||||
|
@ -182,7 +183,7 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure GraphQL if requested
|
// Configure GraphQL if requested
|
||||||
if ctx.GlobalIsSet(utils.GraphQLEnabledFlag.Name) {
|
if ctx.IsSet(utils.GraphQLEnabledFlag.Name) {
|
||||||
utils.RegisterGraphQLService(stack, backend, cfg.Node)
|
utils.RegisterGraphQLService(stack, backend, cfg.Node)
|
||||||
}
|
}
|
||||||
// Add the Ethereum Stats daemon if requested.
|
// Add the Ethereum Stats daemon if requested.
|
||||||
|
@ -222,47 +223,47 @@ func dumpConfig(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) {
|
func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) {
|
||||||
if ctx.GlobalIsSet(utils.MetricsEnabledFlag.Name) {
|
if ctx.IsSet(utils.MetricsEnabledFlag.Name) {
|
||||||
cfg.Metrics.Enabled = ctx.GlobalBool(utils.MetricsEnabledFlag.Name)
|
cfg.Metrics.Enabled = ctx.Bool(utils.MetricsEnabledFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsEnabledExpensiveFlag.Name) {
|
if ctx.IsSet(utils.MetricsEnabledExpensiveFlag.Name) {
|
||||||
cfg.Metrics.EnabledExpensive = ctx.GlobalBool(utils.MetricsEnabledExpensiveFlag.Name)
|
cfg.Metrics.EnabledExpensive = ctx.Bool(utils.MetricsEnabledExpensiveFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsHTTPFlag.Name) {
|
if ctx.IsSet(utils.MetricsHTTPFlag.Name) {
|
||||||
cfg.Metrics.HTTP = ctx.GlobalString(utils.MetricsHTTPFlag.Name)
|
cfg.Metrics.HTTP = ctx.String(utils.MetricsHTTPFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsPortFlag.Name) {
|
if ctx.IsSet(utils.MetricsPortFlag.Name) {
|
||||||
cfg.Metrics.Port = ctx.GlobalInt(utils.MetricsPortFlag.Name)
|
cfg.Metrics.Port = ctx.Int(utils.MetricsPortFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsEnableInfluxDBFlag.Name) {
|
if ctx.IsSet(utils.MetricsEnableInfluxDBFlag.Name) {
|
||||||
cfg.Metrics.EnableInfluxDB = ctx.GlobalBool(utils.MetricsEnableInfluxDBFlag.Name)
|
cfg.Metrics.EnableInfluxDB = ctx.Bool(utils.MetricsEnableInfluxDBFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBEndpointFlag.Name) {
|
if ctx.IsSet(utils.MetricsInfluxDBEndpointFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBEndpoint = ctx.GlobalString(utils.MetricsInfluxDBEndpointFlag.Name)
|
cfg.Metrics.InfluxDBEndpoint = ctx.String(utils.MetricsInfluxDBEndpointFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBDatabaseFlag.Name) {
|
if ctx.IsSet(utils.MetricsInfluxDBDatabaseFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBDatabase = ctx.GlobalString(utils.MetricsInfluxDBDatabaseFlag.Name)
|
cfg.Metrics.InfluxDBDatabase = ctx.String(utils.MetricsInfluxDBDatabaseFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBUsernameFlag.Name) {
|
if ctx.IsSet(utils.MetricsInfluxDBUsernameFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBUsername = ctx.GlobalString(utils.MetricsInfluxDBUsernameFlag.Name)
|
cfg.Metrics.InfluxDBUsername = ctx.String(utils.MetricsInfluxDBUsernameFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBPasswordFlag.Name) {
|
if ctx.IsSet(utils.MetricsInfluxDBPasswordFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBPassword = ctx.GlobalString(utils.MetricsInfluxDBPasswordFlag.Name)
|
cfg.Metrics.InfluxDBPassword = ctx.String(utils.MetricsInfluxDBPasswordFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBTagsFlag.Name) {
|
if ctx.IsSet(utils.MetricsInfluxDBTagsFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBTags = ctx.GlobalString(utils.MetricsInfluxDBTagsFlag.Name)
|
cfg.Metrics.InfluxDBTags = ctx.String(utils.MetricsInfluxDBTagsFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsEnableInfluxDBV2Flag.Name) {
|
if ctx.IsSet(utils.MetricsEnableInfluxDBV2Flag.Name) {
|
||||||
cfg.Metrics.EnableInfluxDBV2 = ctx.GlobalBool(utils.MetricsEnableInfluxDBV2Flag.Name)
|
cfg.Metrics.EnableInfluxDBV2 = ctx.Bool(utils.MetricsEnableInfluxDBV2Flag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBTokenFlag.Name) {
|
if ctx.IsSet(utils.MetricsInfluxDBTokenFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBToken = ctx.GlobalString(utils.MetricsInfluxDBTokenFlag.Name)
|
cfg.Metrics.InfluxDBToken = ctx.String(utils.MetricsInfluxDBTokenFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBBucketFlag.Name) {
|
if ctx.IsSet(utils.MetricsInfluxDBBucketFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBBucket = ctx.GlobalString(utils.MetricsInfluxDBBucketFlag.Name)
|
cfg.Metrics.InfluxDBBucket = ctx.String(utils.MetricsInfluxDBBucketFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBOrganizationFlag.Name) {
|
if ctx.IsSet(utils.MetricsInfluxDBOrganizationFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBOrganization = ctx.GlobalString(utils.MetricsInfluxDBOrganizationFlag.Name)
|
cfg.Metrics.InfluxDBOrganization = ctx.String(utils.MetricsInfluxDBOrganizationFlag.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,31 +24,29 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
consoleFlags = []cli.Flag{utils.JSpathFlag, utils.ExecFlag, utils.PreloadJSFlag}
|
consoleFlags = []cli.Flag{utils.JSpathFlag, utils.ExecFlag, utils.PreloadJSFlag}
|
||||||
|
|
||||||
consoleCommand = cli.Command{
|
consoleCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(localConsole),
|
Action: localConsole,
|
||||||
Name: "console",
|
Name: "console",
|
||||||
Usage: "Start an interactive JavaScript environment",
|
Usage: "Start an interactive JavaScript environment",
|
||||||
Flags: utils.GroupFlags(nodeFlags, rpcFlags, consoleFlags),
|
Flags: utils.GroupFlags(nodeFlags, rpcFlags, consoleFlags),
|
||||||
Category: "CONSOLE COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The Geth console is an interactive shell for the JavaScript runtime environment
|
The Geth console is an interactive shell for the JavaScript runtime environment
|
||||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||||
See https://geth.ethereum.org/docs/interface/javascript-console.`,
|
See https://geth.ethereum.org/docs/interface/javascript-console.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
attachCommand = cli.Command{
|
attachCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(remoteConsole),
|
Action: remoteConsole,
|
||||||
Name: "attach",
|
Name: "attach",
|
||||||
Usage: "Start an interactive JavaScript environment (connect to node)",
|
Usage: "Start an interactive JavaScript environment (connect to node)",
|
||||||
ArgsUsage: "[endpoint]",
|
ArgsUsage: "[endpoint]",
|
||||||
Flags: utils.GroupFlags([]cli.Flag{utils.DataDirFlag}, consoleFlags),
|
Flags: utils.GroupFlags([]cli.Flag{utils.DataDirFlag}, consoleFlags),
|
||||||
Category: "CONSOLE COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The Geth console is an interactive shell for the JavaScript runtime environment
|
The Geth console is an interactive shell for the JavaScript runtime environment
|
||||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||||
|
@ -56,13 +54,12 @@ See https://geth.ethereum.org/docs/interface/javascript-console.
|
||||||
This command allows to open a console on a running geth node.`,
|
This command allows to open a console on a running geth node.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
javascriptCommand = cli.Command{
|
javascriptCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(ephemeralConsole),
|
Action: ephemeralConsole,
|
||||||
Name: "js",
|
Name: "js",
|
||||||
Usage: "(DEPRECATED) Execute the specified JavaScript files",
|
Usage: "(DEPRECATED) Execute the specified JavaScript files",
|
||||||
ArgsUsage: "<jsfile> [jsfile...]",
|
ArgsUsage: "<jsfile> [jsfile...]",
|
||||||
Flags: utils.GroupFlags(nodeFlags, consoleFlags),
|
Flags: utils.GroupFlags(nodeFlags, consoleFlags),
|
||||||
Category: "CONSOLE COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The JavaScript VM exposes a node admin interface as well as the Ðapp
|
The JavaScript VM exposes a node admin interface as well as the Ðapp
|
||||||
JavaScript API. See https://geth.ethereum.org/docs/interface/javascript-console`,
|
JavaScript API. See https://geth.ethereum.org/docs/interface/javascript-console`,
|
||||||
|
@ -85,7 +82,7 @@ func localConsole(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
config := console.Config{
|
config := console.Config{
|
||||||
DataDir: utils.MakeDataDir(ctx),
|
DataDir: utils.MakeDataDir(ctx),
|
||||||
DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
|
DocRoot: ctx.String(utils.JSpathFlag.Name),
|
||||||
Client: client,
|
Client: client,
|
||||||
Preload: utils.MakeConsolePreloads(ctx),
|
Preload: utils.MakeConsolePreloads(ctx),
|
||||||
}
|
}
|
||||||
|
@ -96,7 +93,7 @@ func localConsole(ctx *cli.Context) error {
|
||||||
defer console.Stop(false)
|
defer console.Stop(false)
|
||||||
|
|
||||||
// If only a short execution was requested, evaluate and return.
|
// 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)
|
console.Evaluate(script)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -129,7 +126,7 @@ func remoteConsole(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
config := console.Config{
|
config := console.Config{
|
||||||
DataDir: utils.MakeDataDir(ctx),
|
DataDir: utils.MakeDataDir(ctx),
|
||||||
DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
|
DocRoot: ctx.String(utils.JSpathFlag.Name),
|
||||||
Client: client,
|
Client: client,
|
||||||
Preload: utils.MakeConsolePreloads(ctx),
|
Preload: utils.MakeConsolePreloads(ctx),
|
||||||
}
|
}
|
||||||
|
@ -139,7 +136,7 @@ func remoteConsole(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
defer console.Stop(false)
|
defer console.Stop(false)
|
||||||
|
|
||||||
if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
|
if script := ctx.String(utils.ExecFlag.Name); script != "" {
|
||||||
console.Evaluate(script)
|
console.Evaluate(script)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -155,7 +152,7 @@ func remoteConsole(ctx *cli.Context) error {
|
||||||
// everything down.
|
// everything down.
|
||||||
func ephemeralConsole(ctx *cli.Context) error {
|
func ephemeralConsole(ctx *cli.Context) error {
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
for _, file := range ctx.Args() {
|
for _, file := range ctx.Args().Slice() {
|
||||||
b.Write([]byte(fmt.Sprintf("loadScript('%s');", file)))
|
b.Write([]byte(fmt.Sprintf("loadScript('%s');", file)))
|
||||||
}
|
}
|
||||||
utils.Fatalf(`The "js" command is deprecated. Please use the following instead:
|
utils.Fatalf(`The "js" command is deprecated. Please use the following instead:
|
||||||
|
|
|
@ -40,26 +40,24 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
removedbCommand = cli.Command{
|
removedbCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(removeDB),
|
Action: removeDB,
|
||||||
Name: "removedb",
|
Name: "removedb",
|
||||||
Usage: "Remove blockchain and state databases",
|
Usage: "Remove blockchain and state databases",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Flags: utils.DatabasePathFlags,
|
Flags: utils.DatabasePathFlags,
|
||||||
Category: "DATABASE COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
Remove blockchain and state databases`,
|
Remove blockchain and state databases`,
|
||||||
}
|
}
|
||||||
dbCommand = cli.Command{
|
dbCommand = &cli.Command{
|
||||||
Name: "db",
|
Name: "db",
|
||||||
Usage: "Low level database operations",
|
Usage: "Low level database operations",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Category: "DATABASE COMMANDS",
|
Subcommands: []*cli.Command{
|
||||||
Subcommands: []cli.Command{
|
|
||||||
dbInspectCmd,
|
dbInspectCmd,
|
||||||
dbStatCmd,
|
dbStatCmd,
|
||||||
dbCompactCmd,
|
dbCompactCmd,
|
||||||
|
@ -75,8 +73,8 @@ Remove blockchain and state databases`,
|
||||||
dbCheckStateContentCmd,
|
dbCheckStateContentCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dbInspectCmd = cli.Command{
|
dbInspectCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(inspect),
|
Action: inspect,
|
||||||
Name: "inspect",
|
Name: "inspect",
|
||||||
ArgsUsage: "<prefix> <start>",
|
ArgsUsage: "<prefix> <start>",
|
||||||
Flags: utils.GroupFlags([]cli.Flag{
|
Flags: utils.GroupFlags([]cli.Flag{
|
||||||
|
@ -85,8 +83,8 @@ Remove blockchain and state databases`,
|
||||||
Usage: "Inspect the storage size for each type of data in the database",
|
Usage: "Inspect the storage size for each type of data in the database",
|
||||||
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
||||||
}
|
}
|
||||||
dbCheckStateContentCmd = cli.Command{
|
dbCheckStateContentCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(checkStateContent),
|
Action: checkStateContent,
|
||||||
Name: "check-state-content",
|
Name: "check-state-content",
|
||||||
ArgsUsage: "<start (optional)>",
|
ArgsUsage: "<start (optional)>",
|
||||||
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
|
@ -95,16 +93,16 @@ Remove blockchain and state databases`,
|
||||||
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
|
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
|
||||||
a data corruption.`,
|
a data corruption.`,
|
||||||
}
|
}
|
||||||
dbStatCmd = cli.Command{
|
dbStatCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dbStats),
|
Action: dbStats,
|
||||||
Name: "stats",
|
Name: "stats",
|
||||||
Usage: "Print leveldb statistics",
|
Usage: "Print leveldb statistics",
|
||||||
Flags: utils.GroupFlags([]cli.Flag{
|
Flags: utils.GroupFlags([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
}
|
}
|
||||||
dbCompactCmd = cli.Command{
|
dbCompactCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dbCompact),
|
Action: dbCompact,
|
||||||
Name: "compact",
|
Name: "compact",
|
||||||
Usage: "Compact leveldb database. WARNING: May take a very long time",
|
Usage: "Compact leveldb database. WARNING: May take a very long time",
|
||||||
Flags: utils.GroupFlags([]cli.Flag{
|
Flags: utils.GroupFlags([]cli.Flag{
|
||||||
|
@ -116,8 +114,8 @@ a data corruption.`,
|
||||||
WARNING: This operation may take a very long time to finish, and may cause database
|
WARNING: This operation may take a very long time to finish, and may cause database
|
||||||
corruption if it is aborted during execution'!`,
|
corruption if it is aborted during execution'!`,
|
||||||
}
|
}
|
||||||
dbGetCmd = cli.Command{
|
dbGetCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dbGet),
|
Action: dbGet,
|
||||||
Name: "get",
|
Name: "get",
|
||||||
Usage: "Show the value of a database key",
|
Usage: "Show the value of a database key",
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
|
@ -126,8 +124,8 @@ corruption if it is aborted during execution'!`,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
}
|
}
|
||||||
dbDeleteCmd = cli.Command{
|
dbDeleteCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dbDelete),
|
Action: dbDelete,
|
||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "Delete a database key (WARNING: may corrupt your database)",
|
Usage: "Delete a database key (WARNING: may corrupt your database)",
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
|
@ -137,8 +135,8 @@ corruption if it is aborted during execution'!`,
|
||||||
Description: `This command deletes the specified database key from the database.
|
Description: `This command deletes the specified database key from the database.
|
||||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}
|
}
|
||||||
dbPutCmd = cli.Command{
|
dbPutCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dbPut),
|
Action: dbPut,
|
||||||
Name: "put",
|
Name: "put",
|
||||||
Usage: "Set the value of a database key (WARNING: may corrupt your database)",
|
Usage: "Set the value of a database key (WARNING: may corrupt your database)",
|
||||||
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
||||||
|
@ -148,8 +146,8 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Description: `This command sets a given database key to the given value.
|
Description: `This command sets a given database key to the given value.
|
||||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}
|
}
|
||||||
dbGetSlotsCmd = cli.Command{
|
dbGetSlotsCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(dbDumpTrie),
|
Action: dbDumpTrie,
|
||||||
Name: "dumptrie",
|
Name: "dumptrie",
|
||||||
Usage: "Show the storage key/values of a given storage trie",
|
Usage: "Show the storage key/values of a given storage trie",
|
||||||
ArgsUsage: "<hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
|
ArgsUsage: "<hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
|
||||||
|
@ -158,8 +156,8 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
}
|
}
|
||||||
dbDumpFreezerIndex = cli.Command{
|
dbDumpFreezerIndex = &cli.Command{
|
||||||
Action: utils.MigrateFlags(freezerInspect),
|
Action: freezerInspect,
|
||||||
Name: "freezer-index",
|
Name: "freezer-index",
|
||||||
Usage: "Dump out the index of a given freezer type",
|
Usage: "Dump out the index of a given freezer type",
|
||||||
ArgsUsage: "<type> <start (int)> <end (int)>",
|
ArgsUsage: "<type> <start (int)> <end (int)>",
|
||||||
|
@ -168,8 +166,8 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: "This command displays information about the freezer index.",
|
Description: "This command displays information about the freezer index.",
|
||||||
}
|
}
|
||||||
dbImportCmd = cli.Command{
|
dbImportCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(importLDBdata),
|
Action: importLDBdata,
|
||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Imports leveldb-data from an exported RLP dump.",
|
Usage: "Imports leveldb-data from an exported RLP dump.",
|
||||||
ArgsUsage: "<dumpfile> <start (optional)",
|
ArgsUsage: "<dumpfile> <start (optional)",
|
||||||
|
@ -178,8 +176,8 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: "The import command imports the specific chain data from an RLP encoded stream.",
|
Description: "The import command imports the specific chain data from an RLP encoded stream.",
|
||||||
}
|
}
|
||||||
dbExportCmd = cli.Command{
|
dbExportCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(exportChaindata),
|
Action: exportChaindata,
|
||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
|
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
|
||||||
ArgsUsage: "<type> <dumpfile>",
|
ArgsUsage: "<type> <dumpfile>",
|
||||||
|
@ -188,8 +186,8 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
|
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
|
||||||
}
|
}
|
||||||
dbMetadataCmd = cli.Command{
|
dbMetadataCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(showMetaData),
|
Action: showMetaData,
|
||||||
Name: "metadata",
|
Name: "metadata",
|
||||||
Usage: "Shows metadata about the chain status.",
|
Usage: "Shows metadata about the chain status.",
|
||||||
Flags: utils.GroupFlags([]cli.Flag{
|
Flags: utils.GroupFlags([]cli.Flag{
|
||||||
|
@ -197,8 +195,8 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: "Shows metadata about the chain status.",
|
Description: "Shows metadata about the chain status.",
|
||||||
}
|
}
|
||||||
dbMigrateFreezerCmd = cli.Command{
|
dbMigrateFreezerCmd = &cli.Command{
|
||||||
Action: utils.MigrateFlags(freezerMigrate),
|
Action: freezerMigrate,
|
||||||
Name: "freezer-migrate",
|
Name: "freezer-migrate",
|
||||||
Usage: "Migrate legacy parts of the freezer. (WARNING: may take a long time)",
|
Usage: "Migrate legacy parts of the freezer. (WARNING: may take a long time)",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
|
|
|
@ -144,7 +144,7 @@ func initGeth(t *testing.T) string {
|
||||||
func startLightServer(t *testing.T) *gethrpc {
|
func startLightServer(t *testing.T) *gethrpc {
|
||||||
datadir := initGeth(t)
|
datadir := initGeth(t)
|
||||||
t.Logf("Importing keys to geth")
|
t.Logf("Importing keys to geth")
|
||||||
runGeth(t, "--datadir", datadir, "--password", "./testdata/password.txt", "account", "import", "./testdata/key.prv", "--lightkdf").WaitExit()
|
runGeth(t, "account", "import", "--datadir", datadir, "--password", "./testdata/password.txt", "--lightkdf", "./testdata/key.prv").WaitExit()
|
||||||
account := "0x02f0d131f1f97aef08aec6e3291b957d9efe7105"
|
account := "0x02f0d131f1f97aef08aec6e3291b957d9efe7105"
|
||||||
server := startGethWithIpc(t, "lightserver", "--allow-insecure-unlock", "--datadir", datadir, "--password", "./testdata/password.txt", "--unlock", account, "--mine", "--light.serve=100", "--light.maxpeers=1", "--nodiscover", "--nat=extip:127.0.0.1", "--verbosity=4")
|
server := startGethWithIpc(t, "lightserver", "--allow-insecure-unlock", "--datadir", datadir, "--password", "./testdata/password.txt", "--unlock", account, "--mine", "--light.serve=100", "--light.maxpeers=1", "--nodiscover", "--nat=extip:127.0.0.1", "--verbosity=4")
|
||||||
return server
|
return server
|
||||||
|
|
|
@ -44,7 +44,7 @@ import (
|
||||||
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
||||||
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||||
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -208,7 +208,7 @@ func init() {
|
||||||
app.Action = geth
|
app.Action = geth
|
||||||
app.HideVersion = true // we have a command to print the version
|
app.HideVersion = true // we have a command to print the version
|
||||||
app.Copyright = "Copyright 2013-2022 The go-ethereum Authors"
|
app.Copyright = "Copyright 2013-2022 The go-ethereum Authors"
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
// See chaincmd.go:
|
// See chaincmd.go:
|
||||||
initCommand,
|
initCommand,
|
||||||
importCommand,
|
importCommand,
|
||||||
|
@ -242,13 +242,16 @@ func init() {
|
||||||
}
|
}
|
||||||
sort.Sort(cli.CommandsByName(app.Commands))
|
sort.Sort(cli.CommandsByName(app.Commands))
|
||||||
|
|
||||||
app.Flags = utils.GroupFlags(nodeFlags,
|
app.Flags = utils.GroupFlags(
|
||||||
|
nodeFlags,
|
||||||
rpcFlags,
|
rpcFlags,
|
||||||
consoleFlags,
|
consoleFlags,
|
||||||
debug.Flags,
|
debug.Flags,
|
||||||
metricsFlags)
|
metricsFlags,
|
||||||
|
)
|
||||||
|
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
|
flags.MigrateGlobalFlags(ctx)
|
||||||
return debug.Setup(ctx)
|
return debug.Setup(ctx)
|
||||||
}
|
}
|
||||||
app.After = func(ctx *cli.Context) error {
|
app.After = func(ctx *cli.Context) error {
|
||||||
|
@ -270,22 +273,22 @@ func main() {
|
||||||
func prepare(ctx *cli.Context) {
|
func prepare(ctx *cli.Context) {
|
||||||
// If we're running a known preset, log it for convenience.
|
// If we're running a known preset, log it for convenience.
|
||||||
switch {
|
switch {
|
||||||
case ctx.GlobalIsSet(utils.RopstenFlag.Name):
|
case ctx.IsSet(utils.RopstenFlag.Name):
|
||||||
log.Info("Starting Geth on Ropsten testnet...")
|
log.Info("Starting Geth on Ropsten testnet...")
|
||||||
|
|
||||||
case ctx.GlobalIsSet(utils.RinkebyFlag.Name):
|
case ctx.IsSet(utils.RinkebyFlag.Name):
|
||||||
log.Info("Starting Geth on Rinkeby testnet...")
|
log.Info("Starting Geth on Rinkeby testnet...")
|
||||||
|
|
||||||
case ctx.GlobalIsSet(utils.GoerliFlag.Name):
|
case ctx.IsSet(utils.GoerliFlag.Name):
|
||||||
log.Info("Starting Geth on Görli testnet...")
|
log.Info("Starting Geth on Görli testnet...")
|
||||||
|
|
||||||
case ctx.GlobalIsSet(utils.SepoliaFlag.Name):
|
case ctx.IsSet(utils.SepoliaFlag.Name):
|
||||||
log.Info("Starting Geth on Sepolia testnet...")
|
log.Info("Starting Geth on Sepolia testnet...")
|
||||||
|
|
||||||
case ctx.GlobalIsSet(utils.KilnFlag.Name):
|
case ctx.IsSet(utils.KilnFlag.Name):
|
||||||
log.Info("Starting Geth on Kiln testnet...")
|
log.Info("Starting Geth on Kiln testnet...")
|
||||||
|
|
||||||
case ctx.GlobalIsSet(utils.DeveloperFlag.Name):
|
case ctx.IsSet(utils.DeveloperFlag.Name):
|
||||||
log.Info("Starting Geth in ephemeral dev mode...")
|
log.Info("Starting Geth in ephemeral dev mode...")
|
||||||
log.Warn(`You are running Geth in --dev mode. Please note the following:
|
log.Warn(`You are running Geth in --dev mode. Please note the following:
|
||||||
|
|
||||||
|
@ -303,27 +306,27 @@ func prepare(ctx *cli.Context) {
|
||||||
to 0, and discovery is disabled.
|
to 0, and discovery is disabled.
|
||||||
`)
|
`)
|
||||||
|
|
||||||
case !ctx.GlobalIsSet(utils.NetworkIdFlag.Name):
|
case !ctx.IsSet(utils.NetworkIdFlag.Name):
|
||||||
log.Info("Starting Geth on Ethereum mainnet...")
|
log.Info("Starting Geth on Ethereum mainnet...")
|
||||||
}
|
}
|
||||||
// If we're a full node on mainnet without --cache specified, bump default cache allowance
|
// If we're a full node on mainnet without --cache specified, bump default cache allowance
|
||||||
if ctx.GlobalString(utils.SyncModeFlag.Name) != "light" && !ctx.GlobalIsSet(utils.CacheFlag.Name) && !ctx.GlobalIsSet(utils.NetworkIdFlag.Name) {
|
if ctx.String(utils.SyncModeFlag.Name) != "light" && !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
||||||
// Make sure we're not on any supported preconfigured testnet either
|
// Make sure we're not on any supported preconfigured testnet either
|
||||||
if !ctx.GlobalIsSet(utils.RopstenFlag.Name) &&
|
if !ctx.IsSet(utils.RopstenFlag.Name) &&
|
||||||
!ctx.GlobalIsSet(utils.SepoliaFlag.Name) &&
|
!ctx.IsSet(utils.SepoliaFlag.Name) &&
|
||||||
!ctx.GlobalIsSet(utils.RinkebyFlag.Name) &&
|
!ctx.IsSet(utils.RinkebyFlag.Name) &&
|
||||||
!ctx.GlobalIsSet(utils.GoerliFlag.Name) &&
|
!ctx.IsSet(utils.GoerliFlag.Name) &&
|
||||||
!ctx.GlobalIsSet(utils.KilnFlag.Name) &&
|
!ctx.IsSet(utils.KilnFlag.Name) &&
|
||||||
!ctx.GlobalIsSet(utils.DeveloperFlag.Name) {
|
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||||
// Nope, we're really on mainnet. Bump that cache up!
|
// Nope, we're really on mainnet. Bump that cache up!
|
||||||
log.Info("Bumping default cache on mainnet", "provided", ctx.GlobalInt(utils.CacheFlag.Name), "updated", 4096)
|
log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)
|
||||||
ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(4096))
|
ctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we're running a light client on any network, drop the cache to some meaningfully low amount
|
// If we're running a light client on any network, drop the cache to some meaningfully low amount
|
||||||
if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" && !ctx.GlobalIsSet(utils.CacheFlag.Name) {
|
if ctx.String(utils.SyncModeFlag.Name) == "light" && !ctx.IsSet(utils.CacheFlag.Name) {
|
||||||
log.Info("Dropping default light client cache", "provided", ctx.GlobalInt(utils.CacheFlag.Name), "updated", 128)
|
log.Info("Dropping default light client cache", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 128)
|
||||||
ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(128))
|
ctx.Set(utils.CacheFlag.Name, strconv.Itoa(128))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start metrics export if enabled
|
// Start metrics export if enabled
|
||||||
|
@ -337,7 +340,7 @@ func prepare(ctx *cli.Context) {
|
||||||
// It creates a default node based on the command line arguments and runs it in
|
// It creates a default node based on the command line arguments and runs it in
|
||||||
// blocking mode, waiting for it to be shut down.
|
// blocking mode, waiting for it to be shut down.
|
||||||
func geth(ctx *cli.Context) error {
|
func geth(ctx *cli.Context) error {
|
||||||
if args := ctx.Args(); len(args) > 0 {
|
if args := ctx.Args().Slice(); len(args) > 0 {
|
||||||
return fmt.Errorf("invalid command: %q", args[0])
|
return fmt.Errorf("invalid command: %q", args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +411,7 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
|
||||||
|
|
||||||
// Spawn a standalone goroutine for status synchronization monitoring,
|
// Spawn a standalone goroutine for status synchronization monitoring,
|
||||||
// close the node when synchronization is complete if user required.
|
// close the node when synchronization is complete if user required.
|
||||||
if ctx.GlobalBool(utils.ExitWhenSyncedFlag.Name) {
|
if ctx.Bool(utils.ExitWhenSyncedFlag.Name) {
|
||||||
go func() {
|
go func() {
|
||||||
sub := stack.EventMux().Subscribe(downloader.DoneEvent{})
|
sub := stack.EventMux().Subscribe(downloader.DoneEvent{})
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
@ -431,9 +434,9 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start auxiliary services if enabled
|
// Start auxiliary services if enabled
|
||||||
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) {
|
if ctx.Bool(utils.MiningEnabledFlag.Name) || ctx.Bool(utils.DeveloperFlag.Name) {
|
||||||
// Mining only makes sense if a full Ethereum node is running
|
// Mining only makes sense if a full Ethereum node is running
|
||||||
if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
|
if ctx.String(utils.SyncModeFlag.Name) == "light" {
|
||||||
utils.Fatalf("Light clients do not support mining")
|
utils.Fatalf("Light clients do not support mining")
|
||||||
}
|
}
|
||||||
ethBackend, ok := backend.(*eth.EthAPIBackend)
|
ethBackend, ok := backend.(*eth.EthAPIBackend)
|
||||||
|
@ -441,10 +444,10 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
|
||||||
utils.Fatalf("Ethereum service not running")
|
utils.Fatalf("Ethereum service not running")
|
||||||
}
|
}
|
||||||
// Set the gas price to the limits from the CLI and start mining
|
// Set the gas price to the limits from the CLI and start mining
|
||||||
gasprice := utils.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
|
gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
|
||||||
ethBackend.TxPool().SetGasPrice(gasprice)
|
ethBackend.TxPool().SetGasPrice(gasprice)
|
||||||
// start mining
|
// start mining
|
||||||
threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name)
|
threads := ctx.Int(utils.MinerThreadsFlag.Name)
|
||||||
if err := ethBackend.StartMining(threads); err != nil {
|
if err := ethBackend.StartMining(threads); err != nil {
|
||||||
utils.Fatalf("Failed to start mining: %v", err)
|
utils.Fatalf("Failed to start mining: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -454,7 +457,7 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
|
||||||
// unlockAccounts unlocks any account specifically requested.
|
// unlockAccounts unlocks any account specifically requested.
|
||||||
func unlockAccounts(ctx *cli.Context, stack *node.Node) {
|
func unlockAccounts(ctx *cli.Context, stack *node.Node) {
|
||||||
var unlocks []string
|
var unlocks []string
|
||||||
inputs := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
|
inputs := strings.Split(ctx.String(utils.UnlockedAccountFlag.Name), ",")
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
if trimmed := strings.TrimSpace(input); trimmed != "" {
|
if trimmed := strings.TrimSpace(input); trimmed != "" {
|
||||||
unlocks = append(unlocks, trimmed)
|
unlocks = append(unlocks, trimmed)
|
||||||
|
|
|
@ -26,28 +26,27 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
VersionCheckUrlFlag = cli.StringFlag{
|
VersionCheckUrlFlag = &cli.StringFlag{
|
||||||
Name: "check.url",
|
Name: "check.url",
|
||||||
Usage: "URL to use when checking vulnerabilities",
|
Usage: "URL to use when checking vulnerabilities",
|
||||||
Value: "https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json",
|
Value: "https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json",
|
||||||
}
|
}
|
||||||
VersionCheckVersionFlag = cli.StringFlag{
|
VersionCheckVersionFlag = &cli.StringFlag{
|
||||||
Name: "check.version",
|
Name: "check.version",
|
||||||
Usage: "Version to check",
|
Usage: "Version to check",
|
||||||
Value: fmt.Sprintf("Geth/v%v/%v-%v/%v",
|
Value: fmt.Sprintf("Geth/v%v/%v-%v/%v",
|
||||||
params.VersionWithCommit(gitCommit, gitDate),
|
params.VersionWithCommit(gitCommit, gitDate),
|
||||||
runtime.GOOS, runtime.GOARCH, runtime.Version()),
|
runtime.GOOS, runtime.GOARCH, runtime.Version()),
|
||||||
}
|
}
|
||||||
makecacheCommand = cli.Command{
|
makecacheCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(makecache),
|
Action: makecache,
|
||||||
Name: "makecache",
|
Name: "makecache",
|
||||||
Usage: "Generate ethash verification cache (for testing)",
|
Usage: "Generate ethash verification cache (for testing)",
|
||||||
ArgsUsage: "<blockNum> <outputDir>",
|
ArgsUsage: "<blockNum> <outputDir>",
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The makecache command generates an ethash cache in <outputDir>.
|
The makecache command generates an ethash cache in <outputDir>.
|
||||||
|
|
||||||
|
@ -55,12 +54,11 @@ This command exists to support the system testing project.
|
||||||
Regular users do not need to execute it.
|
Regular users do not need to execute it.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
makedagCommand = cli.Command{
|
makedagCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(makedag),
|
Action: makedag,
|
||||||
Name: "makedag",
|
Name: "makedag",
|
||||||
Usage: "Generate ethash mining DAG (for testing)",
|
Usage: "Generate ethash mining DAG (for testing)",
|
||||||
ArgsUsage: "<blockNum> <outputDir>",
|
ArgsUsage: "<blockNum> <outputDir>",
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The makedag command generates an ethash DAG in <outputDir>.
|
The makedag command generates an ethash DAG in <outputDir>.
|
||||||
|
|
||||||
|
@ -68,43 +66,40 @@ This command exists to support the system testing project.
|
||||||
Regular users do not need to execute it.
|
Regular users do not need to execute it.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
versionCommand = cli.Command{
|
versionCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(version),
|
Action: version,
|
||||||
Name: "version",
|
Name: "version",
|
||||||
Usage: "Print version numbers",
|
Usage: "Print version numbers",
|
||||||
ArgsUsage: " ",
|
ArgsUsage: " ",
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The output of this command is supposed to be machine-readable.
|
The output of this command is supposed to be machine-readable.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
versionCheckCommand = cli.Command{
|
versionCheckCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(versionCheck),
|
Action: versionCheck,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
VersionCheckUrlFlag,
|
VersionCheckUrlFlag,
|
||||||
VersionCheckVersionFlag,
|
VersionCheckVersionFlag,
|
||||||
},
|
},
|
||||||
Name: "version-check",
|
Name: "version-check",
|
||||||
Usage: "Checks (online) whether the current version suffers from any known security vulnerabilities",
|
Usage: "Checks (online) for known Geth security vulnerabilities",
|
||||||
ArgsUsage: "<versionstring (optional)>",
|
ArgsUsage: "<versionstring (optional)>",
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Description: `
|
Description: `
|
||||||
The version-check command fetches vulnerability-information from https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json,
|
The version-check command fetches vulnerability-information from https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json,
|
||||||
and displays information about any security vulnerabilities that affect the currently executing version.
|
and displays information about any security vulnerabilities that affect the currently executing version.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
licenseCommand = cli.Command{
|
licenseCommand = &cli.Command{
|
||||||
Action: utils.MigrateFlags(license),
|
Action: license,
|
||||||
Name: "license",
|
Name: "license",
|
||||||
Usage: "Display license information",
|
Usage: "Display license information",
|
||||||
ArgsUsage: " ",
|
ArgsUsage: " ",
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// makecache generates an ethash verification cache into the provided folder.
|
// makecache generates an ethash verification cache into the provided folder.
|
||||||
func makecache(ctx *cli.Context) error {
|
func makecache(ctx *cli.Context) error {
|
||||||
args := ctx.Args()
|
args := ctx.Args().Slice()
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
utils.Fatalf(`Usage: geth makecache <block number> <outputdir>`)
|
utils.Fatalf(`Usage: geth makecache <block number> <outputdir>`)
|
||||||
}
|
}
|
||||||
|
@ -119,7 +114,7 @@ func makecache(ctx *cli.Context) error {
|
||||||
|
|
||||||
// makedag generates an ethash mining DAG into the provided folder.
|
// makedag generates an ethash mining DAG into the provided folder.
|
||||||
func makedag(ctx *cli.Context) error {
|
func makedag(ctx *cli.Context) error {
|
||||||
args := ctx.Args()
|
args := ctx.Args().Slice()
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
|
utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
cli "gopkg.in/urfave/cli.v1"
|
cli "github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -46,18 +46,16 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
snapshotCommand = cli.Command{
|
snapshotCommand = &cli.Command{
|
||||||
Name: "snapshot",
|
Name: "snapshot",
|
||||||
Usage: "A set of commands based on the snapshot",
|
Usage: "A set of commands based on the snapshot",
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Description: "",
|
Description: "",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "prune-state",
|
Name: "prune-state",
|
||||||
Usage: "Prune stale ethereum state data based on the snapshot",
|
Usage: "Prune stale ethereum state data based on the snapshot",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: utils.MigrateFlags(pruneState),
|
Action: pruneState,
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Flags: utils.GroupFlags([]cli.Flag{
|
Flags: utils.GroupFlags([]cli.Flag{
|
||||||
utils.CacheTrieJournalFlag,
|
utils.CacheTrieJournalFlag,
|
||||||
utils.BloomFilterSizeFlag,
|
utils.BloomFilterSizeFlag,
|
||||||
|
@ -81,8 +79,7 @@ the trie clean cache with default directory will be deleted.
|
||||||
Name: "verify-state",
|
Name: "verify-state",
|
||||||
Usage: "Recalculate state hash based on the snapshot for verification",
|
Usage: "Recalculate state hash based on the snapshot for verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: utils.MigrateFlags(verifyState),
|
Action: verifyState,
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot verify-state <state-root>
|
geth snapshot verify-state <state-root>
|
||||||
|
@ -95,8 +92,7 @@ In other words, this command does the snapshot to trie conversion.
|
||||||
Name: "check-dangling-storage",
|
Name: "check-dangling-storage",
|
||||||
Usage: "Check that there is no 'dangling' snap storage",
|
Usage: "Check that there is no 'dangling' snap storage",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: utils.MigrateFlags(checkDanglingStorage),
|
Action: checkDanglingStorage,
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot check-dangling-storage <state-root> traverses the snap storage
|
geth snapshot check-dangling-storage <state-root> traverses the snap storage
|
||||||
|
@ -107,8 +103,7 @@ data, and verifies that all snapshot storage data has a corresponding account.
|
||||||
Name: "inspect-account",
|
Name: "inspect-account",
|
||||||
Usage: "Check all snapshot layers for the a specific account",
|
Usage: "Check all snapshot layers for the a specific account",
|
||||||
ArgsUsage: "<address | hash>",
|
ArgsUsage: "<address | hash>",
|
||||||
Action: utils.MigrateFlags(checkAccount),
|
Action: checkAccount,
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
|
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
|
||||||
|
@ -119,8 +114,7 @@ information about the specified address.
|
||||||
Name: "traverse-state",
|
Name: "traverse-state",
|
||||||
Usage: "Traverse the state with given root hash and perform quick verification",
|
Usage: "Traverse the state with given root hash and perform quick verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: utils.MigrateFlags(traverseState),
|
Action: traverseState,
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot traverse-state <state-root>
|
geth snapshot traverse-state <state-root>
|
||||||
|
@ -135,8 +129,7 @@ It's also usable without snapshot enabled.
|
||||||
Name: "traverse-rawstate",
|
Name: "traverse-rawstate",
|
||||||
Usage: "Traverse the state with given root hash and perform detailed verification",
|
Usage: "Traverse the state with given root hash and perform detailed verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: utils.MigrateFlags(traverseRawState),
|
Action: traverseRawState,
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot traverse-rawstate <state-root>
|
geth snapshot traverse-rawstate <state-root>
|
||||||
|
@ -152,8 +145,7 @@ It's also usable without snapshot enabled.
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)",
|
Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)",
|
||||||
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
||||||
Action: utils.MigrateFlags(dumpState),
|
Action: dumpState,
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Flags: utils.GroupFlags([]cli.Flag{
|
Flags: utils.GroupFlags([]cli.Flag{
|
||||||
utils.ExcludeCodeFlag,
|
utils.ExcludeCodeFlag,
|
||||||
utils.ExcludeStorageFlag,
|
utils.ExcludeStorageFlag,
|
||||||
|
@ -177,7 +169,7 @@ func pruneState(ctx *cli.Context) error {
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
||||||
pruner, err := pruner.NewPruner(chaindb, stack.ResolvePath(""), stack.ResolvePath(config.Eth.TrieCleanCacheJournal), ctx.GlobalUint64(utils.BloomFilterSizeFlag.Name))
|
pruner, err := pruner.NewPruner(chaindb, stack.ResolvePath(""), stack.ResolvePath(config.Eth.TrieCleanCacheJournal), ctx.Uint64(utils.BloomFilterSizeFlag.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to open snapshot tree", "err", err)
|
log.Error("Failed to open snapshot tree", "err", err)
|
||||||
return err
|
return err
|
||||||
|
@ -188,7 +180,7 @@ func pruneState(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
var targetRoot common.Hash
|
var targetRoot common.Hash
|
||||||
if ctx.NArg() == 1 {
|
if ctx.NArg() == 1 {
|
||||||
targetRoot, err = parseRoot(ctx.Args()[0])
|
targetRoot, err = parseRoot(ctx.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to resolve state root", "err", err)
|
log.Error("Failed to resolve state root", "err", err)
|
||||||
return err
|
return err
|
||||||
|
@ -222,7 +214,7 @@ func verifyState(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
var root = headBlock.Root()
|
var root = headBlock.Root()
|
||||||
if ctx.NArg() == 1 {
|
if ctx.NArg() == 1 {
|
||||||
root, err = parseRoot(ctx.Args()[0])
|
root, err = parseRoot(ctx.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to resolve state root", "err", err)
|
log.Error("Failed to resolve state root", "err", err)
|
||||||
return err
|
return err
|
||||||
|
@ -267,7 +259,7 @@ func traverseState(ctx *cli.Context) error {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if ctx.NArg() == 1 {
|
if ctx.NArg() == 1 {
|
||||||
root, err = parseRoot(ctx.Args()[0])
|
root, err = parseRoot(ctx.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to resolve state root", "err", err)
|
log.Error("Failed to resolve state root", "err", err)
|
||||||
return err
|
return err
|
||||||
|
@ -356,7 +348,7 @@ func traverseRawState(ctx *cli.Context) error {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if ctx.NArg() == 1 {
|
if ctx.NArg() == 1 {
|
||||||
root, err = parseRoot(ctx.Args()[0])
|
root, err = parseRoot(ctx.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to resolve state root", "err", err)
|
log.Error("Failed to resolve state root", "err", err)
|
||||||
return err
|
return err
|
||||||
|
@ -558,12 +550,12 @@ func checkAccount(ctx *cli.Context) error {
|
||||||
hash common.Hash
|
hash common.Hash
|
||||||
addr common.Address
|
addr common.Address
|
||||||
)
|
)
|
||||||
switch len(ctx.Args()[0]) {
|
switch arg := ctx.Args().First(); len(arg) {
|
||||||
case 40, 42:
|
case 40, 42:
|
||||||
addr = common.HexToAddress(ctx.Args()[0])
|
addr = common.HexToAddress(arg)
|
||||||
hash = crypto.Keccak256Hash(addr.Bytes())
|
hash = crypto.Keccak256Hash(addr.Bytes())
|
||||||
case 64, 66:
|
case 64, 66:
|
||||||
hash = common.HexToHash(ctx.Args()[0])
|
hash = common.HexToHash(arg)
|
||||||
default:
|
default:
|
||||||
return errors.New("malformed address or hash")
|
return errors.New("malformed address or hash")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,301 +0,0 @@
|
||||||
// Copyright 2015 The go-ethereum Authors
|
|
||||||
// This file is part of go-ethereum.
|
|
||||||
//
|
|
||||||
// go-ethereum is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// go-ethereum is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Contains the geth command usage template and generator.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
||||||
"github.com/ethereum/go-ethereum/internal/debug"
|
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AppHelpFlagGroups is the application flags, grouped by functionality.
|
|
||||||
var AppHelpFlagGroups = []flags.FlagGroup{
|
|
||||||
{
|
|
||||||
Name: "ETHEREUM",
|
|
||||||
Flags: utils.GroupFlags([]cli.Flag{
|
|
||||||
configFileFlag,
|
|
||||||
utils.MinFreeDiskSpaceFlag,
|
|
||||||
utils.KeyStoreDirFlag,
|
|
||||||
utils.USBFlag,
|
|
||||||
utils.SmartCardDaemonPathFlag,
|
|
||||||
utils.NetworkIdFlag,
|
|
||||||
utils.SyncModeFlag,
|
|
||||||
utils.ExitWhenSyncedFlag,
|
|
||||||
utils.GCModeFlag,
|
|
||||||
utils.TxLookupLimitFlag,
|
|
||||||
utils.EthStatsURLFlag,
|
|
||||||
utils.IdentityFlag,
|
|
||||||
utils.LightKDFFlag,
|
|
||||||
utils.EthRequiredBlocksFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "LIGHT CLIENT",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.LightServeFlag,
|
|
||||||
utils.LightIngressFlag,
|
|
||||||
utils.LightEgressFlag,
|
|
||||||
utils.LightMaxPeersFlag,
|
|
||||||
utils.UltraLightServersFlag,
|
|
||||||
utils.UltraLightFractionFlag,
|
|
||||||
utils.UltraLightOnlyAnnounceFlag,
|
|
||||||
utils.LightNoPruneFlag,
|
|
||||||
utils.LightNoSyncServeFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "DEVELOPER CHAIN",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.DeveloperFlag,
|
|
||||||
utils.DeveloperPeriodFlag,
|
|
||||||
utils.DeveloperGasLimitFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "ETHASH",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.EthashCacheDirFlag,
|
|
||||||
utils.EthashCachesInMemoryFlag,
|
|
||||||
utils.EthashCachesOnDiskFlag,
|
|
||||||
utils.EthashCachesLockMmapFlag,
|
|
||||||
utils.EthashDatasetDirFlag,
|
|
||||||
utils.EthashDatasetsInMemoryFlag,
|
|
||||||
utils.EthashDatasetsOnDiskFlag,
|
|
||||||
utils.EthashDatasetsLockMmapFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "TRANSACTION POOL",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.TxPoolLocalsFlag,
|
|
||||||
utils.TxPoolNoLocalsFlag,
|
|
||||||
utils.TxPoolJournalFlag,
|
|
||||||
utils.TxPoolRejournalFlag,
|
|
||||||
utils.TxPoolPriceLimitFlag,
|
|
||||||
utils.TxPoolPriceBumpFlag,
|
|
||||||
utils.TxPoolAccountSlotsFlag,
|
|
||||||
utils.TxPoolGlobalSlotsFlag,
|
|
||||||
utils.TxPoolAccountQueueFlag,
|
|
||||||
utils.TxPoolGlobalQueueFlag,
|
|
||||||
utils.TxPoolLifetimeFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "PERFORMANCE TUNING",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.CacheFlag,
|
|
||||||
utils.CacheDatabaseFlag,
|
|
||||||
utils.CacheTrieFlag,
|
|
||||||
utils.CacheTrieJournalFlag,
|
|
||||||
utils.CacheTrieRejournalFlag,
|
|
||||||
utils.CacheGCFlag,
|
|
||||||
utils.CacheSnapshotFlag,
|
|
||||||
utils.CacheNoPrefetchFlag,
|
|
||||||
utils.CachePreimagesFlag,
|
|
||||||
utils.FDLimitFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "ACCOUNT",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.UnlockedAccountFlag,
|
|
||||||
utils.PasswordFileFlag,
|
|
||||||
utils.ExternalSignerFlag,
|
|
||||||
utils.InsecureUnlockAllowedFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "API AND CONSOLE",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.IPCDisabledFlag,
|
|
||||||
utils.IPCPathFlag,
|
|
||||||
utils.HTTPEnabledFlag,
|
|
||||||
utils.HTTPListenAddrFlag,
|
|
||||||
utils.HTTPPortFlag,
|
|
||||||
utils.HTTPApiFlag,
|
|
||||||
utils.HTTPPathPrefixFlag,
|
|
||||||
utils.HTTPCORSDomainFlag,
|
|
||||||
utils.HTTPVirtualHostsFlag,
|
|
||||||
utils.WSEnabledFlag,
|
|
||||||
utils.WSListenAddrFlag,
|
|
||||||
utils.WSPortFlag,
|
|
||||||
utils.WSApiFlag,
|
|
||||||
utils.WSPathPrefixFlag,
|
|
||||||
utils.WSAllowedOriginsFlag,
|
|
||||||
utils.JWTSecretFlag,
|
|
||||||
utils.AuthListenFlag,
|
|
||||||
utils.AuthPortFlag,
|
|
||||||
utils.AuthVirtualHostsFlag,
|
|
||||||
utils.GraphQLEnabledFlag,
|
|
||||||
utils.GraphQLCORSDomainFlag,
|
|
||||||
utils.GraphQLVirtualHostsFlag,
|
|
||||||
utils.RPCGlobalGasCapFlag,
|
|
||||||
utils.RPCGlobalEVMTimeoutFlag,
|
|
||||||
utils.RPCGlobalTxFeeCapFlag,
|
|
||||||
utils.AllowUnprotectedTxs,
|
|
||||||
utils.JSpathFlag,
|
|
||||||
utils.ExecFlag,
|
|
||||||
utils.PreloadJSFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "NETWORKING",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.BootnodesFlag,
|
|
||||||
utils.DNSDiscoveryFlag,
|
|
||||||
utils.ListenPortFlag,
|
|
||||||
utils.MaxPeersFlag,
|
|
||||||
utils.MaxPendingPeersFlag,
|
|
||||||
utils.NATFlag,
|
|
||||||
utils.NoDiscoverFlag,
|
|
||||||
utils.DiscoveryV5Flag,
|
|
||||||
utils.NetrestrictFlag,
|
|
||||||
utils.NodeKeyFileFlag,
|
|
||||||
utils.NodeKeyHexFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "MINER",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.MiningEnabledFlag,
|
|
||||||
utils.MinerThreadsFlag,
|
|
||||||
utils.MinerNotifyFlag,
|
|
||||||
utils.MinerNotifyFullFlag,
|
|
||||||
utils.MinerGasPriceFlag,
|
|
||||||
utils.MinerGasLimitFlag,
|
|
||||||
utils.MinerEtherbaseFlag,
|
|
||||||
utils.MinerExtraDataFlag,
|
|
||||||
utils.MinerRecommitIntervalFlag,
|
|
||||||
utils.MinerNoVerifyFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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.FakePoWFlag,
|
|
||||||
utils.NoCompactionFlag,
|
|
||||||
}, debug.Flags...),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "METRICS AND STATS",
|
|
||||||
Flags: metricsFlags,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "ALIASED (deprecated)",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.NoUSBFlag,
|
|
||||||
utils.LegacyWhitelistFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "MISC",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.SnapshotFlag,
|
|
||||||
utils.BloomFilterSizeFlag,
|
|
||||||
utils.IgnoreLegacyReceiptsFlag,
|
|
||||||
cli.HelpFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Override the default app help template
|
|
||||||
cli.AppHelpTemplate = flags.AppHelpTemplate
|
|
||||||
|
|
||||||
// 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 == flags.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{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deprecated := make(map[string]struct{})
|
|
||||||
for _, flag := range utils.DeprecatedFlags {
|
|
||||||
deprecated[flag.String()] = struct{}{}
|
|
||||||
}
|
|
||||||
// Only add uncategorized flags if they are not deprecated
|
|
||||||
var uncategorized []cli.Flag
|
|
||||||
for _, flag := range data.(*cli.App).Flags {
|
|
||||||
if _, ok := categorized[flag.String()]; !ok {
|
|
||||||
if _, ok := deprecated[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, flags.HelpData{App: data, FlagGroups: AppHelpFlagGroups})
|
|
||||||
} else if tmpl == flags.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[flags.FlagCategory(flag, AppHelpFlagGroups)] = append(categorized[flags.FlagCategory(flag, AppHelpFlagGroups)], flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort to get a stable ordering
|
|
||||||
sorted := make([]flags.FlagGroup, 0, len(categorized))
|
|
||||||
for cat, flgs := range categorized {
|
|
||||||
sorted = append(sorted, flags.FlagGroup{Name: cat, Flags: flgs})
|
|
||||||
}
|
|
||||||
sort.Sort(flags.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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -28,7 +28,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/jedisct1/go-minisign"
|
"github.com/jedisct1/go-minisign"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var gethPubKeys []string = []string{
|
var gethPubKeys []string = []string{
|
||||||
|
|
|
@ -46,71 +46,77 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/p2p/simulations"
|
"github.com/ethereum/go-ethereum/p2p/simulations"
|
||||||
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var client *simulations.Client
|
var client *simulations.Client
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// global command flags
|
// global command flags
|
||||||
apiFlag = cli.StringFlag{
|
apiFlag = &cli.StringFlag{
|
||||||
Name: "api",
|
Name: "api",
|
||||||
Value: "http://localhost:8888",
|
Value: "http://localhost:8888",
|
||||||
Usage: "simulation API URL",
|
Usage: "simulation API URL",
|
||||||
EnvVar: "P2PSIM_API_URL",
|
EnvVars: []string{"P2PSIM_API_URL"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// events subcommand flags
|
// events subcommand flags
|
||||||
currentFlag = cli.BoolFlag{
|
currentFlag = &cli.BoolFlag{
|
||||||
Name: "current",
|
Name: "current",
|
||||||
Usage: "get existing nodes and conns first",
|
Usage: "get existing nodes and conns first",
|
||||||
}
|
}
|
||||||
filterFlag = cli.StringFlag{
|
filterFlag = &cli.StringFlag{
|
||||||
Name: "filter",
|
Name: "filter",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "message filter",
|
Usage: "message filter",
|
||||||
}
|
}
|
||||||
|
|
||||||
// node create subcommand flags
|
// node create subcommand flags
|
||||||
nameFlag = cli.StringFlag{
|
nameFlag = &cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "node name",
|
Usage: "node name",
|
||||||
}
|
}
|
||||||
servicesFlag = cli.StringFlag{
|
servicesFlag = &cli.StringFlag{
|
||||||
Name: "services",
|
Name: "services",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "node services (comma separated)",
|
Usage: "node services (comma separated)",
|
||||||
}
|
}
|
||||||
keyFlag = cli.StringFlag{
|
keyFlag = &cli.StringFlag{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "node private key (hex encoded)",
|
Usage: "node private key (hex encoded)",
|
||||||
}
|
}
|
||||||
|
|
||||||
// node rpc subcommand flags
|
// node rpc subcommand flags
|
||||||
subscribeFlag = cli.BoolFlag{
|
subscribeFlag = &cli.BoolFlag{
|
||||||
Name: "subscribe",
|
Name: "subscribe",
|
||||||
Usage: "method is a subscription",
|
Usage: "method is a subscription",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Git information set by linker when building with ci.go.
|
||||||
|
gitCommit string
|
||||||
|
gitDate string
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := flags.NewApp(gitCommit, gitDate, "devp2p simulation command-line client")
|
||||||
app.Usage = "devp2p simulation command-line client"
|
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
apiFlag,
|
apiFlag,
|
||||||
}
|
}
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
client = simulations.NewClient(ctx.GlobalString(apiFlag.Name))
|
client = simulations.NewClient(ctx.String(apiFlag.Name))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "show",
|
Name: "show",
|
||||||
Usage: "show network information",
|
Usage: "show network information",
|
||||||
|
@ -139,7 +145,7 @@ func main() {
|
||||||
Name: "node",
|
Name: "node",
|
||||||
Usage: "manage simulation nodes",
|
Usage: "manage simulation nodes",
|
||||||
Action: listNodes,
|
Action: listNodes,
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "list nodes",
|
Usage: "list nodes",
|
||||||
|
@ -204,7 +210,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showNetwork(ctx *cli.Context) error {
|
func showNetwork(ctx *cli.Context) error {
|
||||||
if len(ctx.Args()) != 0 {
|
if ctx.NArg() != 0 {
|
||||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
network, err := client.GetNetwork()
|
network, err := client.GetNetwork()
|
||||||
|
@ -219,7 +225,7 @@ func showNetwork(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func streamNetwork(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)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
events := make(chan *simulations.Event)
|
events := make(chan *simulations.Event)
|
||||||
|
@ -245,7 +251,7 @@ func streamNetwork(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSnapshot(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)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
snap, err := client.CreateSnapshot()
|
snap, err := client.CreateSnapshot()
|
||||||
|
@ -256,7 +262,7 @@ func createSnapshot(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadSnapshot(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)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
snap := &simulations.Snapshot{}
|
snap := &simulations.Snapshot{}
|
||||||
|
@ -267,7 +273,7 @@ func loadSnapshot(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func listNodes(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)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
nodes, err := client.GetNodes()
|
nodes, err := client.GetNodes()
|
||||||
|
@ -292,7 +298,7 @@ func protocolList(node *p2p.NodeInfo) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNode(ctx *cli.Context) error {
|
func createNode(ctx *cli.Context) error {
|
||||||
if len(ctx.Args()) != 0 {
|
if ctx.NArg() != 0 {
|
||||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
config := adapters.RandomNodeConfig()
|
config := adapters.RandomNodeConfig()
|
||||||
|
@ -317,11 +323,10 @@ func createNode(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showNode(ctx *cli.Context) error {
|
func showNode(ctx *cli.Context) error {
|
||||||
args := ctx.Args()
|
if ctx.NArg() != 1 {
|
||||||
if len(args) != 1 {
|
|
||||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
nodeName := args[0]
|
nodeName := ctx.Args().First()
|
||||||
node, err := client.GetNode(nodeName)
|
node, err := client.GetNode(nodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -342,11 +347,10 @@ func showNode(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func startNode(ctx *cli.Context) error {
|
func startNode(ctx *cli.Context) error {
|
||||||
args := ctx.Args()
|
if ctx.NArg() != 1 {
|
||||||
if len(args) != 1 {
|
|
||||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
nodeName := args[0]
|
nodeName := ctx.Args().First()
|
||||||
if err := client.StartNode(nodeName); err != nil {
|
if err := client.StartNode(nodeName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -355,11 +359,10 @@ func startNode(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopNode(ctx *cli.Context) error {
|
func stopNode(ctx *cli.Context) error {
|
||||||
args := ctx.Args()
|
if ctx.NArg() != 1 {
|
||||||
if len(args) != 1 {
|
|
||||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
nodeName := args[0]
|
nodeName := ctx.Args().First()
|
||||||
if err := client.StopNode(nodeName); err != nil {
|
if err := client.StopNode(nodeName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -368,12 +371,12 @@ func stopNode(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectNode(ctx *cli.Context) error {
|
func connectNode(ctx *cli.Context) error {
|
||||||
args := ctx.Args()
|
if ctx.NArg() != 2 {
|
||||||
if len(args) != 2 {
|
|
||||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
nodeName := args[0]
|
args := ctx.Args()
|
||||||
peerName := args[1]
|
nodeName := args.Get(0)
|
||||||
|
peerName := args.Get(1)
|
||||||
if err := client.ConnectNode(nodeName, peerName); err != nil {
|
if err := client.ConnectNode(nodeName, peerName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -383,11 +386,11 @@ func connectNode(ctx *cli.Context) error {
|
||||||
|
|
||||||
func disconnectNode(ctx *cli.Context) error {
|
func disconnectNode(ctx *cli.Context) error {
|
||||||
args := ctx.Args()
|
args := ctx.Args()
|
||||||
if len(args) != 2 {
|
if args.Len() != 2 {
|
||||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
nodeName := args[0]
|
nodeName := args.Get(0)
|
||||||
peerName := args[1]
|
peerName := args.Get(1)
|
||||||
if err := client.DisconnectNode(nodeName, peerName); err != nil {
|
if err := client.DisconnectNode(nodeName, peerName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -397,21 +400,21 @@ func disconnectNode(ctx *cli.Context) error {
|
||||||
|
|
||||||
func rpcNode(ctx *cli.Context) error {
|
func rpcNode(ctx *cli.Context) error {
|
||||||
args := ctx.Args()
|
args := ctx.Args()
|
||||||
if len(args) < 2 {
|
if args.Len() < 2 {
|
||||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||||
}
|
}
|
||||||
nodeName := args[0]
|
nodeName := args.Get(0)
|
||||||
method := args[1]
|
method := args.Get(1)
|
||||||
rpcClient, err := client.RPCClient(context.Background(), nodeName)
|
rpcClient, err := client.RPCClient(context.Background(), nodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if ctx.Bool(subscribeFlag.Name) {
|
if ctx.Bool(subscribeFlag.Name) {
|
||||||
return rpcSubscribe(rpcClient, ctx.App.Writer, method, args[3:]...)
|
return rpcSubscribe(rpcClient, ctx.App.Writer, method, args.Slice()[3:]...)
|
||||||
}
|
}
|
||||||
var result interface{}
|
var result interface{}
|
||||||
params := make([]interface{}, len(args[3:]))
|
params := make([]interface{}, len(args.Slice()[3:]))
|
||||||
for i, v := range args[3:] {
|
for i, v := range args.Slice()[3:] {
|
||||||
params[i] = v
|
params[i] = v
|
||||||
}
|
}
|
||||||
if err := rpcClient.Call(&result, method, params...); err != nil {
|
if err := rpcClient.Call(&result, method, params...); err != nil {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// main is just a boring entry point to set up the CLI app.
|
// main is just a boring entry point to set up the CLI app.
|
||||||
|
@ -33,11 +33,11 @@ func main() {
|
||||||
app.Name = "puppeth"
|
app.Name = "puppeth"
|
||||||
app.Usage = "assemble and maintain private Ethereum networks"
|
app.Usage = "assemble and maintain private Ethereum networks"
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "network",
|
Name: "network",
|
||||||
Usage: "name of the network to administer (no spaces or hyphens, please)",
|
Usage: "name of the network to administer (no spaces or hyphens, please)",
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "loglevel",
|
Name: "loglevel",
|
||||||
Value: 3,
|
Value: 3,
|
||||||
Usage: "log level to emit to the screen",
|
Usage: "log level to emit to the screen",
|
||||||
|
|
|
@ -41,7 +41,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -78,10 +78,10 @@ func StartNode(ctx *cli.Context, stack *node.Node, isConsole bool) {
|
||||||
defer signal.Stop(sigc)
|
defer signal.Stop(sigc)
|
||||||
|
|
||||||
minFreeDiskSpace := 2 * ethconfig.Defaults.TrieDirtyCache // Default 2 * 256Mb
|
minFreeDiskSpace := 2 * ethconfig.Defaults.TrieDirtyCache // Default 2 * 256Mb
|
||||||
if ctx.GlobalIsSet(MinFreeDiskSpaceFlag.Name) {
|
if ctx.IsSet(MinFreeDiskSpaceFlag.Name) {
|
||||||
minFreeDiskSpace = ctx.GlobalInt(MinFreeDiskSpaceFlag.Name)
|
minFreeDiskSpace = ctx.Int(MinFreeDiskSpaceFlag.Name)
|
||||||
} else if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
|
} else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
||||||
minFreeDiskSpace = 2 * ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
|
minFreeDiskSpace = 2 * ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
||||||
}
|
}
|
||||||
if minFreeDiskSpace > 0 {
|
if minFreeDiskSpace > 0 {
|
||||||
go monitorFreeDiskSpace(sigc, stack.InstanceDir(), uint64(minFreeDiskSpace)*1024*1024)
|
go monitorFreeDiskSpace(sigc, stack.InstanceDir(), uint64(minFreeDiskSpace)*1024*1024)
|
||||||
|
|
|
@ -1,211 +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"
|
|
||||||
"math/big"
|
|
||||||
"os"
|
|
||||||
"os/user"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/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 string
|
|
||||||
|
|
||||||
func (s *DirectoryString) String() string {
|
|
||||||
return string(*s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DirectoryString) Set(value string) error {
|
|
||||||
*s = DirectoryString(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
|
|
||||||
EnvVar string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f DirectoryFlag) String() string {
|
|
||||||
return cli.FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
set.Var(&f.Value, f.Name, f.Usage)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f DirectoryFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *DirectoryFlag) Set(value string) {
|
|
||||||
f.Value.Set(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func eachName(longName string, fn func(string)) {
|
|
||||||
parts := strings.Split(longName, ",")
|
|
||||||
for _, name := range parts {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
fn(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type TextMarshaler interface {
|
|
||||||
encoding.TextMarshaler
|
|
||||||
encoding.TextUnmarshaler
|
|
||||||
}
|
|
||||||
|
|
||||||
// textMarshalerVal turns a TextMarshaler into a flag.Value
|
|
||||||
type textMarshalerVal struct {
|
|
||||||
v TextMarshaler
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v textMarshalerVal) String() string {
|
|
||||||
if v.v == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
text, _ := v.v.MarshalText()
|
|
||||||
return string(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v textMarshalerVal) Set(s string) error {
|
|
||||||
return v.v.UnmarshalText([]byte(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextMarshalerFlag wraps a TextMarshaler value.
|
|
||||||
type TextMarshalerFlag struct {
|
|
||||||
Name string
|
|
||||||
Value TextMarshaler
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f TextMarshalerFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f TextMarshalerFlag) String() string {
|
|
||||||
return cli.FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f TextMarshalerFlag) Apply(set *flag.FlagSet) {
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
set.Var(textMarshalerVal{f.Value}, f.Name, f.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
|
|
||||||
EnvVar 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
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f BigFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f BigFlag) String() string {
|
|
||||||
return cli.FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f BigFlag) Apply(set *flag.FlagSet) {
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
f.Value = new(big.Int)
|
|
||||||
set.Var((*bigValue)(f.Value), f.Name, f.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))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 ""
|
|
||||||
}
|
|
1137
cmd/utils/flags.go
1137
cmd/utils/flags.go
File diff suppressed because it is too large
Load Diff
|
@ -20,15 +20,15 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ShowDeprecated = cli.Command{
|
var ShowDeprecated = &cli.Command{
|
||||||
Action: showDeprecated,
|
Action: showDeprecated,
|
||||||
Name: "show-deprecated-flags",
|
Name: "show-deprecated-flags",
|
||||||
Usage: "Show flags that have been deprecated",
|
Usage: "Show flags that have been deprecated",
|
||||||
ArgsUsage: " ",
|
ArgsUsage: " ",
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
|
||||||
Description: "Show flags that have been deprecated and will soon be removed",
|
Description: "Show flags that have been deprecated and will soon be removed",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,20 +39,22 @@ var DeprecatedFlags = []cli.Flag{
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// (Deprecated May 2020, shown in aliased flags section)
|
// (Deprecated May 2020, shown in aliased flags section)
|
||||||
NoUSBFlag = cli.BoolFlag{
|
NoUSBFlag = &cli.BoolFlag{
|
||||||
Name: "nousb",
|
Name: "nousb",
|
||||||
Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)",
|
Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)",
|
||||||
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
// (Deprecated July 2021, shown in aliased flags section)
|
// (Deprecated July 2021, shown in aliased flags section)
|
||||||
LegacyMinerGasTargetFlag = cli.Uint64Flag{
|
LegacyMinerGasTargetFlag = &cli.Uint64Flag{
|
||||||
Name: "miner.gastarget",
|
Name: "miner.gastarget",
|
||||||
Usage: "Target gas floor for mined blocks (deprecated)",
|
Usage: "Target gas floor for mined blocks (deprecated)",
|
||||||
Value: ethconfig.Defaults.Miner.GasFloor,
|
Value: ethconfig.Defaults.Miner.GasFloor,
|
||||||
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
||||||
func showDeprecated(*cli.Context) {
|
func showDeprecated(*cli.Context) error {
|
||||||
fmt.Println("--------------------------------------------------------------------")
|
fmt.Println("--------------------------------------------------------------------")
|
||||||
fmt.Println("The following flags are deprecated and will be removed in the future!")
|
fmt.Println("The following flags are deprecated and will be removed in the future!")
|
||||||
fmt.Println("--------------------------------------------------------------------")
|
fmt.Println("--------------------------------------------------------------------")
|
||||||
|
@ -61,4 +63,5 @@ func showDeprecated(*cli.Context) {
|
||||||
fmt.Println(flag.String())
|
fmt.Println(flag.String())
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -55,6 +55,7 @@ require (
|
||||||
github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344
|
github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a
|
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a
|
||||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
|
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
|
||||||
|
github.com/urfave/cli/v2 v2.10.2
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
|
@ -64,7 +65,6 @@ require (
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||||
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023
|
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023
|
||||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
|
||||||
gopkg.in/urfave/cli.v1 v1.20.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -77,6 +77,7 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
|
||||||
github.com/aws/smithy-go v1.1.0 // indirect
|
github.com/aws/smithy-go v1.1.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||||
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
|
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
|
||||||
|
@ -92,8 +93,10 @@ require (
|
||||||
github.com/opentracing/opentracing-go v1.1.0 // indirect
|
github.com/opentracing/opentracing-go v1.1.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
||||||
github.com/tklauser/numcpus v0.2.2 // indirect
|
github.com/tklauser/numcpus v0.2.2 // indirect
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect
|
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect
|
||||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
|
golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
|
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
|
||||||
|
|
11
go.sum
11
go.sum
|
@ -25,6 +25,7 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSu
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJNuUB6n7rs5Wsel4dXLe90Um2n4=
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJNuUB6n7rs5Wsel4dXLe90Um2n4=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo=
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
@ -83,6 +84,8 @@ github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/
|
||||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f h1:C43yEtQ6NIf4ftFXD/V55gnGFgPbMQobd//YlnLjUJ8=
|
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f h1:C43yEtQ6NIf4ftFXD/V55gnGFgPbMQobd//YlnLjUJ8=
|
||||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
|
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||||
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
||||||
|
@ -371,6 +374,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
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/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
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/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
|
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
|
||||||
github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
|
github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
@ -408,11 +413,15 @@ github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZF
|
||||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
|
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
|
||||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y=
|
||||||
|
github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
@ -662,8 +671,6 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7
|
||||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
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/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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
@ -24,71 +24,84 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/metrics/exp"
|
"github.com/ethereum/go-ethereum/metrics/exp"
|
||||||
"github.com/fjl/memsize/memsizeui"
|
"github.com/fjl/memsize/memsizeui"
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Memsize memsizeui.Handler
|
var Memsize memsizeui.Handler
|
||||||
|
|
||||||
var (
|
var (
|
||||||
verbosityFlag = cli.IntFlag{
|
verbosityFlag = &cli.IntFlag{
|
||||||
Name: "verbosity",
|
Name: "verbosity",
|
||||||
Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail",
|
Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail",
|
||||||
Value: 3,
|
Value: 3,
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
vmoduleFlag = cli.StringFlag{
|
vmoduleFlag = &cli.StringFlag{
|
||||||
Name: "vmodule",
|
Name: "vmodule",
|
||||||
Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)",
|
Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)",
|
||||||
Value: "",
|
Value: "",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
logjsonFlag = cli.BoolFlag{
|
logjsonFlag = &cli.BoolFlag{
|
||||||
Name: "log.json",
|
Name: "log.json",
|
||||||
Usage: "Format logs with JSON",
|
Usage: "Format logs with JSON",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
backtraceAtFlag = cli.StringFlag{
|
backtraceAtFlag = &cli.StringFlag{
|
||||||
Name: "log.backtrace",
|
Name: "log.backtrace",
|
||||||
Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")",
|
Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")",
|
||||||
Value: "",
|
Value: "",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
debugFlag = cli.BoolFlag{
|
debugFlag = &cli.BoolFlag{
|
||||||
Name: "log.debug",
|
Name: "log.debug",
|
||||||
Usage: "Prepends log messages with call-site location (file and line number)",
|
Usage: "Prepends log messages with call-site location (file and line number)",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
pprofFlag = cli.BoolFlag{
|
pprofFlag = &cli.BoolFlag{
|
||||||
Name: "pprof",
|
Name: "pprof",
|
||||||
Usage: "Enable the pprof HTTP server",
|
Usage: "Enable the pprof HTTP server",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
pprofPortFlag = cli.IntFlag{
|
pprofPortFlag = &cli.IntFlag{
|
||||||
Name: "pprof.port",
|
Name: "pprof.port",
|
||||||
Usage: "pprof HTTP server listening port",
|
Usage: "pprof HTTP server listening port",
|
||||||
Value: 6060,
|
Value: 6060,
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
pprofAddrFlag = cli.StringFlag{
|
pprofAddrFlag = &cli.StringFlag{
|
||||||
Name: "pprof.addr",
|
Name: "pprof.addr",
|
||||||
Usage: "pprof HTTP server listening interface",
|
Usage: "pprof HTTP server listening interface",
|
||||||
Value: "127.0.0.1",
|
Value: "127.0.0.1",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
memprofilerateFlag = cli.IntFlag{
|
memprofilerateFlag = &cli.IntFlag{
|
||||||
Name: "pprof.memprofilerate",
|
Name: "pprof.memprofilerate",
|
||||||
Usage: "Turn on memory profiling with the given rate",
|
Usage: "Turn on memory profiling with the given rate",
|
||||||
Value: runtime.MemProfileRate,
|
Value: runtime.MemProfileRate,
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
blockprofilerateFlag = cli.IntFlag{
|
blockprofilerateFlag = &cli.IntFlag{
|
||||||
Name: "pprof.blockprofilerate",
|
Name: "pprof.blockprofilerate",
|
||||||
Usage: "Turn on block profiling with the given rate",
|
Usage: "Turn on block profiling with the given rate",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
cpuprofileFlag = cli.StringFlag{
|
cpuprofileFlag = &cli.StringFlag{
|
||||||
Name: "pprof.cpuprofile",
|
Name: "pprof.cpuprofile",
|
||||||
Usage: "Write CPU profile to the given file",
|
Usage: "Write CPU profile to the given file",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
traceFlag = cli.StringFlag{
|
traceFlag = &cli.StringFlag{
|
||||||
Name: "trace",
|
Name: "trace",
|
||||||
Usage: "Write execution trace to the given file",
|
Usage: "Write execution trace to the given file",
|
||||||
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -121,7 +134,7 @@ func init() {
|
||||||
func Setup(ctx *cli.Context) error {
|
func Setup(ctx *cli.Context) error {
|
||||||
var ostream log.Handler
|
var ostream log.Handler
|
||||||
output := io.Writer(os.Stderr)
|
output := io.Writer(os.Stderr)
|
||||||
if ctx.GlobalBool(logjsonFlag.Name) {
|
if ctx.Bool(logjsonFlag.Name) {
|
||||||
ostream = log.StreamHandler(output, log.JSONFormat())
|
ostream = log.StreamHandler(output, log.JSONFormat())
|
||||||
} else {
|
} else {
|
||||||
usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
|
usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
|
||||||
|
@ -133,53 +146,53 @@ func Setup(ctx *cli.Context) error {
|
||||||
glogger.SetHandler(ostream)
|
glogger.SetHandler(ostream)
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
verbosity := ctx.GlobalInt(verbosityFlag.Name)
|
verbosity := ctx.Int(verbosityFlag.Name)
|
||||||
glogger.Verbosity(log.Lvl(verbosity))
|
glogger.Verbosity(log.Lvl(verbosity))
|
||||||
vmodule := ctx.GlobalString(vmoduleFlag.Name)
|
vmodule := ctx.String(vmoduleFlag.Name)
|
||||||
glogger.Vmodule(vmodule)
|
glogger.Vmodule(vmodule)
|
||||||
|
|
||||||
debug := ctx.GlobalBool(debugFlag.Name)
|
debug := ctx.Bool(debugFlag.Name)
|
||||||
if ctx.GlobalIsSet(debugFlag.Name) {
|
if ctx.IsSet(debugFlag.Name) {
|
||||||
debug = ctx.GlobalBool(debugFlag.Name)
|
debug = ctx.Bool(debugFlag.Name)
|
||||||
}
|
}
|
||||||
log.PrintOrigins(debug)
|
log.PrintOrigins(debug)
|
||||||
|
|
||||||
backtrace := ctx.GlobalString(backtraceAtFlag.Name)
|
backtrace := ctx.String(backtraceAtFlag.Name)
|
||||||
glogger.BacktraceAt(backtrace)
|
glogger.BacktraceAt(backtrace)
|
||||||
|
|
||||||
log.Root().SetHandler(glogger)
|
log.Root().SetHandler(glogger)
|
||||||
|
|
||||||
// profiling, tracing
|
// profiling, tracing
|
||||||
runtime.MemProfileRate = memprofilerateFlag.Value
|
runtime.MemProfileRate = memprofilerateFlag.Value
|
||||||
if ctx.GlobalIsSet(memprofilerateFlag.Name) {
|
if ctx.IsSet(memprofilerateFlag.Name) {
|
||||||
runtime.MemProfileRate = ctx.GlobalInt(memprofilerateFlag.Name)
|
runtime.MemProfileRate = ctx.Int(memprofilerateFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
blockProfileRate := ctx.GlobalInt(blockprofilerateFlag.Name)
|
blockProfileRate := ctx.Int(blockprofilerateFlag.Name)
|
||||||
Handler.SetBlockProfileRate(blockProfileRate)
|
Handler.SetBlockProfileRate(blockProfileRate)
|
||||||
|
|
||||||
if traceFile := ctx.GlobalString(traceFlag.Name); traceFile != "" {
|
if traceFile := ctx.String(traceFlag.Name); traceFile != "" {
|
||||||
if err := Handler.StartGoTrace(traceFile); err != nil {
|
if err := Handler.StartGoTrace(traceFile); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cpuFile := ctx.GlobalString(cpuprofileFlag.Name); cpuFile != "" {
|
if cpuFile := ctx.String(cpuprofileFlag.Name); cpuFile != "" {
|
||||||
if err := Handler.StartCPUProfile(cpuFile); err != nil {
|
if err := Handler.StartCPUProfile(cpuFile); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pprof server
|
// pprof server
|
||||||
if ctx.GlobalBool(pprofFlag.Name) {
|
if ctx.Bool(pprofFlag.Name) {
|
||||||
listenHost := ctx.GlobalString(pprofAddrFlag.Name)
|
listenHost := ctx.String(pprofAddrFlag.Name)
|
||||||
|
|
||||||
port := ctx.GlobalInt(pprofPortFlag.Name)
|
port := ctx.Int(pprofPortFlag.Name)
|
||||||
|
|
||||||
address := fmt.Sprintf("%s:%d", listenHost, port)
|
address := fmt.Sprintf("%s:%d", listenHost, port)
|
||||||
// This context value ("metrics.addr") represents the utils.MetricsHTTPFlag.Name.
|
// This context value ("metrics.addr") represents the utils.MetricsHTTPFlag.Name.
|
||||||
// It cannot be imported because it will cause a cyclical dependency.
|
// It cannot be imported because it will cause a cyclical dependency.
|
||||||
StartPProf(address, !ctx.GlobalIsSet("metrics.addr"))
|
StartPProf(address, !ctx.IsSet("metrics.addr"))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
// 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)"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cli.HelpFlag.(*cli.BoolFlag).Category = MiscCategory
|
||||||
|
cli.VersionFlag.(*cli.BoolFlag).Category = MiscCategory
|
||||||
|
}
|
|
@ -0,0 +1,340 @@
|
||||||
|
// Copyright 2015 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DirectoryString is custom type which is registered in the flags library which cli uses for
|
||||||
|
// argument parsing. This allows us to expand Value to an absolute path when
|
||||||
|
// the argument is parsed
|
||||||
|
type DirectoryString string
|
||||||
|
|
||||||
|
func (s *DirectoryString) String() string {
|
||||||
|
return string(*s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DirectoryString) Set(value string) error {
|
||||||
|
*s = DirectoryString(expandPath(value))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ cli.Flag = (*DirectoryFlag)(nil)
|
||||||
|
_ cli.RequiredFlag = (*DirectoryFlag)(nil)
|
||||||
|
_ cli.VisibleFlag = (*DirectoryFlag)(nil)
|
||||||
|
_ cli.DocGenerationFlag = (*DirectoryFlag)(nil)
|
||||||
|
_ cli.CategorizableFlag = (*DirectoryFlag)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// DirectoryFlag is custom cli.Flag type which expand the received string to an absolute path.
|
||||||
|
// e.g. ~/.ethereum -> /home/username/.ethereum
|
||||||
|
type DirectoryFlag struct {
|
||||||
|
Name string
|
||||||
|
|
||||||
|
Category string
|
||||||
|
DefaultText string
|
||||||
|
Usage string
|
||||||
|
|
||||||
|
Required bool
|
||||||
|
Hidden bool
|
||||||
|
HasBeenSet bool
|
||||||
|
|
||||||
|
Value DirectoryString
|
||||||
|
|
||||||
|
Aliases []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// For cli.Flag:
|
||||||
|
|
||||||
|
func (f *DirectoryFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) }
|
||||||
|
func (f *DirectoryFlag) IsSet() bool { return f.HasBeenSet }
|
||||||
|
func (f *DirectoryFlag) String() string { return cli.FlagStringer(f) }
|
||||||
|
|
||||||
|
// Apply called by cli library, grabs variable from environment (if in env)
|
||||||
|
// and adds variable to flag set for parsing.
|
||||||
|
func (f *DirectoryFlag) Apply(set *flag.FlagSet) error {
|
||||||
|
eachName(f, func(name string) {
|
||||||
|
set.Var(&f.Value, f.Name, f.Usage)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// For cli.RequiredFlag:
|
||||||
|
|
||||||
|
func (f *DirectoryFlag) IsRequired() bool { return f.Required }
|
||||||
|
|
||||||
|
// For cli.VisibleFlag:
|
||||||
|
|
||||||
|
func (f *DirectoryFlag) IsVisible() bool { return !f.Hidden }
|
||||||
|
|
||||||
|
// For cli.CategorizableFlag:
|
||||||
|
|
||||||
|
func (f *DirectoryFlag) GetCategory() string { return f.Category }
|
||||||
|
|
||||||
|
// For cli.DocGenerationFlag:
|
||||||
|
|
||||||
|
func (f *DirectoryFlag) TakesValue() bool { return true }
|
||||||
|
func (f *DirectoryFlag) GetUsage() string { return f.Usage }
|
||||||
|
func (f *DirectoryFlag) GetValue() string { return f.Value.String() }
|
||||||
|
func (f *DirectoryFlag) GetEnvVars() []string { return nil } // env not supported
|
||||||
|
|
||||||
|
func (f *DirectoryFlag) GetDefaultText() string {
|
||||||
|
if f.DefaultText != "" {
|
||||||
|
return f.DefaultText
|
||||||
|
}
|
||||||
|
return f.GetValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
type TextMarshaler interface {
|
||||||
|
encoding.TextMarshaler
|
||||||
|
encoding.TextUnmarshaler
|
||||||
|
}
|
||||||
|
|
||||||
|
// textMarshalerVal turns a TextMarshaler into a flag.Value
|
||||||
|
type textMarshalerVal struct {
|
||||||
|
v TextMarshaler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v textMarshalerVal) String() string {
|
||||||
|
if v.v == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
text, _ := v.v.MarshalText()
|
||||||
|
return string(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v textMarshalerVal) Set(s string) error {
|
||||||
|
return v.v.UnmarshalText([]byte(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ cli.Flag = (*TextMarshalerFlag)(nil)
|
||||||
|
_ cli.RequiredFlag = (*TextMarshalerFlag)(nil)
|
||||||
|
_ cli.VisibleFlag = (*TextMarshalerFlag)(nil)
|
||||||
|
_ cli.DocGenerationFlag = (*TextMarshalerFlag)(nil)
|
||||||
|
_ cli.CategorizableFlag = (*TextMarshalerFlag)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// TextMarshalerFlag wraps a TextMarshaler value.
|
||||||
|
type TextMarshalerFlag struct {
|
||||||
|
Name string
|
||||||
|
|
||||||
|
Category string
|
||||||
|
DefaultText string
|
||||||
|
Usage string
|
||||||
|
|
||||||
|
Required bool
|
||||||
|
Hidden bool
|
||||||
|
HasBeenSet bool
|
||||||
|
|
||||||
|
Value TextMarshaler
|
||||||
|
|
||||||
|
Aliases []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// For cli.Flag:
|
||||||
|
|
||||||
|
func (f *TextMarshalerFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) }
|
||||||
|
func (f *TextMarshalerFlag) IsSet() bool { return f.HasBeenSet }
|
||||||
|
func (f *TextMarshalerFlag) String() string { return cli.FlagStringer(f) }
|
||||||
|
|
||||||
|
func (f *TextMarshalerFlag) Apply(set *flag.FlagSet) error {
|
||||||
|
eachName(f, func(name string) {
|
||||||
|
set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// For cli.RequiredFlag:
|
||||||
|
|
||||||
|
func (f *TextMarshalerFlag) IsRequired() bool { return f.Required }
|
||||||
|
|
||||||
|
// For cli.VisibleFlag:
|
||||||
|
|
||||||
|
func (f *TextMarshalerFlag) IsVisible() bool { return !f.Hidden }
|
||||||
|
|
||||||
|
// For cli.CategorizableFlag:
|
||||||
|
|
||||||
|
func (f *TextMarshalerFlag) GetCategory() string { return f.Category }
|
||||||
|
|
||||||
|
// For cli.DocGenerationFlag:
|
||||||
|
|
||||||
|
func (f *TextMarshalerFlag) TakesValue() bool { return true }
|
||||||
|
func (f *TextMarshalerFlag) GetUsage() string { return f.Usage }
|
||||||
|
func (f *TextMarshalerFlag) GetEnvVars() []string { return nil } // env not supported
|
||||||
|
|
||||||
|
func (f *TextMarshalerFlag) GetValue() string {
|
||||||
|
t, err := f.Value.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return "(ERR: " + err.Error() + ")"
|
||||||
|
}
|
||||||
|
return string(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *TextMarshalerFlag) GetDefaultText() string {
|
||||||
|
if f.DefaultText != "" {
|
||||||
|
return f.DefaultText
|
||||||
|
}
|
||||||
|
return f.GetValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalTextMarshaler returns the value of a TextMarshalerFlag from the global flag set.
|
||||||
|
func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler {
|
||||||
|
val := ctx.Generic(name)
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return val.(textMarshalerVal).v
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ cli.Flag = (*BigFlag)(nil)
|
||||||
|
_ cli.RequiredFlag = (*BigFlag)(nil)
|
||||||
|
_ cli.VisibleFlag = (*BigFlag)(nil)
|
||||||
|
_ cli.DocGenerationFlag = (*BigFlag)(nil)
|
||||||
|
_ cli.CategorizableFlag = (*BigFlag)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// BigFlag is a command line flag that accepts 256 bit big integers in decimal or
|
||||||
|
// hexadecimal syntax.
|
||||||
|
type BigFlag struct {
|
||||||
|
Name string
|
||||||
|
|
||||||
|
Category string
|
||||||
|
DefaultText string
|
||||||
|
Usage string
|
||||||
|
|
||||||
|
Required bool
|
||||||
|
Hidden bool
|
||||||
|
HasBeenSet bool
|
||||||
|
|
||||||
|
Value *big.Int
|
||||||
|
|
||||||
|
Aliases []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// For cli.Flag:
|
||||||
|
|
||||||
|
func (f *BigFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) }
|
||||||
|
func (f *BigFlag) IsSet() bool { return f.HasBeenSet }
|
||||||
|
func (f *BigFlag) String() string { return cli.FlagStringer(f) }
|
||||||
|
|
||||||
|
func (f *BigFlag) Apply(set *flag.FlagSet) error {
|
||||||
|
eachName(f, func(name string) {
|
||||||
|
f.Value = new(big.Int)
|
||||||
|
set.Var((*bigValue)(f.Value), f.Name, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// For cli.RequiredFlag:
|
||||||
|
|
||||||
|
func (f *BigFlag) IsRequired() bool { return f.Required }
|
||||||
|
|
||||||
|
// For cli.VisibleFlag:
|
||||||
|
|
||||||
|
func (f *BigFlag) IsVisible() bool { return !f.Hidden }
|
||||||
|
|
||||||
|
// For cli.CategorizableFlag:
|
||||||
|
|
||||||
|
func (f *BigFlag) GetCategory() string { return f.Category }
|
||||||
|
|
||||||
|
// For cli.DocGenerationFlag:
|
||||||
|
|
||||||
|
func (f *BigFlag) TakesValue() bool { return true }
|
||||||
|
func (f *BigFlag) GetUsage() string { return f.Usage }
|
||||||
|
func (f *BigFlag) GetValue() string { return f.Value.String() }
|
||||||
|
func (f *BigFlag) GetEnvVars() []string { return nil } // env not supported
|
||||||
|
|
||||||
|
func (f *BigFlag) GetDefaultText() string {
|
||||||
|
if f.DefaultText != "" {
|
||||||
|
return f.DefaultText
|
||||||
|
}
|
||||||
|
return f.GetValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
// bigValue turns *big.Int into a flag.Value
|
||||||
|
type bigValue big.Int
|
||||||
|
|
||||||
|
func (b *bigValue) String() string {
|
||||||
|
if b == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return (*big.Int)(b).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bigValue) Set(s string) error {
|
||||||
|
intVal, ok := math.ParseBig256(s)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("invalid integer syntax")
|
||||||
|
}
|
||||||
|
*b = (bigValue)(*intVal)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalBig returns the value of a BigFlag from the global flag set.
|
||||||
|
func GlobalBig(ctx *cli.Context, name string) *big.Int {
|
||||||
|
val := ctx.Generic(name)
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return (*big.Int)(val.(*bigValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expands a file path
|
||||||
|
// 1. replace tilde with users home dir
|
||||||
|
// 2. expands embedded environment variables
|
||||||
|
// 3. cleans the path, e.g. /a/b/../c -> /a/c
|
||||||
|
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
|
||||||
|
func expandPath(p string) string {
|
||||||
|
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
|
||||||
|
if home := HomeDir(); home != "" {
|
||||||
|
p = home + p[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path.Clean(os.ExpandEnv(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
func HomeDir() string {
|
||||||
|
if home := os.Getenv("HOME"); home != "" {
|
||||||
|
return home
|
||||||
|
}
|
||||||
|
if usr, err := user.Current(); err == nil {
|
||||||
|
return usr.HomeDir
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func eachName(f cli.Flag, fn func(string)) {
|
||||||
|
for _, name := range f.Names() {
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
fn(name)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,20 @@
|
||||||
// Copyright 2015 The go-ethereum Authors
|
// Copyright 2015 The go-ethereum Authors
|
||||||
// This file is part of go-ethereum.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// go-ethereum is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// 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
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
//
|
//
|
||||||
// go-ethereum is distributed in the hope that it will be useful,
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package utils
|
package flags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
|
@ -17,137 +17,160 @@
|
||||||
package flags
|
package flags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"fmt"
|
||||||
"path/filepath"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} {{.cmd.ArgsUsage}}
|
|
||||||
{{if .cmd.Description}}{{.cmd.Description}}
|
|
||||||
{{end}}{{if .cmd.Subcommands}}
|
|
||||||
SUBCOMMANDS:
|
|
||||||
{{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
|
|
||||||
{{end}}{{end}}{{if .categorizedFlags}}
|
|
||||||
{{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
|
|
||||||
{{range $categorized.Flags}}{{"\t"}}{{.}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}{{end}}`
|
|
||||||
|
|
||||||
OriginCommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} {{.ArgsUsage}}
|
|
||||||
{{if .Description}}{{.Description}}
|
|
||||||
{{end}}{{if .Subcommands}}
|
|
||||||
SUBCOMMANDS:
|
|
||||||
{{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
|
|
||||||
{{end}}{{end}}{{if .Flags}}
|
|
||||||
OPTIONS:
|
|
||||||
{{range $.Flags}} {{.}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}`
|
|
||||||
|
|
||||||
// AppHelpTemplate is the test template for the default, global app help topic.
|
|
||||||
AppHelpTemplate = `NAME:
|
|
||||||
{{.App.Name}} - {{.App.Usage}}
|
|
||||||
|
|
||||||
Copyright 2013-2022 The go-ethereum Authors
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
{{.App.HelpName}} [options]{{if .App.Commands}} [command] [command options]{{end}} {{if .App.ArgsUsage}}{{.App.ArgsUsage}}{{else}}[arguments...]{{end}}
|
|
||||||
{{if .App.Version}}
|
|
||||||
VERSION:
|
|
||||||
{{.App.Version}}
|
|
||||||
{{end}}{{if len .App.Authors}}
|
|
||||||
AUTHOR(S):
|
|
||||||
{{range .App.Authors}}{{ . }}{{end}}
|
|
||||||
{{end}}{{if .App.Commands}}
|
|
||||||
COMMANDS:
|
|
||||||
{{range .App.Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
|
|
||||||
{{end}}{{end}}{{if .FlagGroups}}
|
|
||||||
{{range .FlagGroups}}{{.Name}} OPTIONS:
|
|
||||||
{{range .Flags}}{{.}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}{{end}}{{if .App.Copyright }}
|
|
||||||
COPYRIGHT:
|
|
||||||
{{.App.Copyright}}
|
|
||||||
{{end}}
|
|
||||||
`
|
|
||||||
// ClefAppHelpTemplate is the template for the default, global app help topic.
|
|
||||||
ClefAppHelpTemplate = `NAME:
|
|
||||||
{{.App.Name}} - {{.App.Usage}}
|
|
||||||
|
|
||||||
Copyright 2013-2022 The go-ethereum Authors
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
{{.App.HelpName}} [options]{{if .App.Commands}} command [command options]{{end}} {{if .App.ArgsUsage}}{{.App.ArgsUsage}}{{else}}[arguments...]{{end}}
|
|
||||||
{{if .App.Version}}
|
|
||||||
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}}
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|
||||||
// HelpData is a one shot struct to pass to the usage template
|
|
||||||
type HelpData struct {
|
|
||||||
App interface{}
|
|
||||||
FlagGroups []FlagGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlagGroup is a collection of flags belonging to a single topic.
|
|
||||||
type FlagGroup struct {
|
|
||||||
Name string
|
|
||||||
Flags []cli.Flag
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(a), len(a) // ensure non categorized flags come last
|
|
||||||
|
|
||||||
for i, group := range a {
|
|
||||||
if iCat == group.Name {
|
|
||||||
iIdx = i
|
|
||||||
}
|
|
||||||
if jCat == group.Name {
|
|
||||||
jIdx = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return iIdx < jIdx
|
|
||||||
}
|
|
||||||
|
|
||||||
func FlagCategory(flag cli.Flag, flagGroups []FlagGroup) string {
|
|
||||||
for _, category := range flagGroups {
|
|
||||||
for _, flg := range category.Flags {
|
|
||||||
if flg.GetName() == flag.GetName() {
|
|
||||||
return category.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "MISC"
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewApp creates an app with sane defaults.
|
// NewApp creates an app with sane defaults.
|
||||||
func NewApp(gitCommit, gitDate, usage string) *cli.App {
|
func NewApp(gitCommit, gitDate, usage string) *cli.App {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.EnableBashCompletion = true
|
app.EnableBashCompletion = true
|
||||||
app.Name = filepath.Base(os.Args[0])
|
|
||||||
app.Author = ""
|
|
||||||
app.Email = ""
|
|
||||||
app.Version = params.VersionWithCommit(gitCommit, gitDate)
|
app.Version = params.VersionWithCommit(gitCommit, gitDate)
|
||||||
app.Usage = usage
|
app.Usage = usage
|
||||||
|
app.Copyright = "Copyright 2013-2022 The go-ethereum Authors"
|
||||||
|
app.Before = func(ctx *cli.Context) error {
|
||||||
|
MigrateGlobalFlags(ctx)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var migrationApplied = map[*cli.Command]struct{}{}
|
||||||
|
|
||||||
|
// MigrateGlobalFlags makes all global flag values available in the
|
||||||
|
// context. This should be called as early as possible in app.Before.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// geth account new --keystore /tmp/mykeystore --lightkdf
|
||||||
|
//
|
||||||
|
// is equivalent after calling this method with:
|
||||||
|
//
|
||||||
|
// geth --keystore /tmp/mykeystore --lightkdf account new
|
||||||
|
//
|
||||||
|
// i.e. in the subcommand Action function of 'account new', ctx.Bool("lightkdf)
|
||||||
|
// will return true even if --lightkdf is set as a global option.
|
||||||
|
//
|
||||||
|
// This function may become unnecessary when https://github.com/urfave/cli/pull/1245 is merged.
|
||||||
|
func MigrateGlobalFlags(ctx *cli.Context) {
|
||||||
|
var iterate func(cs []*cli.Command, fn func(*cli.Command))
|
||||||
|
iterate = func(cs []*cli.Command, fn func(*cli.Command)) {
|
||||||
|
for _, cmd := range cs {
|
||||||
|
if _, ok := migrationApplied[cmd]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
migrationApplied[cmd] = struct{}{}
|
||||||
|
fn(cmd)
|
||||||
|
iterate(cmd.Subcommands, fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This iterates over all commands and wraps their action function.
|
||||||
|
iterate(ctx.App.Commands, func(cmd *cli.Command) {
|
||||||
|
action := cmd.Action
|
||||||
|
cmd.Action = func(ctx *cli.Context) error {
|
||||||
|
doMigrateFlags(ctx)
|
||||||
|
return action(ctx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func doMigrateFlags(ctx *cli.Context) {
|
||||||
|
for _, name := range ctx.FlagNames() {
|
||||||
|
for _, parent := range ctx.Lineage()[1:] {
|
||||||
|
if parent.IsSet(name) {
|
||||||
|
ctx.Set(name, parent.String(name))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cli.FlagStringer = FlagString
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagString prints a single flag in help.
|
||||||
|
func FlagString(f cli.Flag) string {
|
||||||
|
df, ok := f.(cli.DocGenerationFlag)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
needsPlaceholder := df.TakesValue()
|
||||||
|
placeholder := ""
|
||||||
|
if needsPlaceholder {
|
||||||
|
placeholder = "value"
|
||||||
|
}
|
||||||
|
|
||||||
|
namesText := pad(cli.FlagNamePrefixer(df.Names(), placeholder), 30)
|
||||||
|
|
||||||
|
defaultValueString := ""
|
||||||
|
if s := df.GetDefaultText(); s != "" {
|
||||||
|
defaultValueString = " (default: " + s + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
usage := strings.TrimSpace(df.GetUsage())
|
||||||
|
envHint := strings.TrimSpace(cli.FlagEnvHinter(df.GetEnvVars(), ""))
|
||||||
|
if len(envHint) > 0 {
|
||||||
|
usage += " " + envHint
|
||||||
|
}
|
||||||
|
|
||||||
|
usage = wordWrap(usage, 80)
|
||||||
|
usage = indent(usage, 10)
|
||||||
|
|
||||||
|
return fmt.Sprintf("\n %s%s\n%s", namesText, defaultValueString, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pad(s string, length int) string {
|
||||||
|
if len(s) < length {
|
||||||
|
s += strings.Repeat(" ", length-len(s))
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func indent(s string, nspace int) string {
|
||||||
|
ind := strings.Repeat(" ", nspace)
|
||||||
|
return ind + strings.ReplaceAll(s, "\n", "\n"+ind)
|
||||||
|
}
|
||||||
|
|
||||||
|
func wordWrap(s string, width int) string {
|
||||||
|
var (
|
||||||
|
output strings.Builder
|
||||||
|
lineLength = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
for {
|
||||||
|
sp := strings.IndexByte(s, ' ')
|
||||||
|
var word string
|
||||||
|
if sp == -1 {
|
||||||
|
word = s
|
||||||
|
} else {
|
||||||
|
word = s[:sp]
|
||||||
|
}
|
||||||
|
wlen := len(word)
|
||||||
|
over := lineLength+wlen >= width
|
||||||
|
if over {
|
||||||
|
output.WriteByte('\n')
|
||||||
|
lineLength = 0
|
||||||
|
} else {
|
||||||
|
if lineLength != 0 {
|
||||||
|
output.WriteByte(' ')
|
||||||
|
lineLength++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.WriteString(word)
|
||||||
|
lineLength += wlen
|
||||||
|
|
||||||
|
if sp == -1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s = s[wlen+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.String()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue