flags.go 7.4 KB
Newer Older
1 2 3 4
package utils

import (
	"crypto/ecdsa"
5 6 7 8
	"fmt"
	"net"
	"net/http"
	"os"
9 10 11 12
	"path"
	"runtime"

	"github.com/codegangsta/cli"
F
Felix Lange 已提交
13
	"github.com/ethereum/go-ethereum/accounts"
Z
zelig 已提交
14
	"github.com/ethereum/go-ethereum/common"
15 16 17 18 19 20 21
	"github.com/ethereum/go-ethereum/core"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/eth"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/logger"
	"github.com/ethereum/go-ethereum/p2p/nat"
22 23
	"github.com/ethereum/go-ethereum/rpc"
	"github.com/ethereum/go-ethereum/xeth"
24 25
)

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
func init() {
	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]

VERSION:
   {{.Version}}

COMMANDS:
   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
   {{end}}{{if .Flags}}
GLOBAL OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}{{end}}
`

	cli.CommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...]
{{if .Description}}{{.Description}}
{{end}}{{if .Subcommands}}
SUBCOMMANDS:
	{{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
	{{end}}{{end}}{{if .Flags}}
OPTIONS:
	{{range .Flags}}{{.}}
	{{end}}{{end}}
`
}

F
Felix Lange 已提交
52 53 54 55 56
// NewApp creates an app with sane defaults.
func NewApp(version, usage string) *cli.App {
	app := cli.NewApp()
	app.Name = path.Base(os.Args[0])
	app.Author = ""
O
obscuren 已提交
57
	//app.Authors = nil
F
Felix Lange 已提交
58 59 60 61 62 63
	app.Email = ""
	app.Version = version
	app.Usage = usage
	return app
}

64 65 66 67 68 69 70 71 72 73 74 75
// These are all the command line flags we support.
// If you add to this list, please remember to include the
// flag in the appropriate command definition.
//
// The flags are defined here so their names and help texts
// are the same for all commands.

var (
	// General settings
	DataDirFlag = cli.StringFlag{
		Name:  "datadir",
		Usage: "Data directory to be used",
O
obscuren 已提交
76
		Value: common.DefaultDataDir(),
77
	}
Z
zelig 已提交
78 79 80 81 82 83 84 85 86 87 88 89
	ProtocolVersionFlag = cli.IntFlag{
		Name:  "protocolversion",
		Usage: "ETH protocol version",
		Value: eth.ProtocolVersion,
	}
	NetworkIdFlag = cli.IntFlag{
		Name:  "networkid",
		Usage: "Network Id",
		Value: eth.NetworkId,
	}

	// miner settings
90 91 92 93 94 95 96 97 98
	MinerThreadsFlag = cli.IntFlag{
		Name:  "minerthreads",
		Usage: "Number of miner threads",
		Value: runtime.NumCPU(),
	}
	MiningEnabledFlag = cli.BoolFlag{
		Name:  "mine",
		Usage: "Enable mining",
	}
Z
zelig 已提交
99
	EtherbaseFlag = cli.StringFlag{
O
obscuren 已提交
100
		Name:  "etherbase",
Z
zelig 已提交
101 102 103
		Usage: "public address for block mining rewards. By default the address of your primary account is used",
		Value: "primary",
	}
Z
zelig 已提交
104 105 106

	UnlockedAccountFlag = cli.StringFlag{
		Name:  "unlock",
Z
zelig 已提交
107
		Usage: "unlock the account given until this program exits (prompts for password). '--unlock primary' unlocks the primary account",
Z
zelig 已提交
108 109 110 111
		Value: "",
	}
	PasswordFileFlag = cli.StringFlag{
		Name:  "password",
Z
zelig 已提交
112
		Usage: "Path to password file for (un)locking an existing account.",
Z
zelig 已提交
113
		Value: "",
Z
zelig 已提交
114
	}
115

Z
zelig 已提交
116
	// logging and debug settings
117 118 119 120 121 122 123 124 125
	LogFileFlag = cli.StringFlag{
		Name:  "logfile",
		Usage: "Send log output to a file",
	}
	LogLevelFlag = cli.IntFlag{
		Name:  "loglevel",
		Usage: "0-5 (silent, error, warn, info, debug, debug detail)",
		Value: int(logger.InfoLevel),
	}
126 127 128 129
	LogJSONFlag = cli.StringFlag{
		Name:  "logjson",
		Usage: "Send json structured log output to a file or '-' for standard output (default: no json output)",
		Value: "",
130
	}
Z
zelig 已提交
131 132 133 134
	VMDebugFlag = cli.BoolFlag{
		Name:  "vmdebug",
		Usage: "Virtual Machine debug output",
	}
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180

	// RPC settings
	RPCEnabledFlag = cli.BoolFlag{
		Name:  "rpc",
		Usage: "Whether RPC server is enabled",
	}
	RPCListenAddrFlag = cli.StringFlag{
		Name:  "rpcaddr",
		Usage: "Listening address for the JSON-RPC server",
		Value: "127.0.0.1",
	}
	RPCPortFlag = cli.IntFlag{
		Name:  "rpcport",
		Usage: "Port on which the JSON-RPC server should listen",
		Value: 8545,
	}

	// Network Settings
	MaxPeersFlag = cli.IntFlag{
		Name:  "maxpeers",
		Usage: "Maximum number of network peers",
		Value: 16,
	}
	ListenPortFlag = cli.IntFlag{
		Name:  "port",
		Usage: "Network listening port",
		Value: 30303,
	}
	BootnodesFlag = cli.StringFlag{
		Name:  "bootnodes",
		Usage: "Space-separated enode URLs for discovery bootstrap",
		Value: "",
	}
	NodeKeyFileFlag = cli.StringFlag{
		Name:  "nodekey",
		Usage: "P2P node key file",
	}
	NodeKeyHexFlag = cli.StringFlag{
		Name:  "nodekeyhex",
		Usage: "P2P node key as hex (for testing)",
	}
	NATFlag = cli.StringFlag{
		Name:  "nat",
		Usage: "Port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
		Value: "any",
	}
Z
CLI:  
zelig 已提交
181 182 183 184 185
	JSpathFlag = cli.StringFlag{
		Name:  "jspath",
		Usage: "JS library path to be used with console and js subcommands",
		Value: ".",
	}
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
)

