2015-07-07 03:54:22 +03:00
// Copyright 2014 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
2015-07-22 19:48:40 +03:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-07 03:54:22 +03:00
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
2015-07-22 19:48:40 +03:00
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
2014-10-23 16:48:53 +03:00
2015-07-07 06:08:16 +03:00
// geth is the official command-line client for Ethereum.
2014-06-23 14:20:59 +03:00
package main
import (
2014-08-06 10:53:12 +03:00
"fmt"
2015-03-24 18:19:11 +02:00
"io/ioutil"
2014-08-06 10:53:12 +03:00
"os"
2015-05-05 09:24:15 +03:00
"path/filepath"
2014-07-30 02:05:40 +03:00
"runtime"
2015-03-06 04:00:41 +02:00
"strconv"
2015-05-05 09:24:15 +03:00
"strings"
2015-06-25 13:47:06 +03:00
"time"
2014-07-30 02:05:40 +03:00
2015-03-06 04:00:41 +02:00
"github.com/codegangsta/cli"
2015-03-17 15:12:34 +02:00
"github.com/ethereum/ethash"
2015-03-23 15:00:06 +02:00
"github.com/ethereum/go-ethereum/accounts"
2014-10-31 15:20:11 +02:00
"github.com/ethereum/go-ethereum/cmd/utils"
2015-03-16 17:49:39 +02:00
"github.com/ethereum/go-ethereum/common"
2016-03-02 00:32:43 +02:00
"github.com/ethereum/go-ethereum/core"
2015-01-04 15:20:16 +02:00
"github.com/ethereum/go-ethereum/eth"
2016-03-02 00:32:43 +02:00
"github.com/ethereum/go-ethereum/ethdb"
2016-01-26 15:39:21 +02:00
"github.com/ethereum/go-ethereum/internal/debug"
2014-10-31 13:56:05 +02:00
"github.com/ethereum/go-ethereum/logger"
2015-07-01 01:52:44 +03:00
"github.com/ethereum/go-ethereum/logger/glog"
2015-06-27 18:12:58 +03:00
"github.com/ethereum/go-ethereum/metrics"
2015-11-17 18:33:25 +02:00
"github.com/ethereum/go-ethereum/node"
2015-08-06 12:20:15 +03:00
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
2014-06-23 14:20:59 +03:00
)
2014-07-03 19:36:24 +03:00
const (
2015-08-12 14:32:52 +03:00
ClientIdentifier = "Geth"
2015-11-03 13:48:04 +03:00
Version = "1.4.0-unstable"
2015-08-06 12:20:15 +03:00
VersionMajor = 1
2015-11-03 13:48:04 +03:00
VersionMinor = 4
2015-08-20 22:43:36 +03:00
VersionPatch = 0
2014-07-03 19:36:24 +03:00
)
2015-04-28 14:14:53 +03:00
var (
2015-08-05 19:41:00 +03:00
gitCommit string // set via linker flagg
2015-04-28 14:14:53 +03:00
nodeNameVersion string
app * cli . App
)
2014-06-23 14:20:59 +03:00
2015-03-06 04:00:41 +02:00
func init ( ) {
2015-04-28 14:14:53 +03:00
if gitCommit == "" {
nodeNameVersion = Version
} else {
nodeNameVersion = Version + "-" + gitCommit [ : 8 ]
}
app = utils . NewApp ( Version , "the go-ethereum command line interface" )
2015-11-17 18:33:25 +02:00
app . Action = geth
2015-03-06 04:00:41 +02:00
app . HideVersion = true // we have a command to print the version
app . Commands = [ ] cli . Command {
2015-05-27 14:43:49 +03:00
importCommand ,
exportCommand ,
upgradedbCommand ,
removedbCommand ,
dumpCommand ,
2015-06-25 10:36:47 +03:00
monitorCommand ,
2015-03-17 15:12:34 +02:00
{
Action : makedag ,
Name : "makedag" ,
Usage : "generate ethash dag (for testing)" ,
Description : `
The makedag command generates an ethash DAG in / tmp / dag .
This command exists to support the system testing project .
Regular users do not need to execute it .
2015-06-12 08:45:23 +03:00
` ,
} ,
{
Action : gpuinfo ,
Name : "gpuinfo" ,
Usage : "gpuinfo" ,
Description : `
Prints OpenCL device info for all found GPUs .
` ,
} ,
{
Action : gpubench ,
Name : "gpubench" ,
Usage : "benchmark GPU" ,
Description : `
Runs quick benchmark on first GPU found .
2015-03-17 15:12:34 +02:00
` ,
} ,
2015-03-06 04:00:41 +02:00
{
Action : version ,
Name : "version" ,
Usage : "print ethereum version numbers" ,
Description : `
The output of this command is supposed to be machine - readable .
` ,
} ,
2015-03-24 18:19:11 +02:00
{
2015-03-26 20:55:39 +02:00
Name : "wallet" ,
Usage : "ethereum presale wallet" ,
2015-03-24 18:19:11 +02:00
Subcommands : [ ] cli . Command {
{
Action : importWallet ,
Name : "import" ,
Usage : "import ethereum presale wallet" ,
} ,
} ,
2015-05-20 04:42:10 +03:00
Description : `
get wallet import / path / to / my / presale . wallet
will prompt for your password and imports your ether presale account .
It can be used non - interactively with the -- password option taking a
passwordfile as argument containing the wallet password in plaintext .
` } ,
2015-03-07 13:39:52 +02:00
{
Action : accountList ,
Name : "account" ,
Usage : "manage accounts" ,
2015-03-26 20:55:39 +02:00
Description : `
Manage accounts lets you create new accounts , list all existing accounts ,
import a private key into a new account .
2015-05-20 18:56:17 +03:00
' help ' shows a list of subcommands or help for one subcommand .
2015-04-22 02:41:34 +03:00
2015-03-26 20:55:39 +02:00
It supports interactive mode , when you are prompted for password as well as
non - interactive mode where passwords are supplied via a given password file .
Non - interactive mode is only meant for scripted use on test networks or known
safe environments .
Make sure you remember the password you gave when creating a new account ( with
either new or import ) . Without it you are not able to unlock your account .
Note that exporting your key in unencrypted format is NOT supported .
Keys are stored under < DATADIR > / keys .
It is safe to transfer the entire directory or the individual keys therein
2015-06-18 18:20:00 +03:00
between ethereum nodes by simply copying .
2015-03-26 20:55:39 +02:00
Make sure you backup your keys regularly .
2015-09-22 11:34:58 +03:00
In order to use your account to send transactions , you need to unlock them using
the ' -- unlock ' option . The argument is a space separated list of addresses or
indexes . If used non - interactively with a passwordfile , the file should contain
the respective passwords one per line . If you unlock n accounts and the password
file contains less than n entries , then the last password is meant to apply to
all remaining accounts .
2015-06-18 18:20:00 +03:00
2015-03-26 20:55:39 +02:00
And finally . DO NOT FORGET YOUR PASSWORD .
` ,
2015-03-07 13:39:52 +02:00
Subcommands : [ ] cli . Command {
{
Action : accountList ,
Name : "list" ,
Usage : "print account addresses" ,
} ,
{
Action : accountCreate ,
Name : "new" ,
Usage : "create a new account" ,
2015-03-23 15:00:06 +02:00
Description : `
ethereum account new
2015-03-26 20:55:39 +02:00
Creates a new account . Prints the address .
The account is saved in encrypted format , you are prompted for a passphrase .
You must remember this passphrase to unlock your account in the future .
2015-03-23 15:00:06 +02:00
For non - interactive use the passphrase can be specified with the -- password flag :
ethereum -- password < passwordfile > account new
2015-03-26 20:55:39 +02:00
Note , this is meant to be used for testing only , it is a bad idea to save your
password to file or expose in any other way .
2015-03-23 15:00:06 +02:00
` ,
} ,
2015-07-03 06:56:20 +03:00
{
Action : accountUpdate ,
Name : "update" ,
Usage : "update an existing account" ,
Description : `
ethereum account update < address >
Update an existing account .
The account is saved in the newest version in encrypted format , you are prompted
for a passphrase to unlock the account and another to save the updated file .
This same command can therefore be used to migrate an account of a deprecated
format to the newest format or change the password for an account .
For non - interactive use the passphrase can be specified with the -- password flag :
2015-09-22 11:34:58 +03:00
ethereum -- password < passwordfile > account update < address >
2015-07-03 06:56:20 +03:00
Since only one password can be given , only format update can be performed ,
changing your password is only possible interactively .
Note that account update has the a side effect that the order of your accounts
changes .
` ,
} ,
2015-03-23 15:00:06 +02:00
{
Action : accountImport ,
Name : "import" ,
Usage : "import a private key into a new account" ,
Description : `
ethereum account import < keyfile >
2015-03-26 20:55:39 +02:00
Imports an unencrypted private key from < keyfile > and creates a new account .
Prints the address .
2015-04-09 00:03:47 +03:00
The keyfile is assumed to contain an unencrypted private key in hexadecimal format .
2015-03-23 15:00:06 +02:00
The account is saved in encrypted format , you are prompted for a passphrase .
2015-03-26 20:55:39 +02:00
You must remember this passphrase to unlock your account in the future .
2015-03-23 15:00:06 +02:00
2015-03-26 20:55:39 +02:00
For non - interactive use the passphrase can be specified with the - password flag :
2015-03-23 15:00:06 +02:00
2015-03-26 20:55:39 +02:00
ethereum -- password < passwordfile > account import < keyfile >
2015-03-23 15:00:06 +02:00
Note :
2015-03-24 18:05:27 +02:00
As you can directly copy your encrypted accounts to another ethereum instance ,
2015-03-26 20:55:39 +02:00
this import mechanism is not needed when you transfer an account between
2015-03-24 18:05:27 +02:00
nodes .
2015-03-23 15:00:06 +02:00
` ,
2015-03-07 13:39:52 +02:00
} ,
} ,
} ,
2016-03-02 00:32:43 +02:00
{
Action : initGenesis ,
Name : "init" ,
Usage : "bootstraps and initialises a new genesis block (JSON)" ,
Description : `
The init command initialises a new genesis block and definition for the network .
This is a destructive action and changes the network in which you will be
participating .
` ,
} ,
2015-03-06 04:00:41 +02:00
{
2015-03-15 08:31:40 +02:00
Action : console ,
Name : "console" ,
2015-03-26 22:27:52 +02:00
Usage : ` Geth Console: interactive JavaScript environment ` ,
2015-03-15 08:31:40 +02:00
Description : `
2015-03-26 22:27:52 +02:00
The Geth console is an interactive shell for the JavaScript runtime environment
2015-04-22 02:41:34 +03:00
which exposes a node admin interface as well as the Ðapp JavaScript API .
See https : //github.com/ethereum/go-ethereum/wiki/Javascipt-Console
2016-03-02 00:32:43 +02:00
` ,
} ,
2015-06-18 19:23:13 +03:00
{
Action : attach ,
Name : "attach" ,
2015-06-23 10:11:57 +03:00
Usage : ` Geth Console: interactive JavaScript environment (connect to node) ` ,
2015-06-18 19:23:13 +03:00
Description : `
2015-12-16 11:58:01 +02:00
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 .
See https : //github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
This command allows to open a console on a running geth node .
` ,
2015-03-15 08:31:40 +02:00
} ,
{
2015-11-17 18:33:25 +02:00
Action : execScripts ,
2015-03-06 04:00:41 +02:00
Name : "js" ,
2015-03-26 22:27:52 +02:00
Usage : ` executes the given JavaScript files in the Geth JavaScript VM ` ,
2015-03-06 04:00:41 +02:00
Description : `
2015-04-22 02:41:34 +03:00
The JavaScript VM exposes a node admin interface as well as the Ðapp
2015-03-24 18:05:27 +02:00
JavaScript API . See https : //github.com/ethereum/go-ethereum/wiki/Javascipt-Console
2015-03-06 04:00:41 +02:00
` ,
} ,
}
app . Flags = [ ] cli . Flag {
2015-04-19 00:53:30 +03:00
utils . IdentityFlag ,
2015-03-11 02:08:42 +02:00
utils . UnlockedAccountFlag ,
2015-03-23 15:00:06 +02:00
utils . PasswordFileFlag ,
2015-07-10 15:29:40 +03:00
utils . GenesisFileFlag ,
2015-03-06 04:00:41 +02:00
utils . BootnodesFlag ,
utils . DataDirFlag ,
2016-03-08 00:38:56 +02:00
utils . KeyStoreDirFlag ,
2015-04-13 11:13:52 +03:00
utils . BlockchainVersionFlag ,
2015-08-03 18:48:24 +03:00
utils . OlympicFlag ,
2015-10-09 18:36:31 +03:00
utils . FastSyncFlag ,
2015-07-22 13:46:20 +03:00
utils . CacheFlag ,
2015-11-10 15:47:19 +02:00
utils . LightKDFFlag ,
2015-03-15 08:31:40 +02:00
utils . JSpathFlag ,
2015-03-06 04:00:41 +02:00
utils . ListenPortFlag ,
utils . MaxPeersFlag ,
2015-05-04 17:35:49 +03:00
utils . MaxPendingPeersFlag ,
2015-03-26 23:49:22 +02:00
utils . EtherbaseFlag ,
2015-05-09 13:00:51 +03:00
utils . GasPriceFlag ,
2015-03-06 04:00:41 +02:00
utils . MinerThreadsFlag ,
utils . MiningEnabledFlag ,
2015-06-12 08:45:23 +03:00
utils . MiningGPUFlag ,
2015-05-20 18:56:17 +03:00
utils . AutoDAGFlag ,
2015-03-06 04:00:41 +02:00
utils . NATFlag ,
2015-04-08 14:22:31 +03:00
utils . NatspecEnabledFlag ,
2015-05-26 19:07:24 +03:00
utils . NoDiscoverFlag ,
2015-03-06 04:00:41 +02:00
utils . NodeKeyFileFlag ,
utils . NodeKeyHexFlag ,
utils . RPCEnabledFlag ,
utils . RPCListenAddrFlag ,
utils . RPCPortFlag ,
2015-12-16 11:58:01 +02:00
utils . RPCApiFlag ,
utils . WSEnabledFlag ,
utils . WSListenAddrFlag ,
utils . WSPortFlag ,
utils . WSApiFlag ,
2016-02-09 13:24:42 +02:00
utils . WSAllowedDomainsFlag ,
2015-06-08 12:01:02 +03:00
utils . IPCDisabledFlag ,
utils . IPCApiFlag ,
utils . IPCPathFlag ,
2015-06-19 15:04:18 +03:00
utils . ExecFlag ,
2015-04-20 18:45:37 +03:00
utils . WhisperEnabledFlag ,
2015-09-06 16:46:54 +03:00
utils . DevModeFlag ,
2015-10-05 14:01:34 +03:00
utils . TestNetFlag ,
2015-07-18 00:09:36 +03:00
utils . VMForceJitFlag ,
utils . VMJitCacheFlag ,
utils . VMEnableJitFlag ,
2015-03-18 09:44:58 +02:00
utils . NetworkIdFlag ,
2015-03-29 22:21:14 +03:00
utils . RPCCORSDomainFlag ,
2015-06-29 16:11:01 +03:00
utils . MetricsEnabledFlag ,
2015-04-23 01:11:11 +03:00
utils . SolcPathFlag ,
2015-05-26 15:17:43 +03:00
utils . GpoMinGasPriceFlag ,
utils . GpoMaxGasPriceFlag ,
utils . GpoFullBlockRatioFlag ,
utils . GpobaseStepDownFlag ,
utils . GpobaseStepUpFlag ,
utils . GpobaseCorrectionFactorFlag ,
2015-09-22 11:34:58 +03:00
utils . ExtraDataFlag ,
2015-03-06 04:00:41 +02:00
}
2016-01-26 15:39:21 +02:00
app . Flags = append ( app . Flags , debug . Flags ... )
2015-04-20 18:59:41 +03:00
app . Before = func ( ctx * cli . Context ) error {
2015-12-08 18:05:43 +02:00
runtime . GOMAXPROCS ( runtime . NumCPU ( ) )
2016-01-26 15:39:21 +02:00
if err := debug . Setup ( ctx ) ; err != nil {
return err
}
// Start system runtime metrics collection
go metrics . CollectProcessMetrics ( 3 * time . Second )
2015-12-08 18:05:43 +02:00
2015-10-07 18:21:13 +03:00
utils . SetupNetwork ( ctx )
2015-04-20 18:59:41 +03:00
return nil
2015-03-06 04:00:41 +02:00
}
2016-01-26 15:39:21 +02:00
app . After = func ( ctx * cli . Context ) error {
logger . Flush ( )
debug . Exit ( )
return nil
}
2015-03-06 04:00:41 +02:00
}
2014-12-23 15:33:15 +02:00
2015-03-06 04:00:41 +02:00
func main ( ) {
if err := app . Run ( os . Args ) ; err != nil {
fmt . Fprintln ( os . Stderr , err )
os . Exit ( 1 )
}
}
2014-06-26 12:47:45 +03:00
2015-08-06 12:20:15 +03:00
func makeDefaultExtra ( ) [ ] byte {
var clientInfo = struct {
Version uint
Name string
GoVersion string
Os string
} { uint ( VersionMajor << 16 | VersionMinor << 8 | VersionPatch ) , ClientIdentifier , runtime . Version ( ) , runtime . GOOS }
extra , err := rlp . EncodeToBytes ( clientInfo )
if err != nil {
glog . V ( logger . Warn ) . Infoln ( "error setting canonical miner information:" , err )
}
if uint64 ( len ( extra ) ) > params . MaximumExtraDataSize . Uint64 ( ) {
glog . V ( logger . Warn ) . Infoln ( "error setting canonical miner information: extra exceeds" , params . MaximumExtraDataSize )
glog . V ( logger . Debug ) . Infof ( "extra: %x\n" , extra )
return nil
}
return extra
}
2015-11-17 18:33:25 +02:00
// geth is the main entry point into the system if no special subcommand is ran.
// It creates a default node based on the command line arguments and runs it in
// blocking mode, waiting for it to be shut down.
func geth ( ctx * cli . Context ) {
node := utils . MakeSystemNode ( ClientIdentifier , nodeNameVersion , makeDefaultExtra ( ) , ctx )
startNode ( ctx , node )
node . Wait ( )
2015-03-06 04:00:41 +02:00
}
2014-07-11 17:04:27 +03:00
2015-12-16 11:58:01 +02:00
// attach will connect to a running geth instance attaching a JavaScript console and to it.
2015-06-18 19:23:13 +03:00
func attach ( ctx * cli . Context ) {
2015-12-16 11:58:01 +02:00
// attach to a running geth instance
client , err := utils . NewRemoteRPCClient ( ctx )
2015-06-18 19:23:13 +03:00
if err != nil {
2016-02-05 15:08:48 +02:00
utils . Fatalf ( "Unable to attach to geth: %v" , err )
2015-06-18 19:23:13 +03:00
}
repl := newLightweightJSRE (
2015-06-23 10:38:30 +03:00
ctx . GlobalString ( utils . JSpathFlag . Name ) ,
2015-06-18 19:23:13 +03:00
client ,
2015-09-25 14:08:48 +03:00
ctx . GlobalString ( utils . DataDirFlag . Name ) ,
2015-06-18 19:23:13 +03:00
true ,
2015-08-07 10:56:49 +03:00
)
2015-06-18 19:23:13 +03:00
2015-06-19 15:04:18 +03:00
if ctx . GlobalString ( utils . ExecFlag . Name ) != "" {
repl . batch ( ctx . GlobalString ( utils . ExecFlag . Name ) )
} else {
repl . welcome ( )
repl . interactive ( )
}
2015-06-18 19:23:13 +03:00
}
2016-03-02 00:32:43 +02:00
// initGenesis will initialise the given JSON format genesis file and writes it as
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
func initGenesis ( ctx * cli . Context ) {
genesisPath := ctx . Args ( ) . First ( )
if len ( genesisPath ) == 0 {
utils . Fatalf ( "must supply path to genesis JSON file" )
}
chainDb , err := ethdb . NewLDBDatabase ( filepath . Join ( utils . MustMakeDataDir ( ctx ) , "chaindata" ) , 0 , 0 )
if err != nil {
utils . Fatalf ( "could not open database: %v" , err )
}
genesisFile , err := os . Open ( genesisPath )
if err != nil {
utils . Fatalf ( "failed to read genesis file: %v" , err )
}
block , err := core . WriteGenesisBlock ( chainDb , genesisFile )
if err != nil {
utils . Fatalf ( "failed to write genesis block: %v" , err )
}
glog . V ( logger . Info ) . Infof ( "successfully wrote genesis block and/or chain rule set: %x" , block . Hash ( ) )
}
2015-11-17 18:33:25 +02:00
// console starts a new geth node, attaching a JavaScript console to it at the
// same time.
2015-03-15 08:31:40 +02:00
func console ( ctx * cli . Context ) {
2015-11-17 18:33:25 +02:00
// Create and start the node based on the CLI flags
node := utils . MakeSystemNode ( ClientIdentifier , nodeNameVersion , makeDefaultExtra ( ) , ctx )
startNode ( ctx , node )
2015-03-10 16:44:05 +02:00
2015-11-17 18:33:25 +02:00
// Attach to the newly started node, and either execute script or become interactive
2016-02-09 14:10:40 +02:00
client , err := node . Attach ( )
2016-02-05 15:08:48 +02:00
if err != nil {
utils . Fatalf ( "Failed to attach to the inproc geth: %v" , err )
}
2015-11-17 18:33:25 +02:00
repl := newJSRE ( node ,
2015-06-23 10:38:30 +03:00
ctx . GlobalString ( utils . JSpathFlag . Name ) ,
2015-04-23 01:11:11 +03:00
ctx . GlobalString ( utils . RPCCORSDomainFlag . Name ) ,
2015-12-16 11:58:01 +02:00
client , true )
2015-06-18 19:23:13 +03:00
2015-11-17 18:33:25 +02:00
if script := ctx . GlobalString ( utils . ExecFlag . Name ) ; script != "" {
repl . batch ( script )
2015-06-19 15:04:18 +03:00
} else {
repl . welcome ( )
repl . interactive ( )
}
2015-11-17 18:33:25 +02:00
node . Stop ( )
2015-03-15 08:31:40 +02:00
}
2015-11-17 18:33:25 +02:00
// execScripts starts a new geth node based on the CLI flags, and executes each
// of the JavaScript files specified as command arguments.
func execScripts ( ctx * cli . Context ) {
// Create and start the node based on the CLI flags
node := utils . MakeSystemNode ( ClientIdentifier , nodeNameVersion , makeDefaultExtra ( ) , ctx )
startNode ( ctx , node )
2015-03-15 08:31:40 +02:00
2015-11-17 18:33:25 +02:00
// Attach to the newly started node and execute the given scripts
2016-02-09 14:10:40 +02:00
client , err := node . Attach ( )
2016-02-05 15:08:48 +02:00
if err != nil {
utils . Fatalf ( "Failed to attach to the inproc geth: %v" , err )
}
2015-11-17 18:33:25 +02:00
repl := newJSRE ( node ,
2015-06-23 10:38:30 +03:00
ctx . GlobalString ( utils . JSpathFlag . Name ) ,
2015-04-23 01:11:11 +03:00
ctx . GlobalString ( utils . RPCCORSDomainFlag . Name ) ,
2015-12-16 11:58:01 +02:00
client , false )
2015-11-17 18:33:25 +02:00
2015-03-15 08:31:40 +02:00
for _ , file := range ctx . Args ( ) {
repl . exec ( file )
}
2015-11-17 18:33:25 +02:00
node . Stop ( )
2015-03-06 04:00:41 +02:00
}
2015-01-07 02:21:55 +02:00
2015-12-01 12:20:49 +02:00
// tries unlocking the specified account a few times.
2015-11-17 18:33:25 +02:00
func unlockAccount ( ctx * cli . Context , accman * accounts . Manager , address string , i int , passwords [ ] string ) ( common . Address , string ) {
2015-12-01 12:20:49 +02:00
account , err := utils . MakeAddress ( accman , address )
if err != nil {
utils . Fatalf ( "Unlock error: %v" , err )
}
2015-07-07 13:53:36 +03:00
2015-11-17 18:33:25 +02:00
for trials := 0 ; trials < 3 ; trials ++ {
prompt := fmt . Sprintf ( "Unlocking account %s | Attempt %d/%d" , address , trials + 1 , 3 )
password := getPassPhrase ( prompt , false , i , passwords )
if err := accman . Unlock ( account , password ) ; err == nil {
return account , password
}
2015-03-11 02:08:42 +02:00
}
2015-11-17 18:33:25 +02:00
// All trials expended to unlock account, bail out
utils . Fatalf ( "Failed to unlock account: %s" , address )
return common . Address { } , ""
2015-03-23 15:00:06 +02:00
}
2015-11-17 18:33:25 +02:00
// startNode boots up the system node and all registered protocols, after which
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
func startNode ( ctx * cli . Context , stack * node . Node ) {
// Start up the node itself
utils . StartNode ( stack )
2015-07-01 17:15:02 +03:00
2015-11-17 18:33:25 +02:00
// Unlock any account specifically requested
var ethereum * eth . Ethereum
2015-11-26 18:35:44 +02:00
if err := stack . Service ( & ethereum ) ; err != nil {
2015-11-17 18:33:25 +02:00
utils . Fatalf ( "ethereum service not running: %v" , err )
2015-07-01 01:52:44 +03:00
}
2015-11-17 18:33:25 +02:00
accman := ethereum . AccountManager ( )
passwords := utils . MakePasswordList ( ctx )
2015-03-23 15:00:06 +02:00
2015-11-17 18:33:25 +02:00
accounts := strings . Split ( ctx . GlobalString ( utils . UnlockedAccountFlag . Name ) , "," )
2015-06-18 18:20:00 +03:00
for i , account := range accounts {
2015-11-17 18:33:25 +02:00
if trimmed := strings . TrimSpace ( account ) ; trimmed != "" {
unlockAccount ( ctx , accman , trimmed , i , passwords )
2015-03-24 14:37:00 +02:00
}
2015-03-23 15:00:06 +02:00
}
2016-02-02 19:06:43 +02:00
// Start auxiliary services if enabled
2015-03-06 04:00:41 +02:00
if ctx . GlobalBool ( utils . MiningEnabledFlag . Name ) {
2015-11-17 18:33:25 +02:00
if err := ethereum . StartMining ( ctx . GlobalInt ( utils . MinerThreadsFlag . Name ) , ctx . GlobalString ( utils . MiningGPUFlag . Name ) ) ; err != nil {
utils . Fatalf ( "Failed to start mining: %v" , err )
2015-04-22 03:36:28 +03:00
}
2015-03-06 04:00:41 +02:00
}
}
2015-01-05 18:10:42 +02:00
2015-03-07 13:39:52 +02:00
func accountList ( ctx * cli . Context ) {
2015-11-17 18:33:25 +02:00
accman := utils . MakeAccountManager ( ctx )
accts , err := accman . Accounts ( )
2015-03-07 13:39:52 +02:00
if err != nil {
utils . Fatalf ( "Could not list accounts: %v" , err )
}
2015-04-22 02:41:34 +03:00
for i , acct := range accts {
2015-06-21 06:01:12 +03:00
fmt . Printf ( "Account #%d: %x\n" , i , acct )
2015-03-07 13:39:52 +02:00
}
}
2015-11-17 18:33:25 +02:00
// getPassPhrase retrieves the passwor associated with an account, either fetched
// from a list of preloaded passphrases, or requested interactively from the user.
func getPassPhrase ( prompt string , confirmation bool , i int , passwords [ ] string ) string {
// If a list of passwords was supplied, retrieve from them
if len ( passwords ) > 0 {
if i < len ( passwords ) {
return passwords [ i ]
2015-03-26 20:55:39 +02:00
}
2015-11-17 18:33:25 +02:00
return passwords [ len ( passwords ) - 1 ]
}
// Otherwise prompt the user for the password
fmt . Println ( prompt )
password , err := utils . PromptPassword ( "Passphrase: " , true )
if err != nil {
utils . Fatalf ( "Failed to read passphrase: %v" , err )
}
if confirmation {
confirm , err := utils . PromptPassword ( "Repeat passphrase: " , false )
if err != nil {
utils . Fatalf ( "Failed to read passphrase confirmation: %v" , err )
2015-03-11 14:56:02 +02:00
}
2015-11-17 18:33:25 +02:00
if password != confirm {
utils . Fatalf ( "Passphrases do not match" )
2015-06-18 18:20:00 +03:00
}
2015-03-07 13:39:52 +02:00
}
2015-11-17 18:33:25 +02:00
return password
2015-03-23 15:00:06 +02:00
}
2015-11-17 18:33:25 +02:00
// accountCreate creates a new account into the keystore defined by the CLI flags.
2015-03-23 15:00:06 +02:00
func accountCreate ( ctx * cli . Context ) {
2015-11-17 18:33:25 +02:00
accman := utils . MakeAccountManager ( ctx )
password := getPassPhrase ( "Your new account is locked with a password. Please give a password. Do not forget this password." , true , 0 , utils . MakePasswordList ( ctx ) )
account , err := accman . NewAccount ( password )
2015-03-07 13:39:52 +02:00
if err != nil {
2015-11-17 18:33:25 +02:00
utils . Fatalf ( "Failed to create account: %v" , err )
2015-03-07 13:39:52 +02:00
}
2015-11-17 18:33:25 +02:00
fmt . Printf ( "Address: %x\n" , account )
2015-03-23 15:00:06 +02:00
}
2015-11-17 18:33:25 +02:00
// accountUpdate transitions an account from a previous format to the current
// one, also providing the possibility to change the pass-phrase.
2015-07-03 06:56:20 +03:00
func accountUpdate ( ctx * cli . Context ) {
2015-11-17 18:33:25 +02:00
if len ( ctx . Args ( ) ) == 0 {
utils . Fatalf ( "No accounts specified to update" )
2015-07-03 06:56:20 +03:00
}
2015-11-17 18:33:25 +02:00
accman := utils . MakeAccountManager ( ctx )
2015-07-03 06:56:20 +03:00
2015-11-17 18:33:25 +02:00
account , oldPassword := unlockAccount ( ctx , accman , ctx . Args ( ) . First ( ) , 0 , nil )
newPassword := getPassPhrase ( "Please give a new password. Do not forget this password." , true , 0 , nil )
if err := accman . Update ( account , oldPassword , newPassword ) ; err != nil {
2015-07-03 06:56:20 +03:00
utils . Fatalf ( "Could not update the account: %v" , err )
}
}
2015-03-24 18:19:11 +02:00
func importWallet ( ctx * cli . Context ) {
keyfile := ctx . Args ( ) . First ( )
if len ( keyfile ) == 0 {
utils . Fatalf ( "keyfile must be given as argument" )
}
keyJson , err := ioutil . ReadFile ( keyfile )
if err != nil {
utils . Fatalf ( "Could not read wallet file: %v" , err )
}
2015-11-17 18:33:25 +02:00
accman := utils . MakeAccountManager ( ctx )
passphrase := getPassPhrase ( "" , false , 0 , utils . MakePasswordList ( ctx ) )
2015-03-24 18:19:11 +02:00
2015-11-17 18:33:25 +02:00
acct , err := accman . ImportPreSaleKey ( keyJson , passphrase )
2015-03-24 18:19:11 +02:00
if err != nil {
utils . Fatalf ( "Could not create the account: %v" , err )
}
fmt . Printf ( "Address: %x\n" , acct )
}
2015-03-23 15:00:06 +02:00
func accountImport ( ctx * cli . Context ) {
keyfile := ctx . Args ( ) . First ( )
if len ( keyfile ) == 0 {
utils . Fatalf ( "keyfile must be given as argument" )
}
2015-11-17 18:33:25 +02:00
accman := utils . MakeAccountManager ( ctx )
passphrase := getPassPhrase ( "Your new account is locked with a password. Please give a password. Do not forget this password." , true , 0 , utils . MakePasswordList ( ctx ) )
acct , err := accman . Import ( keyfile , passphrase )
2015-03-23 15:00:06 +02:00
if err != nil {
utils . Fatalf ( "Could not create the account: %v" , err )
}
fmt . Printf ( "Address: %x\n" , acct )
}
2015-03-17 15:12:34 +02:00
func makedag ( ctx * cli . Context ) {
2015-05-05 09:24:15 +03:00
args := ctx . Args ( )
wrongArgs := func ( ) {
utils . Fatalf ( ` Usage: geth makedag <block number> <outputdir> ` )
}
switch {
case len ( args ) == 2 :
blockNum , err := strconv . ParseUint ( args [ 0 ] , 0 , 64 )
dir := args [ 1 ]
if err != nil {
wrongArgs ( )
} else {
dir = filepath . Clean ( dir )
// seems to require a trailing slash
if ! strings . HasSuffix ( dir , "/" ) {
dir = dir + "/"
}
_ , err = ioutil . ReadDir ( dir )
if err != nil {
utils . Fatalf ( "Can't find dir" )
}
fmt . Println ( "making DAG, this could take awhile..." )
ethash . MakeDAG ( blockNum , dir )
}
default :
wrongArgs ( )
}
2015-03-17 15:12:34 +02:00
}
2015-06-12 08:45:23 +03:00
func gpuinfo ( ctx * cli . Context ) {
eth . PrintOpenCLDevices ( )
}
func gpubench ( ctx * cli . Context ) {
args := ctx . Args ( )
wrongArgs := func ( ) {
utils . Fatalf ( ` Usage: geth gpubench <gpu number> ` )
}
switch {
case len ( args ) == 1 :
n , err := strconv . ParseUint ( args [ 0 ] , 0 , 64 )
if err != nil {
wrongArgs ( )
}
eth . GPUBench ( n )
case len ( args ) == 0 :
eth . GPUBench ( 0 )
default :
wrongArgs ( )
}
}
2015-03-06 04:00:41 +02:00
func version ( c * cli . Context ) {
2015-04-28 14:14:53 +03:00
fmt . Println ( ClientIdentifier )
fmt . Println ( "Version:" , Version )
if gitCommit != "" {
fmt . Println ( "Git Commit:" , gitCommit )
}
2015-06-26 16:54:27 +03:00
fmt . Println ( "Protocol Versions:" , eth . ProtocolVersions )
2015-04-28 14:14:53 +03:00
fmt . Println ( "Network Id:" , c . GlobalInt ( utils . NetworkIdFlag . Name ) )
fmt . Println ( "Go Version:" , runtime . Version ( ) )
fmt . Println ( "OS:" , runtime . GOOS )
fmt . Printf ( "GOPATH=%s\n" , os . Getenv ( "GOPATH" ) )
fmt . Printf ( "GOROOT=%s\n" , runtime . GOROOT ( ) )
2015-01-07 02:21:55 +02:00
}