2015-03-06 04:00:41 +02:00
package utils
import (
"crypto/ecdsa"
2015-03-10 00:00:27 +02:00
"os"
2015-03-06 04:00:41 +02:00
"path"
"runtime"
"github.com/codegangsta/cli"
2015-04-13 11:13:52 +03:00
"github.com/ethereum/ethash"
2015-03-07 13:39:52 +02:00
"github.com/ethereum/go-ethereum/accounts"
2015-03-18 09:44:58 +02:00
"github.com/ethereum/go-ethereum/common"
2015-03-06 04:00:41 +02:00
"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"
2015-04-03 18:09:01 +03:00
"github.com/ethereum/go-ethereum/logger/glog"
2015-03-06 04:00:41 +02:00
"github.com/ethereum/go-ethereum/p2p/nat"
2015-03-10 00:00:27 +02:00
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/xeth"
2015-03-06 04:00:41 +02:00
)
2015-03-10 17:44:48 +02:00
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 } }
`
}
2015-03-09 23:51:50 +02:00
// 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 = ""
2015-03-26 02:03:03 +02:00
//app.Authors = nil
2015-03-09 23:51:50 +02:00
app . Email = ""
app . Version = version
app . Usage = usage
return app
}
2015-03-06 04:00:41 +02:00
// 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
2015-04-08 16:43:55 +03:00
DataDirFlag = DirectoryFlag {
2015-03-06 04:00:41 +02:00
Name : "datadir" ,
Usage : "Data directory to be used" ,
2015-04-08 16:43:55 +03:00
Value : DirectoryString { common . DefaultDataDir ( ) } ,
2015-03-06 04:00:41 +02:00
}
2015-03-18 09:44:58 +02:00
ProtocolVersionFlag = cli . IntFlag {
Name : "protocolversion" ,
Usage : "ETH protocol version" ,
Value : eth . ProtocolVersion ,
}
NetworkIdFlag = cli . IntFlag {
Name : "networkid" ,
Usage : "Network Id" ,
Value : eth . NetworkId ,
}
2015-04-13 11:13:52 +03:00
BlockchainVersionFlag = cli . IntFlag {
Name : "blockchainversion" ,
Usage : "Blockchain version" ,
Value : core . BlockChainVersion ,
}
2015-04-19 00:53:30 +03:00
IdentityFlag = cli . StringFlag {
Name : "identity" ,
Usage : "node name" ,
}
2015-04-08 14:22:31 +03:00
NatspecEnabledFlag = cli . BoolFlag {
Name : "natspec" ,
Usage : "Enable NatSpec confirmation notice" ,
}
2015-03-18 09:44:58 +02:00
// miner settings
2015-03-06 04:00:41 +02:00
MinerThreadsFlag = cli . IntFlag {
Name : "minerthreads" ,
Usage : "Number of miner threads" ,
Value : runtime . NumCPU ( ) ,
}
MiningEnabledFlag = cli . BoolFlag {
Name : "mine" ,
Usage : "Enable mining" ,
}
2015-03-26 23:49:22 +02:00
EtherbaseFlag = cli . StringFlag {
2015-03-27 13:14:00 +02:00
Name : "etherbase" ,
2015-03-26 23:49:22 +02:00
Usage : "public address for block mining rewards. By default the address of your primary account is used" ,
Value : "primary" ,
}
2015-03-18 09:44:58 +02:00
UnlockedAccountFlag = cli . StringFlag {
Name : "unlock" ,
2015-03-26 23:49:22 +02:00
Usage : "unlock the account given until this program exits (prompts for password). '--unlock primary' unlocks the primary account" ,
2015-03-23 15:00:06 +02:00
Value : "" ,
}
PasswordFileFlag = cli . StringFlag {
Name : "password" ,
2015-03-24 18:05:27 +02:00
Usage : "Path to password file for (un)locking an existing account." ,
2015-03-23 15:00:06 +02:00
Value : "" ,
2015-03-18 09:44:58 +02:00
}
2015-03-06 04:00:41 +02:00
2015-03-18 09:44:58 +02:00
// logging and debug settings
2015-03-06 04:00:41 +02:00
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 ) ,
}
2015-03-21 11:20:47 +02:00
LogJSONFlag = cli . StringFlag {
Name : "logjson" ,
Usage : "Send json structured log output to a file or '-' for standard output (default: no json output)" ,
Value : "" ,
2015-03-06 04:00:41 +02:00
}
2015-03-18 09:44:58 +02:00
VMDebugFlag = cli . BoolFlag {
Name : "vmdebug" ,
Usage : "Virtual Machine debug output" ,
}
2015-03-06 04:00:41 +02:00
// 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 ,
}
2015-03-29 22:21:14 +03:00
RPCCORSDomainFlag = cli . StringFlag {
Name : "rpccorsdomain" ,
Usage : "Domain on which to send Access-Control-Allow-Origin header" ,
Value : "" ,
}
2015-03-06 04:00:41 +02:00
// 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" ,
}
2015-03-15 08:31:40 +02:00
JSpathFlag = cli . StringFlag {
Name : "jspath" ,
Usage : "JS library path to be used with console and js subcommands" ,
Value : "." ,
}
2015-04-03 18:09:01 +03:00
BacktraceAtFlag = cli . GenericFlag {
Name : "backtrace_at" ,
Usage : "When set to a file and line number holding a logging statement a stack trace will be written to the Info log" ,
Value : glog . GetTraceLocation ( ) ,
}
LogToStdErrFlag = cli . BoolFlag {
Name : "logtostderr" ,
Usage : "Logs are written to standard error instead of to files." ,
}
2015-04-07 15:57:04 +03:00
LogVModuleFlag = cli . GenericFlag {
Name : "vmodule" ,
Usage : "The syntax of the argument is a comma-separated list of pattern=N, where pattern is a literal file name (minus the \".go\" suffix) or \"glob\" pattern and N is a V level." ,
Value : glog . GetVModule ( ) ,
}
2015-03-06 04:00:41 +02:00
)
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
}
2015-03-13 19:30:45 +02:00
func MakeEthConfig ( clientID , version string , ctx * cli . Context ) * eth . Config {
2015-04-03 18:09:01 +03:00
// Set verbosity on glog
glog . SetV ( ctx . GlobalInt ( LogLevelFlag . Name ) )
// Set the log type
2015-04-08 23:18:16 +03:00
//glog.SetToStderr(ctx.GlobalBool(LogToStdErrFlag.Name))
glog . SetToStderr ( true )
2015-04-07 15:57:04 +03:00
// Set the log dir
glog . SetLogDir ( ctx . GlobalString ( LogFileFlag . Name ) )
2015-04-03 18:09:01 +03:00
2015-04-19 00:53:30 +03:00
customName := ctx . GlobalString ( IdentityFlag . Name )
if len ( customName ) > 0 {
clientID += "/" + customName
}
2015-03-13 19:30:45 +02:00
return & eth . Config {
2015-04-08 14:22:31 +03:00
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 ) ,
LogJSON : ctx . GlobalString ( LogJSONFlag . Name ) ,
Etherbase : ctx . GlobalString ( EtherbaseFlag . Name ) ,
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 ) ,
NatSpec : ctx . GlobalBool ( NatspecEnabledFlag . Name ) ,
NodeKey : GetNodeKey ( ctx ) ,
Shh : true ,
Dial : true ,
BootNodes : ctx . GlobalString ( BootnodesFlag . Name ) ,
2015-03-13 19:30:45 +02:00
}
2015-03-06 04:00:41 +02:00
}
2015-03-16 12:27:38 +02:00
func GetChain ( ctx * cli . Context ) ( * core . ChainManager , common . Database , common . Database ) {
2015-03-06 04:00:41 +02:00
dataDir := ctx . GlobalString ( DataDirFlag . Name )
2015-04-13 11:13:52 +03:00
2015-03-06 19:26:16 +02:00
blockDb , err := ethdb . NewLDBDatabase ( path . Join ( dataDir , "blockchain" ) )
2015-03-06 04:00:41 +02:00
if err != nil {
Fatalf ( "Could not open database: %v" , err )
}
2015-03-06 19:26:16 +02:00
stateDb , err := ethdb . NewLDBDatabase ( path . Join ( dataDir , "state" ) )
if err != nil {
Fatalf ( "Could not open database: %v" , err )
}
2015-04-13 11:13:52 +03:00
extraDb , err := ethdb . NewLDBDatabase ( path . Join ( dataDir , "extra" ) )
if err != nil {
Fatalf ( "Could not open database: %v" , err )
}
eventMux := new ( event . TypeMux )
chainManager := core . NewChainManager ( blockDb , stateDb , eventMux )
pow := ethash . New ( chainManager )
txPool := core . NewTxPool ( eventMux , chainManager . State )
blockProcessor := core . NewBlockProcessor ( stateDb , extraDb , pow , txPool , chainManager , eventMux )
chainManager . SetProcessor ( blockProcessor )
return chainManager , blockDb , stateDb
2015-03-06 04:00:41 +02:00
}
2015-03-07 13:39:52 +02:00
2015-03-08 02:52:49 +02:00
func GetAccountManager ( ctx * cli . Context ) * accounts . Manager {
2015-03-07 13:39:52 +02:00
dataDir := ctx . GlobalString ( DataDirFlag . Name )
2015-03-26 20:55:39 +02:00
ks := crypto . NewKeyStorePassphrase ( path . Join ( dataDir , "keys" ) )
2015-03-10 01:09:39 +02:00
return accounts . NewManager ( ks )
2015-03-07 13:39:52 +02:00
}
2015-03-10 00:00:27 +02:00
func StartRPC ( eth * eth . Ethereum , ctx * cli . Context ) {
2015-03-29 22:26:47 +03:00
config := rpc . RpcConfig {
ListenAddress : ctx . GlobalString ( RPCListenAddrFlag . Name ) ,
ListenPort : uint ( ctx . GlobalInt ( RPCPortFlag . Name ) ) ,
CorsDomain : ctx . GlobalString ( RPCCORSDomainFlag . Name ) ,
2015-03-10 00:00:27 +02:00
}
2015-03-29 22:26:47 +03:00
xeth := xeth . New ( eth , nil )
_ = rpc . Start ( xeth , config )
2015-03-10 00:00:27 +02:00
}