func GetNAT(ctx *cli.Context) nat.Interface {
	natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
	if err != nil {
		Fatalf("Option %s: %v", NATFlag.Name, err)
	}
	return natif
}

func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
	hex, file := ctx.GlobalString(NodeKeyHexFlag.Name), ctx.GlobalString(NodeKeyFileFlag.Name)
	var err error
	switch {
	case file != "" && hex != "":
		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
	case file != "":
		if key, err = crypto.LoadECDSA(file); err != nil {
			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
		}
	case hex != "":
		if key, err = crypto.HexToECDSA(hex); err != nil {
			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
		}
	}
	return key
}

214 215
func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
	return &eth.Config{
Z
zelig 已提交
216 217 218 219 220 221
		Name:            common.MakeName(clientID, version),
		DataDir:         ctx.GlobalString(DataDirFlag.Name),
		ProtocolVersion: ctx.GlobalInt(ProtocolVersionFlag.Name),
		NetworkId:       ctx.GlobalInt(NetworkIdFlag.Name),
		LogFile:         ctx.GlobalString(LogFileFlag.Name),
		LogLevel:        ctx.GlobalInt(LogLevelFlag.Name),
222
		LogJSON:         ctx.GlobalString(LogJSONFlag.Name),
Z
zelig 已提交
223
		Etherbase:       ctx.GlobalString(EtherbaseFlag.Name),
Z
zelig 已提交
224 225 226 227 228 229 230 231 232 233
		MinerThreads:    ctx.GlobalInt(MinerThreadsFlag.Name),
		AccountManager:  GetAccountManager(ctx),
		VmDebug:         ctx.GlobalBool(VMDebugFlag.Name),
		MaxPeers:        ctx.GlobalInt(MaxPeersFlag.Name),
		Port:            ctx.GlobalString(ListenPortFlag.Name),
		NAT:             GetNAT(ctx),
		NodeKey:         GetNodeKey(ctx),
		Shh:             true,
		Dial:            true,
		BootNodes:       ctx.GlobalString(BootnodesFlag.Name),
234
	}
235 236
}

O
obscuren 已提交
237
func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Database) {
238
	dataDir := ctx.GlobalString(DataDirFlag.Name)
239
	blockDb, err := ethdb.NewLDBDatabase(path.Join(dataDir, "blockchain"))
240 241 242
	if err != nil {
		Fatalf("Could not open database: %v", err)
	}
243 244 245 246 247 248

	stateDb, err := ethdb.NewLDBDatabase(path.Join(dataDir, "state"))
	if err != nil {
		Fatalf("Could not open database: %v", err)
	}
	return core.NewChainManager(blockDb, stateDb, new(event.TypeMux)), blockDb, stateDb
249
}
F
Felix Lange 已提交
250

251
func GetAccountManager(ctx *cli.Context) *accounts.Manager {
F
Felix Lange 已提交
252
	dataDir := ctx.GlobalString(DataDirFlag.Name)
253
	ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
254
	return accounts.NewManager(ks)
F
Felix Lange 已提交
255
}
256 257 258 259

func StartRPC(eth *eth.Ethereum, ctx *cli.Context) {
	addr := ctx.GlobalString(RPCListenAddrFlag.Name)
	port := ctx.GlobalInt(RPCPortFlag.Name)
260
	fmt.Println("Starting RPC on port: ", port)
261 262 263 264
	l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
	if err != nil {
		Fatalf("Can't listen on %s:%d: %v", addr, port, err)
	}
265
	go http.Serve(l, rpc.JSONRPC(xeth.New(eth, nil)))
266
}