From a131e427f64bd56839c432ac93fb64dd3d471087 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 22 Apr 2022 11:44:35 -0700 Subject: [PATCH] Automatically generate markdown pages from bor CLI Adding a script that can automatically generate markdown pages from bor CLI, so we can avoid copy-pasting helper strings whenever a flag is created, deleted, or modified. CLI docs could be generated with command `make docs`. --- Makefile | 9 +- cmd/clidoc/main.go | 71 ++++++++++++ docs/cli/README.md | 25 ++-- docs/cli/account.md | 3 +- docs/cli/account_import.md | 7 +- docs/cli/account_list.md | 9 +- docs/cli/account_new.md | 9 +- docs/cli/attach.md | 11 ++ docs/cli/chain.md | 3 +- docs/cli/chain_sethead.md | 5 +- docs/cli/chain_watch.md | 2 +- docs/cli/debug.md | 13 ++- docs/cli/fingerprint.md | 3 + docs/cli/peers.md | 3 +- docs/cli/peers_add.md | 7 +- docs/cli/peers_list.md | 7 +- docs/cli/peers_remove.md | 7 +- docs/cli/peers_status.md | 5 +- docs/cli/server.md | 195 ++++++++++++++++---------------- docs/cli/status.md | 3 +- docs/cli/version.md | 3 +- internal/cli/account.go | 18 ++- internal/cli/account_import.go | 11 ++ internal/cli/account_list.go | 11 ++ internal/cli/account_new.go | 11 ++ internal/cli/attach.go | 10 ++ internal/cli/bor_fingerprint.go | 10 ++ internal/cli/chain.go | 13 +++ internal/cli/chain_sethead.go | 13 +++ internal/cli/chain_watch.go | 10 ++ internal/cli/command.go | 60 ++++++---- internal/cli/debug.go | 27 +++++ internal/cli/flagset/flagset.go | 54 +++++++++ internal/cli/markdown.go | 14 +++ internal/cli/markdown_test.go | 19 ++++ internal/cli/peers.go | 15 +++ internal/cli/peers_add.go | 11 ++ internal/cli/peers_list.go | 10 ++ internal/cli/peers_remove.go | 11 ++ internal/cli/peers_status.go | 10 ++ internal/cli/server/command.go | 11 ++ internal/cli/server/flags.go | 71 +++++++++++- internal/cli/status.go | 9 ++ internal/cli/version.go | 20 ++++ 44 files changed, 686 insertions(+), 163 deletions(-) create mode 100644 cmd/clidoc/main.go create mode 100644 docs/cli/attach.md create mode 100644 docs/cli/fingerprint.md create mode 100644 internal/cli/markdown.go create mode 100644 internal/cli/markdown_test.go diff --git a/Makefile b/Makefile index 678af31c46..9ee575aab4 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,11 @@ # with Go source code. If you know what GOPATH is then you probably # don't need to bother with make. -.PHONY: geth android ios evm all test clean +.PHONY: geth android ios geth-cross evm all test clean docs +.PHONY: geth-linux geth-linux-386 geth-linux-amd64 geth-linux-mips64 geth-linux-mips64le +.PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64 +.PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64 +.PHONY: geth-windows geth-windows-386 geth-windows-amd64 GOBIN = ./build/bin GO ?= latest @@ -43,6 +47,9 @@ test: lint: ## Run linters. $(GORUN) build/ci.go lint +docs: + $(GORUN) cmd/clidoc/main.go -d ./docs/cli + clean: env GO111MODULE=on go clean -cache rm -fr build/_workspace/pkg/ $(GOBIN)/* diff --git a/cmd/clidoc/main.go b/cmd/clidoc/main.go new file mode 100644 index 0000000000..70ad35501b --- /dev/null +++ b/cmd/clidoc/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "flag" + "log" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/ethereum/go-ethereum/internal/cli" +) + +const ( + DefaultDir string = "./docs/cli" + DefaultMainPage string = "README.md" +) + +func main() { + + commands := cli.Commands() + + dest := flag.String("d", DefaultDir, "Destination directory where the docs will be generated") + flag.Parse() + + dirPath := filepath.Join(".", *dest) + if err := os.MkdirAll(dirPath, os.ModePerm); err != nil { + log.Fatalln("Failed to create directory.", err) + } + + mainPage := []string{ + "# Bor command line interface", + "## Commands", + } + + keys := make([]string, len(commands)) + i := 0 + for k := range commands { + keys[i] = k + i++ + } + sort.Strings(keys) + + for _, name := range keys { + cmd, err := commands[name]() + if err != nil { + log.Fatalf("Error occurred when inspecting bor command %s: %s", name, err) + } + + fileName := strings.ReplaceAll(name, " ", "_") + ".md" + + overwriteFile(filepath.Join(dirPath, fileName), cmd.MarkDown()) + mainPage = append(mainPage, "- [```"+name+"```](./"+fileName+")") + } + + overwriteFile(filepath.Join(dirPath, DefaultMainPage), strings.Join(mainPage, "\n\n")) + + os.Exit(0) +} + +func overwriteFile(filePath string, text string) { + log.Printf("Writing to page: %s\n", filePath) + f, err := os.Create(filePath) + if err != nil { + log.Fatalln(err) + } + f.WriteString(text) + if err := f.Close(); err != nil { + log.Fatalln(err) + } +} diff --git a/docs/cli/README.md b/docs/cli/README.md index ed8a3f5977..c10c8bf9c2 100644 --- a/docs/cli/README.md +++ b/docs/cli/README.md @@ -1,24 +1,27 @@ - -# Command line interface +# Bor command line interface ## Commands -- [```server```](./server.md) - -- [```debug```](./debug.md) - - [```account```](./account.md) -- [```account new```](./account_new.md) +- [```account import```](./account_import.md) - [```account list```](./account_list.md) -- [```account import```](./account_import.md) +- [```account new```](./account_new.md) + +- [```attach```](./attach.md) - [```chain```](./chain.md) - [```chain sethead```](./chain_sethead.md) +- [```chain watch```](./chain_watch.md) + +- [```debug```](./debug.md) + +- [```fingerprint```](./fingerprint.md) + - [```peers```](./peers.md) - [```peers add```](./peers_add.md) @@ -29,8 +32,8 @@ - [```peers status```](./peers_status.md) -- [```status```](./status.md) +- [```server```](./server.md) -- [```chain watch```](./chain_watch.md) +- [```status```](./status.md) -- [```version```](./version.md) +- [```version```](./version.md) \ No newline at end of file diff --git a/docs/cli/account.md b/docs/cli/account.md index 00fd6cbe65..b3659952f6 100644 --- a/docs/cli/account.md +++ b/docs/cli/account.md @@ -1,4 +1,3 @@ - # Account The ```account``` command groups actions to interact with accounts: @@ -7,4 +6,4 @@ The ```account``` command groups actions to interact with accounts: - [```account list```](./account_list.md): List the wallets in the Bor client. -- [```account import```](./account_import.md): Import an account to the Bor client. +- [```account import```](./account_import.md): Import an account to the Bor client. \ No newline at end of file diff --git a/docs/cli/account_import.md b/docs/cli/account_import.md index 2a515866cf..d7b02195bc 100644 --- a/docs/cli/account_import.md +++ b/docs/cli/account_import.md @@ -1,4 +1,9 @@ - # Account import The ```account import``` command imports an account in Json format to the Bor data directory. + +## Options + +- ```datadir```: Path of the data directory to store information + +- ```keystore```: Path of the data directory to store information \ No newline at end of file diff --git a/docs/cli/account_list.md b/docs/cli/account_list.md index 4a2d28de92..61ebf9e776 100644 --- a/docs/cli/account_list.md +++ b/docs/cli/account_list.md @@ -1,4 +1,9 @@ - # Account list -The ```account list``` command lists all the accounts in the Bor data directory. +The `account list` command lists all the accounts in the Bor data directory. + +## Options + +- ```datadir```: Path of the data directory to store information + +- ```keystore```: Path of the data directory to store information \ No newline at end of file diff --git a/docs/cli/account_new.md b/docs/cli/account_new.md index 41e53767a1..dd62061ba0 100644 --- a/docs/cli/account_new.md +++ b/docs/cli/account_new.md @@ -1,4 +1,9 @@ - # Account new -The ```account new``` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command. +The `account new` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command. + +## Options + +- ```datadir```: Path of the data directory to store information + +- ```keystore```: Path of the data directory to store information \ No newline at end of file diff --git a/docs/cli/attach.md b/docs/cli/attach.md new file mode 100644 index 0000000000..6e323b8d18 --- /dev/null +++ b/docs/cli/attach.md @@ -0,0 +1,11 @@ +# Attach + +Connect to remote Bor IPC console. + +## Options + +- ```exec```: Command to run in remote console + +- ```preload```: Comma separated list of JavaScript files to preload into the console + +- ```jspath```: JavaScript root path for `loadScript` \ No newline at end of file diff --git a/docs/cli/chain.md b/docs/cli/chain.md index e55a90f122..8412588e37 100644 --- a/docs/cli/chain.md +++ b/docs/cli/chain.md @@ -1,6 +1,7 @@ - # Chain The ```chain``` command groups actions to interact with the blockchain in the client: - [```chain sethead```](./chain_sethead.md): Set the current chain to a certain block. + +- [```chain watch```](./chain_watch.md): Watch the chainHead, reorg and fork events in real-time. \ No newline at end of file diff --git a/docs/cli/chain_sethead.md b/docs/cli/chain_sethead.md index 985383988f..bf97990e62 100644 --- a/docs/cli/chain_sethead.md +++ b/docs/cli/chain_sethead.md @@ -1,4 +1,3 @@ - # Chain sethead The ```chain sethead ``` command sets the current chain to a certain block. @@ -9,4 +8,6 @@ The ```chain sethead ``` command sets the current chain to a certain blo ## Options -- ```yes```: Force set head. +- ```address```: Address of the grpc endpoint + +- ```yes```: Force set head \ No newline at end of file diff --git a/docs/cli/chain_watch.md b/docs/cli/chain_watch.md index 4844bb7618..252ac02531 100644 --- a/docs/cli/chain_watch.md +++ b/docs/cli/chain_watch.md @@ -1,3 +1,3 @@ # Chain watch -The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time. +The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time. \ No newline at end of file diff --git a/docs/cli/debug.md b/docs/cli/debug.md index c75ae79e49..eecc6c6ef0 100644 --- a/docs/cli/debug.md +++ b/docs/cli/debug.md @@ -1,13 +1,14 @@ - # Debug The ```bor debug``` command takes a debug dump of the running client. ## Options -- ```seconds```: Number of seconds to trace cpu and traces. +- ```address```: Address of the grpc endpoint + +- ```seconds```: seconds to trace -- ```output```: Output directory for the data dump. +- ```output```: Output directory ## Examples @@ -15,8 +16,8 @@ By default it creates a tar.gz file with the output: ``` $ bor debug -Starting debugger... - +Starting debugger... + Created debug archive: bor-debug-2021-10-26-073819Z.tar.gz ``` @@ -27,4 +28,4 @@ $ bor debug --output data Starting debugger... Created debug directory: data/bor-debug-2021-10-26-075437Z -``` +``` \ No newline at end of file diff --git a/docs/cli/fingerprint.md b/docs/cli/fingerprint.md new file mode 100644 index 0000000000..8bb7cb1542 --- /dev/null +++ b/docs/cli/fingerprint.md @@ -0,0 +1,3 @@ +# Fingerprint + +Display the system fingerprint \ No newline at end of file diff --git a/docs/cli/peers.md b/docs/cli/peers.md index 57b4889a00..ac6dfd676e 100644 --- a/docs/cli/peers.md +++ b/docs/cli/peers.md @@ -1,4 +1,3 @@ - # Peers The ```peers``` command groups actions to interact with peers: @@ -9,4 +8,4 @@ The ```peers``` command groups actions to interact with peers: - [```peers remove```](./peers_remove.md): Disconnects the local client from a connected peer if exists. -- [```peers status```](./peers_status.md): Display the status of a peer by its id. +- [```peers status```](./peers_status.md): Display the status of a peer by its id. \ No newline at end of file diff --git a/docs/cli/peers_add.md b/docs/cli/peers_add.md index 35e5ece450..5bc4ed1448 100644 --- a/docs/cli/peers_add.md +++ b/docs/cli/peers_add.md @@ -1,8 +1,9 @@ - # Peers add The ```peers add ``` command joins the local client to another remote peer. -## Arguments +## Options + +- ```address```: Address of the grpc endpoint -- ```trusted```: Whether the peer is added as a trusted peer. +- ```trusted```: Add the peer as a trusted \ No newline at end of file diff --git a/docs/cli/peers_list.md b/docs/cli/peers_list.md index cb1ef2f599..41f398b764 100644 --- a/docs/cli/peers_list.md +++ b/docs/cli/peers_list.md @@ -1,4 +1,7 @@ - -# Peers list +# Peers add The ```peers list``` command lists the connected peers. + +## Options + +- ```address```: Address of the grpc endpoint \ No newline at end of file diff --git a/docs/cli/peers_remove.md b/docs/cli/peers_remove.md index e2fa0a71df..2cac1e7656 100644 --- a/docs/cli/peers_remove.md +++ b/docs/cli/peers_remove.md @@ -1,4 +1,9 @@ - # Peers remove The ```peers remove ``` command disconnects the local client from a connected peer if exists. + +## Options + +- ```address```: Address of the grpc endpoint + +- ```trusted```: Add the peer as a trusted \ No newline at end of file diff --git a/docs/cli/peers_status.md b/docs/cli/peers_status.md index 56343c8d6b..65a0fe9d8f 100644 --- a/docs/cli/peers_status.md +++ b/docs/cli/peers_status.md @@ -1,4 +1,7 @@ - # Peers status The ```peers status ``` command displays the status of a peer by its id. + +## Options + +- ```address```: Address of the grpc endpoint \ No newline at end of file diff --git a/docs/cli/server.md b/docs/cli/server.md index 5a3e7e1052..ba6f3389c5 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -1,133 +1,112 @@ - # Server The ```bor server``` command runs the Bor client. -## General Options - -- ```chain```: Name of the chain to sync (mainnet or mumbai). - -- ```log-level```: Set log level for the server (info, warn, debug, trace). - -- ```datadir```: Path of the data directory to store information (defaults to $HOME). +## Options -- ```config```: List of files that contain the configuration. +- ```chain```: Name of the chain to sync -- ```syncmode```: Blockchain sync mode ("fast", "full", "snap" or "light"). +- ```name```: Name/Identity of the node -- ```gcmode```: Blockchain garbage collection mode ("full", "archive"). +- ```log-level```: Set log level for the server -- ```whitelist```: Comma separated block number-to-hash mappings to enforce (=). +- ```datadir```: Path of the data directory to store information -- ```snapshot```: Enables snapshot-database mode (default = enable). +- ```config```: File for the config file -- ```bor.heimdall```: URL of Heimdall service. +- ```syncmode```: Blockchain sync mode ("fast", "full", or "snap") -- ```bor.withoutheimdall```: Run without Heimdall service (for testing purpose). +- ```gcmode```: Blockchain garbage collection mode ("full", "archive") -- ```ethstats```: Reporting URL of a ethstats service (nodename:secret@host:port). +- ```whitelist```: Comma separated block number-to-hash mappings to enforce (=) -- ```gpo.blocks```: Number of recent blocks to check for gas prices. +- ```no-snapshot```: Disables the snapshot-database mode (default = false) -- ```gpo.percentile```: Suggested gas price is the given percentile of a set of recent transaction gas prices. +- ```bor.heimdall```: URL of Heimdall service -- ```gpo.maxprice```: Maximum gas price will be recommended by gpo. +- ```bor.withoutheimdall```: Run without Heimdall service (for testing purpose) -- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions. - -- ```grpc.addr```: Address and port to bind the GRPC server. - -### Transaction Pool Options +- ```ethstats```: Reporting URL of a ethstats service (nodename:secret@host:port) -- ```txpool.locals```: Comma separated accounts to treat as locals (no flush, priority inclusion). +- ```gpo.blocks```: Number of recent blocks to check for gas prices -- ```txpool.nolocals```: Disables price exemptions for locally submitted transactions +- ```gpo.percentile```: Suggested gas price is the given percentile of a set of recent transaction gas prices -- ```txpool.journal```: Disk journal for local transaction to survive node restarts +- ```gpo.maxprice```: Maximum gas price will be recommended by gpo -- ```txpool.rejournal```: Time interval to regenerate the local transaction journal +- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions -- ```txpool.pricelimit```: Minimum gas price limit to enforce for acceptance into the pool +- ```grpc.addr```: Address and port to bind the GRPC server -- ```txpool.pricebump```: Price bump percentage to replace an already existing transaction +- ```dev```: Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled -- ```txpool.accountslots```: Minimum number of executable transaction slots guaranteed per account +- ```dev.period```: Block period to use in developer mode (0 = mine only if transaction pending) -- ```txpool.globalslots```: Maximum number of executable transaction slots for all accounts - -- ```txpool.accountqueue```: Maximum number of non-executable transaction slots permitted per account - -- ```txpool.globalqueue```: Maximum number of non-executable transaction slots for all accounts - -- ```txpool.lifetime```: Maximum amount of time non-executable transaction are queued - -### Sealer Options - -- ```mine```: Enable sealing. +### Account Management Options -- ```miner.etherbase```: Public address for block mining rewards (default = first account) +- ```unlock```: Comma separated list of accounts to unlock -- ```miner.extradata```: Block extra data set by the miner (default = client version). +- ```password```: Password file to use for non-interactive password input -- ```miner.gaslimit```: Target gas ceiling for mined blocks. +- ```allow-insecure-unlock```: Allow insecure account unlocking when account-related RPCs are exposed by http -- ```miner.gasprice```: Minimum gas price for mining a transaction. +- ```lightkdf```: Reduce key-derivation RAM & CPU usage at some expense of KDF strength ### Cache Options -- ```cache```: Megabytes of memory allocated to internal caching (default = 4096 mainnet full node). +- ```cache```: Megabytes of memory allocated to internal caching (default = 4096 mainnet full node) -- ```cache.database```: Percentage of cache memory allowance to use for database io. +- ```cache.database```: Percentage of cache memory allowance to use for database io -- ```cache.trie```: Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode). +- ```cache.trie```: Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode) -- ```cache.trie.journal```: Disk journal directory for trie cache to survive node restarts. +- ```cache.trie.journal```: Disk journal directory for trie cache to survive node restarts -- ```cache.trie.rejournal```: Time interval to regenerate the trie cache journal. +- ```cache.trie.rejournal```: Time interval to regenerate the trie cache journal -- ```cache.gc```: Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode). +- ```cache.gc```: Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode) -- ```cache.snapshot```: Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode). +- ```cache.snapshot```: Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode) -- ```cache.noprefetch```: Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data). +- ```cache.noprefetch```: Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data) -- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys. +- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys -- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain). +- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain) ### JsonRPC Options -- ```rpc.gascap```: Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite). +- ```rpc.gascap```: Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite) -- ```rpc.txfeecap```: Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap). +- ```rpc.txfeecap```: Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap) -- ```ipcdisable```: Disable the IPC-RPC server. +- ```ipcdisable```: Disable the IPC-RPC server -- ```ipcpath```: Filename for IPC socket/pipe within the datadir (explicit paths escape it). +- ```ipcpath```: Filename for IPC socket/pipe within the datadir (explicit paths escape it) -- ```jsonrpc.corsdomain```: Comma separated list of domains from which to accept cross. +- ```jsonrpc.corsdomain```: Comma separated list of domains from which to accept cross origin requests (browser enforced) - ```jsonrpc.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard. -- ```http```: Enable the HTTP-RPC server. +- ```http```: Enable the HTTP-RPC server + +- ```http.addr```: HTTP-RPC server listening interface + +- ```http.port```: HTTP-RPC server listening port -- ```http.addr```: HTTP-RPC server listening interface. - -- ```http.port```: HTTP-RPC server listening port. - - ```http.rpcprefix```: HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths. -- ```http.modules```: API's offered over the HTTP-RPC interface. +- ```http.modules```: API's offered over the HTTP-RPC interface -- ```ws```: Enable the WS-RPC server. +- ```ws```: Enable the WS-RPC server -- ```ws.addr```: WS-RPC server listening interface. +- ```ws.addr```: WS-RPC server listening interface -- ```ws.port```: WS-RPC server listening port. +- ```ws.port```: WS-RPC server listening port - ```ws.rpcprefix```: HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths. -- ```ws.modules```: API's offered over the WS-RPC interface. +- ```ws.modules```: API's offered over the WS-RPC interface - ```graphql```: Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well. @@ -139,56 +118,78 @@ The ```bor server``` command runs the Bor client. - ```bootnodes```: Comma separated enode URLs for P2P discovery bootstrap -- ```maxpeers```: "Maximum number of network peers (network disabled if set to 0) +- ```maxpeers```: Maximum number of network peers (network disabled if set to 0) - ```maxpendpeers```: Maximum number of pending connection attempts (defaults used if set to 0) -- ```nat```: "NAT port mapping mechanism (any|none|upnp|pmp|extip:) +- ```nat```: NAT port mapping mechanism (any|none|upnp|pmp|extip:) -- ```nodiscover```: "Disables the peer discovery mechanism (manual peer addition) +- ```nodiscover```: Disables the peer discovery mechanism (manual peer addition) -- ```v5disc```: "Enables the experimental RLPx V5 (Topic Discovery) mechanism +- ```v5disc```: Enables the experimental RLPx V5 (Topic Discovery) mechanism + +### Sealer Options + +- ```mine```: Enable mining + +- ```miner.etherbase```: Public address for block mining rewards (default = first account) + +- ```miner.extradata```: Block extra data set by the miner (default = client version) + +- ```miner.gaslimit```: Target gas ceiling for mined blocks + +- ```miner.gasprice```: Minimum gas price for mining a transaction ### Telemetry Options -- ```metrics```: Enable metrics collection and reporting. +- ```metrics```: Enable metrics collection and reporting -- ```metrics.expensive```: Enable expensive metrics collection and reporting. +- ```metrics.expensive```: Enable expensive metrics collection and reporting -- ```metrics.influxdb```: Enable metrics export/push to an external InfluxDB database (v1). +- ```metrics.influxdb```: Enable metrics export/push to an external InfluxDB database (v1) -- ```metrics.influxdb.endpoint```: InfluxDB API endpoint to report metrics to. +- ```metrics.influxdb.endpoint```: InfluxDB API endpoint to report metrics to -- ```metrics.influxdb.database```: InfluxDB database name to push reported metrics to. +- ```metrics.influxdb.database```: InfluxDB database name to push reported metrics to -- ```metrics.influxdb.username```: Username to authorize access to the database. +- ```metrics.influxdb.username```: Username to authorize access to the database -- ```metrics.influxdb.password```: Password to authorize access to the database. +- ```metrics.influxdb.password```: Password to authorize access to the database -- ```metrics.influxdb.tags```: Comma-separated InfluxDB tags (key/values) attached to all measurements. +- ```metrics.influxdb.tags```: Comma-separated InfluxDB tags (key/values) attached to all measurements -- ```metrics.influxdbv2```: Enable metrics export/push to an external InfluxDB v2 database. +- ```metrics.prometheus-addr```: Address for Prometheus Server -- ```metrics.influxdb.token```: Token to authorize access to the database (v2 only). +- ```metrics.opencollector-endpoint```: OpenCollector Endpoint (host:port) -- ```metrics.influxdb.bucket```: InfluxDB bucket name to push reported metrics to (v2 only). +- ```metrics.influxdbv2```: Enable metrics export/push to an external InfluxDB v2 database -- ```metrics.influxdb.organization```: InfluxDB organization name (v2 only). +- ```metrics.influxdb.token```: Token to authorize access to the database (v2 only) -### Account Management Options +- ```metrics.influxdb.bucket```: InfluxDB bucket name to push reported metrics to (v2 only) + +- ```metrics.influxdb.organization```: InfluxDB organization name (v2 only) + +### Transaction Pool Options + +- ```txpool.locals```: Comma separated accounts to treat as locals (no flush, priority inclusion) -- ```unlock```: "Comma separated list of accounts to unlock. +- ```txpool.nolocals```: Disables price exemptions for locally submitted transactions -- ```password```: Password file to use for non-interactive password input. +- ```txpool.journal```: Disk journal for local transaction to survive node restarts -- ```allow-insecure-unlock```: Allow insecure account unlocking when account-related RPCs are exposed by http. +- ```txpool.rejournal```: Time interval to regenerate the local transaction journal -- ```lightkdf```: Reduce key-derivation RAM & CPU usage at some expense of KDF strength. +- ```txpool.pricelimit```: Minimum gas price limit to enforce for acceptance into the pool -## Usage +- ```txpool.pricebump```: Price bump percentage to replace an already existing transaction -Use multiple files to configure the client: +- ```txpool.accountslots```: Minimum number of executable transaction slots guaranteed per account -``` -$ bor server --config ./legacy-config.toml --config ./config2.hcl -``` +- ```txpool.globalslots```: Maximum number of executable transaction slots for all accounts + +- ```txpool.accountqueue```: Maximum number of non-executable transaction slots permitted per account + +- ```txpool.globalqueue```: Maximum number of non-executable transaction slots for all accounts + +- ```txpool.lifetime```: Maximum amount of time non-executable transaction are queued diff --git a/docs/cli/status.md b/docs/cli/status.md index fb7bddb182..9fa8e25905 100644 --- a/docs/cli/status.md +++ b/docs/cli/status.md @@ -1,4 +1,3 @@ - # Status -The ```status``` command outputs the status of the client. +The ```status``` command outputs the status of the client. \ No newline at end of file diff --git a/docs/cli/version.md b/docs/cli/version.md index 156bdf607c..87e7cf44a8 100644 --- a/docs/cli/version.md +++ b/docs/cli/version.md @@ -1,4 +1,3 @@ - # Version The ```bor version``` command outputs the version of the binary. @@ -8,4 +7,4 @@ The ```bor version``` command outputs the version of the binary. ``` $ bor version 0.2.9-stable -``` +``` \ No newline at end of file diff --git a/internal/cli/account.go b/internal/cli/account.go index b8661821d0..7ce6c09b63 100644 --- a/internal/cli/account.go +++ b/internal/cli/account.go @@ -1,11 +1,27 @@ package cli -import "github.com/mitchellh/cli" +import ( + "strings" + + "github.com/mitchellh/cli" +) type Account struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (a *Account) MarkDown() string { + items := []string{ + "# Account", + "The ```account``` command groups actions to interact with accounts:", + "- [```account new```](./account_new.md): Create a new account in the Bor client.", + "- [```account list```](./account_list.md): List the wallets in the Bor client.", + "- [```account import```](./account_import.md): Import an account to the Bor client.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (a *Account) Help() string { return `Usage: bor account diff --git a/internal/cli/account_import.go b/internal/cli/account_import.go index 8c9ff40e58..d7ab14601a 100644 --- a/internal/cli/account_import.go +++ b/internal/cli/account_import.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "strings" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/crypto" @@ -12,6 +13,16 @@ type AccountImportCommand struct { *Meta } +// MarkDown implements cli.MarkDown interface +func (a *AccountImportCommand) MarkDown() string { + items := []string{ + "# Account import", + "The ```account import``` command imports an account in Json format to the Bor data directory.", + a.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (a *AccountImportCommand) Help() string { return `Usage: bor account import diff --git a/internal/cli/account_list.go b/internal/cli/account_list.go index 360d41b558..db77158b8e 100644 --- a/internal/cli/account_list.go +++ b/internal/cli/account_list.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "strings" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/internal/cli/flagset" @@ -11,6 +12,16 @@ type AccountListCommand struct { *Meta } +// MarkDown implements cli.MarkDown interface +func (a *AccountListCommand) MarkDown() string { + items := []string{ + "# Account list", + "The `account list` command lists all the accounts in the Bor data directory.", + a.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (a *AccountListCommand) Help() string { return `Usage: bor account list diff --git a/internal/cli/account_new.go b/internal/cli/account_new.go index 3334384cb0..f6591fc53b 100644 --- a/internal/cli/account_new.go +++ b/internal/cli/account_new.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "strings" "github.com/ethereum/go-ethereum/internal/cli/flagset" ) @@ -10,6 +11,16 @@ type AccountNewCommand struct { *Meta } +// MarkDown implements cli.MarkDown interface +func (a *AccountNewCommand) MarkDown() string { + items := []string{ + "# Account new", + "The `account new` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command.", + a.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (a *AccountNewCommand) Help() string { return `Usage: bor account new diff --git a/internal/cli/attach.go b/internal/cli/attach.go index eec8a28ed3..df1c76ff3d 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -26,6 +26,16 @@ type AttachCommand struct { JSpathFlag string } +// MarkDown implements cli.MarkDown interface +func (c *AttachCommand) MarkDown() string { + items := []string{ + "# Attach", + "Connect to remote Bor IPC console.", + c.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *AttachCommand) Help() string { return `Usage: bor attach diff --git a/internal/cli/bor_fingerprint.go b/internal/cli/bor_fingerprint.go index 5c5a8f47bd..e9f4e70398 100644 --- a/internal/cli/bor_fingerprint.go +++ b/internal/cli/bor_fingerprint.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "os/exec" + "strings" "github.com/ethereum/go-ethereum/params" "github.com/mitchellh/cli" @@ -18,6 +19,15 @@ type FingerprintCommand struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (c *FingerprintCommand) MarkDown() string { + items := []string{ + "# Fingerprint", + "Display the system fingerprint", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *FingerprintCommand) Help() string { return `Usage: bor fingerprint diff --git a/internal/cli/chain.go b/internal/cli/chain.go index b43f22f999..896ce42cc4 100644 --- a/internal/cli/chain.go +++ b/internal/cli/chain.go @@ -1,6 +1,8 @@ package cli import ( + "strings" + "github.com/mitchellh/cli" ) @@ -9,6 +11,17 @@ type ChainCommand struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (c *ChainCommand) MarkDown() string { + items := []string{ + "# Chain", + "The ```chain``` command groups actions to interact with the blockchain in the client:", + "- [```chain sethead```](./chain_sethead.md): Set the current chain to a certain block.", + "- [```chain watch```](./chain_watch.md): Watch the chainHead, reorg and fork events in real-time.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *ChainCommand) Help() string { return `Usage: bor chain diff --git a/internal/cli/chain_sethead.go b/internal/cli/chain_sethead.go index 127ac38f15..4d34479e0b 100644 --- a/internal/cli/chain_sethead.go +++ b/internal/cli/chain_sethead.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/server/proto" @@ -16,6 +17,18 @@ type ChainSetHeadCommand struct { yes bool } +// MarkDown implements cli.MarkDown interface +func (a *ChainSetHeadCommand) MarkDown() string { + items := []string{ + "# Chain sethead", + "The ```chain sethead ``` command sets the current chain to a certain block.", + "## Arguments", + "- ```number```: The block number to roll back.", + a.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *ChainSetHeadCommand) Help() string { return `Usage: bor chain sethead [--yes] diff --git a/internal/cli/chain_watch.go b/internal/cli/chain_watch.go index 9469c1df00..72bd21b85d 100644 --- a/internal/cli/chain_watch.go +++ b/internal/cli/chain_watch.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "os/signal" + "strings" "syscall" "github.com/ethereum/go-ethereum/core" @@ -17,6 +18,15 @@ type ChainWatchCommand struct { *Meta2 } +// MarkDown implements cli.MarkDown interface +func (c *ChainWatchCommand) MarkDown() string { + items := []string{ + "# Chain watch", + "The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *ChainWatchCommand) Help() string { return `Usage: bor chain watch diff --git a/internal/cli/command.go b/internal/cli/command.go index 9e373a65cd..4cb089b9ff 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -14,13 +14,29 @@ import ( "google.golang.org/grpc" ) +type MarkDownCommand interface { + MarkDown + cli.Command +} + +type MarkDownCommandFactory func() (MarkDownCommand, error) + func Run(args []string) int { - commands := commands() + commands := Commands() + + mappedCommands := make(map[string]cli.CommandFactory) + + for k, v := range commands { + mappedCommands[k] = func() (cli.Command, error) { + cmd, err := v() + return cmd.(cli.Command), err + } + } cli := &cli.CLI{ Name: "bor", Args: args, - Commands: commands, + Commands: mappedCommands, } exitCode, err := cli.Run() @@ -31,7 +47,7 @@ func Run(args []string) int { return exitCode } -func commands() map[string]cli.CommandFactory { +func Commands() map[string]MarkDownCommandFactory { ui := &cli.BasicUi{ Reader: os.Stdin, Writer: os.Stdout, @@ -44,93 +60,93 @@ func commands() map[string]cli.CommandFactory { meta := &Meta{ UI: ui, } - return map[string]cli.CommandFactory{ - "server": func() (cli.Command, error) { + return map[string]MarkDownCommandFactory{ + "server": func() (MarkDownCommand, error) { return &server.Command{ UI: ui, }, nil }, - "version": func() (cli.Command, error) { + "version": func() (MarkDownCommand, error) { return &VersionCommand{ UI: ui, }, nil }, - "debug": func() (cli.Command, error) { + "debug": func() (MarkDownCommand, error) { return &DebugCommand{ Meta2: meta2, }, nil }, - "chain": func() (cli.Command, error) { + "chain": func() (MarkDownCommand, error) { return &ChainCommand{ UI: ui, }, nil }, - "chain watch": func() (cli.Command, error) { + "chain watch": func() (MarkDownCommand, error) { return &ChainWatchCommand{ Meta2: meta2, }, nil }, - "chain sethead": func() (cli.Command, error) { + "chain sethead": func() (MarkDownCommand, error) { return &ChainSetHeadCommand{ Meta2: meta2, }, nil }, - "account": func() (cli.Command, error) { + "account": func() (MarkDownCommand, error) { return &Account{ UI: ui, }, nil }, - "account new": func() (cli.Command, error) { + "account new": func() (MarkDownCommand, error) { return &AccountNewCommand{ Meta: meta, }, nil }, - "account import": func() (cli.Command, error) { + "account import": func() (MarkDownCommand, error) { return &AccountImportCommand{ Meta: meta, }, nil }, - "account list": func() (cli.Command, error) { + "account list": func() (MarkDownCommand, error) { return &AccountListCommand{ Meta: meta, }, nil }, - "peers": func() (cli.Command, error) { + "peers": func() (MarkDownCommand, error) { return &PeersCommand{ UI: ui, }, nil }, - "peers add": func() (cli.Command, error) { + "peers add": func() (MarkDownCommand, error) { return &PeersAddCommand{ Meta2: meta2, }, nil }, - "peers remove": func() (cli.Command, error) { + "peers remove": func() (MarkDownCommand, error) { return &PeersRemoveCommand{ Meta2: meta2, }, nil }, - "peers list": func() (cli.Command, error) { + "peers list": func() (MarkDownCommand, error) { return &PeersListCommand{ Meta2: meta2, }, nil }, - "peers status": func() (cli.Command, error) { + "peers status": func() (MarkDownCommand, error) { return &PeersStatusCommand{ Meta2: meta2, }, nil }, - "status": func() (cli.Command, error) { + "status": func() (MarkDownCommand, error) { return &StatusCommand{ Meta2: meta2, }, nil }, - "fingerprint": func() (cli.Command, error) { + "fingerprint": func() (MarkDownCommand, error) { return &FingerprintCommand{ UI: ui, }, nil }, - "attach": func() (cli.Command, error) { + "attach": func() (MarkDownCommand, error) { return &AttachCommand{ UI: ui, Meta: meta, diff --git a/internal/cli/debug.go b/internal/cli/debug.go index a6b6ff7973..66e936995c 100644 --- a/internal/cli/debug.go +++ b/internal/cli/debug.go @@ -31,6 +31,33 @@ type DebugCommand struct { output string } +// MarkDown implements cli.MarkDown interface +func (d *DebugCommand) MarkDown() string { + examples := []string{ + "## Examples", + "By default it creates a tar.gz file with the output:", + CodeBlock([]string{ + "$ bor debug", + "Starting debugger...\n", + "Created debug archive: bor-debug-2021-10-26-073819Z.tar.gz", + }), + "Send the output to a specific directory:", + CodeBlock([]string{ + "$ bor debug --output data", + "Starting debugger...\n", + "Created debug directory: data/bor-debug-2021-10-26-075437Z", + }), + } + + items := []string{ + "# Debug", + "The ```bor debug``` command takes a debug dump of the running client.", + d.Flags().MarkDown(), + } + items = append(items, examples...) + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (d *DebugCommand) Help() string { return `Usage: bor debug diff --git a/internal/cli/flagset/flagset.go b/internal/cli/flagset/flagset.go index 4388dd03fc..e04f452c1e 100644 --- a/internal/cli/flagset/flagset.go +++ b/internal/cli/flagset/flagset.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "math/big" + "sort" "strings" "time" ) @@ -24,6 +25,7 @@ func NewFlagSet(name string) *Flagset { type FlagVar struct { Name string Usage string + Group string } func (f *Flagset) addFlag(fl *FlagVar) { @@ -39,6 +41,40 @@ func (f *Flagset) Help() string { return str + strings.Join(items, "\n\n") } +// MarkDown implements cli.MarkDown interface +func (f *Flagset) MarkDown() string { + if len(f.flags) == 0 { + return "" + } + + groups := make(map[string][]*FlagVar) + + for _, item := range f.flags { + groups[item.Group] = append(groups[item.Group], item) + } + + keys := make([]string, len(groups)) + i := 0 + for k := range groups { + keys[i] = k + i++ + } + sort.Strings(keys) + + items := []string{} + for _, k := range keys { + if k == "" { + items = append(items, fmt.Sprintf("## Options")) + } else { + items = append(items, fmt.Sprintf("### %s Options", k)) + } + for _, item := range groups[k] { + items = append(items, fmt.Sprintf("- ```%s```: %s", item.Name, item.Usage)) + } + } + return strings.Join(items, "\n\n") +} + func (f *Flagset) Parse(args []string) error { return f.set.Parse(args) } @@ -52,12 +88,14 @@ type BoolFlag struct { Usage string Default bool Value *bool + Group string } func (f *Flagset) BoolFlag(b *BoolFlag) { f.addFlag(&FlagVar{ Name: b.Name, Usage: b.Usage, + Group: b.Group, }) f.set.BoolVar(b.Value, b.Name, b.Default, b.Usage) } @@ -67,12 +105,14 @@ type StringFlag struct { Usage string Default string Value *string + Group string } func (f *Flagset) StringFlag(b *StringFlag) { f.addFlag(&FlagVar{ Name: b.Name, Usage: b.Usage, + Group: b.Group, }) f.set.StringVar(b.Value, b.Name, b.Default, b.Usage) } @@ -82,12 +122,14 @@ type IntFlag struct { Usage string Value *int Default int + Group string } func (f *Flagset) IntFlag(i *IntFlag) { f.addFlag(&FlagVar{ Name: i.Name, Usage: i.Usage, + Group: i.Group, }) f.set.IntVar(i.Value, i.Name, i.Default, i.Usage) } @@ -97,12 +139,14 @@ type Uint64Flag struct { Usage string Value *uint64 Default uint64 + Group string } func (f *Flagset) Uint64Flag(i *Uint64Flag) { f.addFlag(&FlagVar{ Name: i.Name, Usage: i.Usage, + Group: i.Group, }) f.set.Uint64Var(i.Value, i.Name, i.Default, i.Usage) } @@ -111,6 +155,7 @@ type BigIntFlag struct { Name string Usage string Value *big.Int + Group string } func (b *BigIntFlag) String() string { @@ -140,6 +185,7 @@ func (f *Flagset) BigIntFlag(b *BigIntFlag) { f.addFlag(&FlagVar{ Name: b.Name, Usage: b.Usage, + Group: b.Group, }) f.set.Var(b, b.Name, b.Usage) } @@ -148,6 +194,7 @@ type SliceStringFlag struct { Name string Usage string Value *[]string + Group string } func (i *SliceStringFlag) String() string { @@ -166,6 +213,7 @@ func (f *Flagset) SliceStringFlag(s *SliceStringFlag) { f.addFlag(&FlagVar{ Name: s.Name, Usage: s.Usage, + Group: s.Group, }) f.set.Var(s, s.Name, s.Usage) } @@ -175,12 +223,14 @@ type DurationFlag struct { Usage string Value *time.Duration Default time.Duration + Group string } func (f *Flagset) DurationFlag(d *DurationFlag) { f.addFlag(&FlagVar{ Name: d.Name, Usage: d.Usage, + Group: d.Group, }) f.set.DurationVar(d.Value, d.Name, d.Default, "") } @@ -189,6 +239,7 @@ type MapStringFlag struct { Name string Usage string Value *map[string]string + Group string } func (m *MapStringFlag) String() string { @@ -222,6 +273,7 @@ func (f *Flagset) MapStringFlag(m *MapStringFlag) { f.addFlag(&FlagVar{ Name: m.Name, Usage: m.Usage, + Group: m.Group, }) f.set.Var(m, m.Name, m.Usage) } @@ -231,12 +283,14 @@ type Float64Flag struct { Usage string Value *float64 Default float64 + Group string } func (f *Flagset) Float64Flag(i *Float64Flag) { f.addFlag(&FlagVar{ Name: i.Name, Usage: i.Usage, + Group: i.Group, }) f.set.Float64Var(i.Value, i.Name, i.Default, "") } diff --git a/internal/cli/markdown.go b/internal/cli/markdown.go new file mode 100644 index 0000000000..652c98e56b --- /dev/null +++ b/internal/cli/markdown.go @@ -0,0 +1,14 @@ +package cli + +import ( + "strings" +) + +type MarkDown interface { + MarkDown() string +} + +// Create a Markdown code block from a slice of string, where each string is a line of code +func CodeBlock(lines []string) string { + return "```\n" + strings.Join(lines, "\n") + "\n```" +} diff --git a/internal/cli/markdown_test.go b/internal/cli/markdown_test.go new file mode 100644 index 0000000000..13a5c4ece3 --- /dev/null +++ b/internal/cli/markdown_test.go @@ -0,0 +1,19 @@ +package cli + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCodeBlock(t *testing.T) { + assert := assert.New(t) + + lines := []string{ + "abc", + "bcd", + } + + expected := "```\n" + "abc\n" + "bcd\n" + "```" + assert.Equal(expected, CodeBlock(lines)) +} diff --git a/internal/cli/peers.go b/internal/cli/peers.go index b591366222..ee70a747b8 100644 --- a/internal/cli/peers.go +++ b/internal/cli/peers.go @@ -1,6 +1,8 @@ package cli import ( + "strings" + "github.com/mitchellh/cli" ) @@ -9,6 +11,19 @@ type PeersCommand struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (a *PeersCommand) MarkDown() string { + items := []string{ + "# Peers", + "The ```peers``` command groups actions to interact with peers:", + "- [```peers add```](./peers_add.md): Joins the local client to another remote peer.", + "- [```peers list```](./peers_list.md): Lists the connected peers to the Bor client.", + "- [```peers remove```](./peers_remove.md): Disconnects the local client from a connected peer if exists.", + "- [```peers status```](./peers_status.md): Display the status of a peer by its id.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *PeersCommand) Help() string { return `Usage: bor peers diff --git a/internal/cli/peers_add.go b/internal/cli/peers_add.go index 2b2fe127e0..ae84f4e0c1 100644 --- a/internal/cli/peers_add.go +++ b/internal/cli/peers_add.go @@ -2,6 +2,7 @@ package cli import ( "context" + "strings" "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/server/proto" @@ -14,6 +15,16 @@ type PeersAddCommand struct { trusted bool } +// MarkDown implements cli.MarkDown interface +func (p *PeersAddCommand) MarkDown() string { + items := []string{ + "# Peers add", + "The ```peers add ``` command joins the local client to another remote peer.", + p.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *PeersAddCommand) Help() string { return `Usage: bor peers add diff --git a/internal/cli/peers_list.go b/internal/cli/peers_list.go index a42e0011a5..56dfdc317d 100644 --- a/internal/cli/peers_list.go +++ b/internal/cli/peers_list.go @@ -14,6 +14,16 @@ type PeersListCommand struct { *Meta2 } +// MarkDown implements cli.MarkDown interface +func (p *PeersListCommand) MarkDown() string { + items := []string{ + "# Peers add", + "The ```peers list``` command lists the connected peers.", + p.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *PeersListCommand) Help() string { return `Usage: bor peers list diff --git a/internal/cli/peers_remove.go b/internal/cli/peers_remove.go index 979f139251..5cd3796e3c 100644 --- a/internal/cli/peers_remove.go +++ b/internal/cli/peers_remove.go @@ -2,6 +2,7 @@ package cli import ( "context" + "strings" "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/server/proto" @@ -14,6 +15,16 @@ type PeersRemoveCommand struct { trusted bool } +// MarkDown implements cli.MarkDown interface +func (p *PeersRemoveCommand) MarkDown() string { + items := []string{ + "# Peers remove", + "The ```peers remove ``` command disconnects the local client from a connected peer if exists.", + p.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *PeersRemoveCommand) Help() string { return `Usage: bor peers remove diff --git a/internal/cli/peers_status.go b/internal/cli/peers_status.go index c1da2b2647..bb8d385291 100644 --- a/internal/cli/peers_status.go +++ b/internal/cli/peers_status.go @@ -14,6 +14,16 @@ type PeersStatusCommand struct { *Meta2 } +// MarkDown implements cli.MarkDown interface +func (p *PeersStatusCommand) MarkDown() string { + items := []string{ + "# Peers status", + "The ```peers status ``` command displays the status of a peer by its id.", + p.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *PeersStatusCommand) Help() string { return `Usage: bor peers status diff --git a/internal/cli/server/command.go b/internal/cli/server/command.go index 4b2374dc42..01ce44f5ee 100644 --- a/internal/cli/server/command.go +++ b/internal/cli/server/command.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "os/signal" + "strings" "syscall" "github.com/ethereum/go-ethereum/log" @@ -25,6 +26,16 @@ type Command struct { srv *Server } +// MarkDown implements cli.MarkDown interface +func (c *Command) MarkDown() string { + items := []string{ + "# Server", + "The ```bor server``` command runs the Bor client.", + c.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *Command) Help() string { return `Usage: bor [options] diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index edc7276a8b..ce93e8c071 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -36,7 +36,7 @@ func (c *Command) Flags() *flagset.Flagset { }) f.StringFlag(&flagset.StringFlag{ Name: "syncmode", - Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`, + Usage: `Blockchain sync mode ("fast", "full", or "snap")`, Value: &c.cliConfig.SyncMode, }) f.StringFlag(&flagset.StringFlag{ @@ -72,56 +72,67 @@ func (c *Command) Flags() *flagset.Flagset { Name: "txpool.locals", Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", Value: &c.cliConfig.TxPool.Locals, + Group: "Transaction Pool", }) f.BoolFlag(&flagset.BoolFlag{ Name: "txpool.nolocals", Usage: "Disables price exemptions for locally submitted transactions", Value: &c.cliConfig.TxPool.NoLocals, + Group: "Transaction Pool", }) f.StringFlag(&flagset.StringFlag{ Name: "txpool.journal", Usage: "Disk journal for local transaction to survive node restarts", Value: &c.cliConfig.TxPool.Journal, + Group: "Transaction Pool", }) f.DurationFlag(&flagset.DurationFlag{ Name: "txpool.rejournal", Usage: "Time interval to regenerate the local transaction journal", Value: &c.cliConfig.TxPool.Rejournal, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.pricelimit", Usage: "Minimum gas price limit to enforce for acceptance into the pool", Value: &c.cliConfig.TxPool.PriceLimit, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.pricebump", Usage: "Price bump percentage to replace an already existing transaction", Value: &c.cliConfig.TxPool.PriceBump, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.accountslots", Usage: "Minimum number of executable transaction slots guaranteed per account", Value: &c.cliConfig.TxPool.AccountSlots, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.globalslots", Usage: "Maximum number of executable transaction slots for all accounts", Value: &c.cliConfig.TxPool.GlobalSlots, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.accountqueue", Usage: "Maximum number of non-executable transaction slots permitted per account", Value: &c.cliConfig.TxPool.AccountQueue, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.globalqueue", Usage: "Maximum number of non-executable transaction slots for all accounts", Value: &c.cliConfig.TxPool.GlobalQueue, + Group: "Transaction Pool", }) f.DurationFlag(&flagset.DurationFlag{ Name: "txpool.lifetime", Usage: "Maximum amount of time non-executable transaction are queued", Value: &c.cliConfig.TxPool.LifeTime, + Group: "Transaction Pool", }) // sealer options @@ -129,26 +140,31 @@ func (c *Command) Flags() *flagset.Flagset { Name: "mine", Usage: "Enable mining", Value: &c.cliConfig.Sealer.Enabled, + Group: "Sealer", }) f.StringFlag(&flagset.StringFlag{ Name: "miner.etherbase", Usage: "Public address for block mining rewards (default = first account)", Value: &c.cliConfig.Sealer.Etherbase, + Group: "Sealer", }) f.StringFlag(&flagset.StringFlag{ Name: "miner.extradata", Usage: "Block extra data set by the miner (default = client version)", Value: &c.cliConfig.Sealer.ExtraData, + Group: "Sealer", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "miner.gaslimit", Usage: "Target gas ceiling for mined blocks", Value: &c.cliConfig.Sealer.GasCeil, + Group: "Sealer", }) f.BigIntFlag(&flagset.BigIntFlag{ Name: "miner.gasprice", Usage: "Minimum gas price for mining a transaction", Value: c.cliConfig.Sealer.GasPrice, + Group: "Sealer", }) // ethstats @@ -185,51 +201,61 @@ func (c *Command) Flags() *flagset.Flagset { Name: "cache", Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)", Value: &c.cliConfig.Cache.Cache, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "cache.database", Usage: "Percentage of cache memory allowance to use for database io", Value: &c.cliConfig.Cache.PercDatabase, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "cache.trie", Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", Value: &c.cliConfig.Cache.PercTrie, + Group: "Cache", }) f.StringFlag(&flagset.StringFlag{ Name: "cache.trie.journal", Usage: "Disk journal directory for trie cache to survive node restarts", Value: &c.cliConfig.Cache.Journal, + Group: "Cache", }) f.DurationFlag(&flagset.DurationFlag{ Name: "cache.trie.rejournal", Usage: "Time interval to regenerate the trie cache journal", Value: &c.cliConfig.Cache.Rejournal, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "cache.gc", Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", Value: &c.cliConfig.Cache.PercGc, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "cache.snapshot", Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", Value: &c.cliConfig.Cache.PercSnapshot, + Group: "Cache", }) f.BoolFlag(&flagset.BoolFlag{ Name: "cache.noprefetch", Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", Value: &c.cliConfig.Cache.NoPrefetch, + Group: "Cache", }) f.BoolFlag(&flagset.BoolFlag{ Name: "cache.preimages", Usage: "Enable recording the SHA3/keccak preimages of trie keys", Value: &c.cliConfig.Cache.Preimages, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txlookuplimit", Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)", Value: &c.cliConfig.Cache.TxLookupLimit, + Group: "Cache", }) // rpc options @@ -237,31 +263,37 @@ func (c *Command) Flags() *flagset.Flagset { Name: "rpc.gascap", Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", Value: &c.cliConfig.JsonRPC.GasCap, + Group: "JsonRPC", }) f.Float64Flag(&flagset.Float64Flag{ Name: "rpc.txfeecap", Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", Value: &c.cliConfig.JsonRPC.TxFeeCap, + Group: "JsonRPC", }) f.BoolFlag(&flagset.BoolFlag{ Name: "ipcdisable", Usage: "Disable the IPC-RPC server", Value: &c.cliConfig.JsonRPC.IPCDisable, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "ipcpath", Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", Value: &c.cliConfig.JsonRPC.IPCPath, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "jsonrpc.corsdomain", Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", Value: &c.cliConfig.JsonRPC.Cors, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "jsonrpc.vhosts", Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", Value: &c.cliConfig.JsonRPC.VHost, + Group: "JsonRPC", }) // http options @@ -269,26 +301,31 @@ func (c *Command) Flags() *flagset.Flagset { Name: "http", Usage: "Enable the HTTP-RPC server", Value: &c.cliConfig.JsonRPC.Http.Enabled, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "http.addr", Usage: "HTTP-RPC server listening interface", Value: &c.cliConfig.JsonRPC.Http.Host, + Group: "JsonRPC", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "http.port", Usage: "HTTP-RPC server listening port", Value: &c.cliConfig.JsonRPC.Http.Port, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "http.rpcprefix", Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", Value: &c.cliConfig.JsonRPC.Http.Prefix, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "http.modules", Usage: "API's offered over the HTTP-RPC interface", Value: &c.cliConfig.JsonRPC.Http.Modules, + Group: "JsonRPC", }) // ws options @@ -296,26 +333,31 @@ func (c *Command) Flags() *flagset.Flagset { Name: "ws", Usage: "Enable the WS-RPC server", Value: &c.cliConfig.JsonRPC.Ws.Enabled, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "ws.addr", Usage: "WS-RPC server listening interface", Value: &c.cliConfig.JsonRPC.Ws.Host, + Group: "JsonRPC", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "ws.port", Usage: "WS-RPC server listening port", Value: &c.cliConfig.JsonRPC.Ws.Port, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "ws.rpcprefix", Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", Value: &c.cliConfig.JsonRPC.Ws.Prefix, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "ws.modules", Usage: "API's offered over the WS-RPC interface", Value: &c.cliConfig.JsonRPC.Ws.Modules, + Group: "JsonRPC", }) // graphql options @@ -323,6 +365,7 @@ func (c *Command) Flags() *flagset.Flagset { Name: "graphql", Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.", Value: &c.cliConfig.JsonRPC.Graphql.Enabled, + Group: "JsonRPC", }) // p2p options @@ -330,41 +373,49 @@ func (c *Command) Flags() *flagset.Flagset { Name: "bind", Usage: "Network binding address", Value: &c.cliConfig.P2P.Bind, + Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "port", Usage: "Network listening port", Value: &c.cliConfig.P2P.Port, + Group: "P2P", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "bootnodes", Usage: "Comma separated enode URLs for P2P discovery bootstrap", Value: &c.cliConfig.P2P.Discovery.Bootnodes, + Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "maxpeers", Usage: "Maximum number of network peers (network disabled if set to 0)", Value: &c.cliConfig.P2P.MaxPeers, + Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "maxpendpeers", Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", Value: &c.cliConfig.P2P.MaxPendPeers, + Group: "P2P", }) f.StringFlag(&flagset.StringFlag{ Name: "nat", Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", Value: &c.cliConfig.P2P.NAT, + Group: "P2P", }) f.BoolFlag(&flagset.BoolFlag{ Name: "nodiscover", Usage: "Disables the peer discovery mechanism (manual peer addition)", Value: &c.cliConfig.P2P.NoDiscover, + Group: "P2P", }) f.BoolFlag(&flagset.BoolFlag{ Name: "v5disc", Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", Value: &c.cliConfig.P2P.Discovery.V5Enabled, + Group: "P2P", }) // metrics @@ -372,72 +423,86 @@ func (c *Command) Flags() *flagset.Flagset { Name: "metrics", Usage: "Enable metrics collection and reporting", Value: &c.cliConfig.Telemetry.Enabled, + Group: "Telemetry", }) f.BoolFlag(&flagset.BoolFlag{ Name: "metrics.expensive", Usage: "Enable expensive metrics collection and reporting", Value: &c.cliConfig.Telemetry.Expensive, + Group: "Telemetry", }) f.BoolFlag(&flagset.BoolFlag{ Name: "metrics.influxdb", Usage: "Enable metrics export/push to an external InfluxDB database (v1)", Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.endpoint", Usage: "InfluxDB API endpoint to report metrics to", Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.database", Usage: "InfluxDB database name to push reported metrics to", Value: &c.cliConfig.Telemetry.InfluxDB.Database, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.username", Usage: "Username to authorize access to the database", Value: &c.cliConfig.Telemetry.InfluxDB.Username, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.password", Usage: "Password to authorize access to the database", Value: &c.cliConfig.Telemetry.InfluxDB.Password, + Group: "Telemetry", }) f.MapStringFlag(&flagset.MapStringFlag{ Name: "metrics.influxdb.tags", Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", Value: &c.cliConfig.Telemetry.InfluxDB.Tags, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.prometheus-addr", Usage: "Address for Prometheus Server", Value: &c.cliConfig.Telemetry.PrometheusAddr, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.opencollector-endpoint", Usage: "OpenCollector Endpoint (host:port)", Value: &c.cliConfig.Telemetry.OpenCollectorEndpoint, + Group: "Telemetry", }) // influx db v2 f.BoolFlag(&flagset.BoolFlag{ Name: "metrics.influxdbv2", Usage: "Enable metrics export/push to an external InfluxDB v2 database", Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.token", Usage: "Token to authorize access to the database (v2 only)", Value: &c.cliConfig.Telemetry.InfluxDB.Token, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.bucket", Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", Value: &c.cliConfig.Telemetry.InfluxDB.Bucket, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.organization", Usage: "InfluxDB organization name (v2 only)", Value: &c.cliConfig.Telemetry.InfluxDB.Organization, + Group: "Telemetry", }) // account @@ -445,21 +510,25 @@ func (c *Command) Flags() *flagset.Flagset { Name: "unlock", Usage: "Comma separated list of accounts to unlock", Value: &c.cliConfig.Accounts.Unlock, + Group: "Account Management", }) f.StringFlag(&flagset.StringFlag{ Name: "password", Usage: "Password file to use for non-interactive password input", Value: &c.cliConfig.Accounts.PasswordFile, + Group: "Account Management", }) f.BoolFlag(&flagset.BoolFlag{ Name: "allow-insecure-unlock", Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", Value: &c.cliConfig.Accounts.AllowInsecureUnlock, + Group: "Account Management", }) f.BoolFlag(&flagset.BoolFlag{ Name: "lightkdf", Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", Value: &c.cliConfig.Accounts.UseLightweightKDF, + Group: "Account Management", }) // grpc diff --git a/internal/cli/status.go b/internal/cli/status.go index ef0a42172b..c4165b0a2e 100644 --- a/internal/cli/status.go +++ b/internal/cli/status.go @@ -14,6 +14,15 @@ type StatusCommand struct { *Meta2 } +// MarkDown implements cli.MarkDown interface +func (p *StatusCommand) MarkDown() string { + items := []string{ + "# Status", + "The ```status``` command outputs the status of the client.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *StatusCommand) Help() string { return `Usage: bor status diff --git a/internal/cli/version.go b/internal/cli/version.go index 7433f208b2..080cf41221 100644 --- a/internal/cli/version.go +++ b/internal/cli/version.go @@ -1,6 +1,8 @@ package cli import ( + "strings" + "github.com/ethereum/go-ethereum/params" "github.com/mitchellh/cli" ) @@ -10,6 +12,24 @@ type VersionCommand struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (d *VersionCommand) MarkDown() string { + examples := []string{ + "## Usage", + CodeBlock([]string{ + "$ bor version", + "0.2.9-stable", + }), + } + + items := []string{ + "# Version", + "The ```bor version``` command outputs the version of the binary.", + } + items = append(items, examples...) + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *VersionCommand) Help() string { return `Usage: bor version