github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/cmd/geth/main.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // geth is the official command-line client for Ethereum.
    18  package main
    19  
    20  import (
    21  	"fmt"
    22  	"io/ioutil"
    23  	_ "net/http/pprof"
    24  	"os"
    25  	"path/filepath"
    26  	"runtime"
    27  	"strconv"
    28  	"strings"
    29  	"time"
    30  
    31  	"github.com/codegangsta/cli"
    32  	"github.com/ethereum/ethash"
    33  	"github.com/ethereum/go-ethereum/accounts"
    34  	"github.com/ethereum/go-ethereum/cmd/utils"
    35  	"github.com/ethereum/go-ethereum/common"
    36  	"github.com/ethereum/go-ethereum/core"
    37  	"github.com/ethereum/go-ethereum/core/types"
    38  	"github.com/ethereum/go-ethereum/eth"
    39  	"github.com/ethereum/go-ethereum/ethdb"
    40  	"github.com/ethereum/go-ethereum/logger"
    41  	"github.com/ethereum/go-ethereum/logger/glog"
    42  	"github.com/ethereum/go-ethereum/metrics"
    43  	"github.com/ethereum/go-ethereum/params"
    44  	"github.com/ethereum/go-ethereum/rlp"
    45  	"github.com/ethereum/go-ethereum/rpc/codec"
    46  	"github.com/ethereum/go-ethereum/rpc/comms"
    47  )
    48  
    49  const (
    50  	ClientIdentifier = "Geth"
    51  	Version          = "1.1.3"
    52  	VersionMajor     = 1
    53  	VersionMinor     = 1
    54  	VersionPatch     = 3
    55  )
    56  
    57  var (
    58  	gitCommit       string // set via linker flagg
    59  	nodeNameVersion string
    60  	app             *cli.App
    61  )
    62  
    63  func init() {
    64  	if gitCommit == "" {
    65  		nodeNameVersion = Version
    66  	} else {
    67  		nodeNameVersion = Version + "-" + gitCommit[:8]
    68  	}
    69  
    70  	app = utils.NewApp(Version, "the go-ethereum command line interface")
    71  	app.Action = run
    72  	app.HideVersion = true // we have a command to print the version
    73  	app.Commands = []cli.Command{
    74  		{
    75  			Action: blockRecovery,
    76  			Name:   "recover",
    77  			Usage:  "attempts to recover a corrupted database by setting a new block by number or hash. See help recover.",
    78  			Description: `
    79  The recover commands will attempt to read out the last
    80  block based on that.
    81  
    82  recover #number recovers by number
    83  recover <hex> recovers by hash
    84  `,
    85  		},
    86  		blocktestCommand,
    87  		importCommand,
    88  		exportCommand,
    89  		upgradedbCommand,
    90  		removedbCommand,
    91  		dumpCommand,
    92  		monitorCommand,
    93  		{
    94  			Action: makedag,
    95  			Name:   "makedag",
    96  			Usage:  "generate ethash dag (for testing)",
    97  			Description: `
    98  The makedag command generates an ethash DAG in /tmp/dag.
    99  
   100  This command exists to support the system testing project.
   101  Regular users do not need to execute it.
   102  `,
   103  		},
   104  		{
   105  			Action: version,
   106  			Name:   "version",
   107  			Usage:  "print ethereum version numbers",
   108  			Description: `
   109  The output of this command is supposed to be machine-readable.
   110  `,
   111  		},
   112  
   113  		{
   114  			Name:  "wallet",
   115  			Usage: "ethereum presale wallet",
   116  			Subcommands: []cli.Command{
   117  				{
   118  					Action: importWallet,
   119  					Name:   "import",
   120  					Usage:  "import ethereum presale wallet",
   121  				},
   122  			},
   123  			Description: `
   124  
   125      get wallet import /path/to/my/presale.wallet
   126  
   127  will prompt for your password and imports your ether presale account.
   128  It can be used non-interactively with the --password option taking a
   129  passwordfile as argument containing the wallet password in plaintext.
   130  
   131  `},
   132  		{
   133  			Action: accountList,
   134  			Name:   "account",
   135  			Usage:  "manage accounts",
   136  			Description: `
   137  
   138  Manage accounts lets you create new accounts, list all existing accounts,
   139  import a private key into a new account.
   140  
   141  '            help' shows a list of subcommands or help for one subcommand.
   142  
   143  It supports interactive mode, when you are prompted for password as well as
   144  non-interactive mode where passwords are supplied via a given password file.
   145  Non-interactive mode is only meant for scripted use on test networks or known
   146  safe environments.
   147  
   148  Make sure you remember the password you gave when creating a new account (with
   149  either new or import). Without it you are not able to unlock your account.
   150  
   151  Note that exporting your key in unencrypted format is NOT supported.
   152  
   153  Keys are stored under <DATADIR>/keys.
   154  It is safe to transfer the entire directory or the individual keys therein
   155  between ethereum nodes by simply copying.
   156  Make sure you backup your keys regularly.
   157  
   158  In order to use your account to send transactions, you need to unlock them using the
   159  '--unlock' option. The argument is a comma
   160  
   161  And finally. DO NOT FORGET YOUR PASSWORD.
   162  `,
   163  			Subcommands: []cli.Command{
   164  				{
   165  					Action: accountList,
   166  					Name:   "list",
   167  					Usage:  "print account addresses",
   168  				},
   169  				{
   170  					Action: accountCreate,
   171  					Name:   "new",
   172  					Usage:  "create a new account",
   173  					Description: `
   174  
   175      ethereum account new
   176  
   177  Creates a new account. Prints the address.
   178  
   179  The account is saved in encrypted format, you are prompted for a passphrase.
   180  
   181  You must remember this passphrase to unlock your account in the future.
   182  
   183  For non-interactive use the passphrase can be specified with the --password flag:
   184  
   185      ethereum --password <passwordfile> account new
   186  
   187  Note, this is meant to be used for testing only, it is a bad idea to save your
   188  password to file or expose in any other way.
   189  					`,
   190  				},
   191  				{
   192  					Action: accountUpdate,
   193  					Name:   "update",
   194  					Usage:  "update an existing account",
   195  					Description: `
   196  
   197      ethereum account update <address>
   198  
   199  Update an existing account.
   200  
   201  The account is saved in the newest version in encrypted format, you are prompted
   202  for a passphrase to unlock the account and another to save the updated file.
   203  
   204  This same command can therefore be used to migrate an account of a deprecated
   205  format to the newest format or change the password for an account.
   206  
   207  For non-interactive use the passphrase can be specified with the --password flag:
   208  
   209      ethereum --password <passwordfile> account new
   210  
   211  Since only one password can be given, only format update can be performed,
   212  changing your password is only possible interactively.
   213  
   214  Note that account update has the a side effect that the order of your accounts
   215  changes.
   216  					`,
   217  				},
   218  				{
   219  					Action: accountImport,
   220  					Name:   "import",
   221  					Usage:  "import a private key into a new account",
   222  					Description: `
   223  
   224      ethereum account import <keyfile>
   225  
   226  Imports an unencrypted private key from <keyfile> and creates a new account.
   227  Prints the address.
   228  
   229  The keyfile is assumed to contain an unencrypted private key in hexadecimal format.
   230  
   231  The account is saved in encrypted format, you are prompted for a passphrase.
   232  
   233  You must remember this passphrase to unlock your account in the future.
   234  
   235  For non-interactive use the passphrase can be specified with the -password flag:
   236  
   237      ethereum --password <passwordfile> account import <keyfile>
   238  
   239  Note:
   240  As you can directly copy your encrypted accounts to another ethereum instance,
   241  this import mechanism is not needed when you transfer an account between
   242  nodes.
   243  					`,
   244  				},
   245  			},
   246  		},
   247  		{
   248  			Action: console,
   249  			Name:   "console",
   250  			Usage:  `Geth Console: interactive JavaScript environment`,
   251  			Description: `
   252  The Geth console is an interactive shell for the JavaScript runtime environment
   253  which exposes a node admin interface as well as the Ðapp JavaScript API.
   254  See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
   255  `},
   256  		{
   257  			Action: attach,
   258  			Name:   "attach",
   259  			Usage:  `Geth Console: interactive JavaScript environment (connect to node)`,
   260  			Description: `
   261  The Geth console is an interactive shell for the JavaScript runtime environment
   262  which exposes a node admin interface as well as the Ðapp JavaScript API.
   263  See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
   264  This command allows to open a console on a running geth node.
   265  `,
   266  		},
   267  		{
   268  			Action: execJSFiles,
   269  			Name:   "js",
   270  			Usage:  `executes the given JavaScript files in the Geth JavaScript VM`,
   271  			Description: `
   272  The JavaScript VM exposes a node admin interface as well as the Ðapp
   273  JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
   274  `,
   275  		},
   276  	}
   277  	app.Flags = []cli.Flag{
   278  		utils.IdentityFlag,
   279  		utils.UnlockedAccountFlag,
   280  		utils.PasswordFileFlag,
   281  		utils.GenesisFileFlag,
   282  		utils.BootnodesFlag,
   283  		utils.DataDirFlag,
   284  		utils.BlockchainVersionFlag,
   285  		utils.OlympicFlag,
   286  		utils.CacheFlag,
   287  		utils.JSpathFlag,
   288  		utils.ListenPortFlag,
   289  		utils.MaxPeersFlag,
   290  		utils.MaxPendingPeersFlag,
   291  		utils.EtherbaseFlag,
   292  		utils.GasPriceFlag,
   293  		utils.MinerThreadsFlag,
   294  		utils.MiningEnabledFlag,
   295  		utils.AutoDAGFlag,
   296  		utils.NATFlag,
   297  		utils.NatspecEnabledFlag,
   298  		utils.NoDiscoverFlag,
   299  		utils.NodeKeyFileFlag,
   300  		utils.NodeKeyHexFlag,
   301  		utils.RPCEnabledFlag,
   302  		utils.RPCListenAddrFlag,
   303  		utils.RPCPortFlag,
   304  		utils.RpcApiFlag,
   305  		utils.IPCDisabledFlag,
   306  		utils.IPCApiFlag,
   307  		utils.IPCPathFlag,
   308  		utils.ExecFlag,
   309  		utils.WhisperEnabledFlag,
   310  		utils.VMDebugFlag,
   311  		utils.VMForceJitFlag,
   312  		utils.VMJitCacheFlag,
   313  		utils.VMEnableJitFlag,
   314  		utils.NetworkIdFlag,
   315  		utils.RPCCORSDomainFlag,
   316  		utils.VerbosityFlag,
   317  		utils.BacktraceAtFlag,
   318  		utils.LogToStdErrFlag,
   319  		utils.LogVModuleFlag,
   320  		utils.LogFileFlag,
   321  		utils.LogJSONFlag,
   322  		utils.PProfEanbledFlag,
   323  		utils.PProfPortFlag,
   324  		utils.MetricsEnabledFlag,
   325  		utils.SolcPathFlag,
   326  		utils.GpoMinGasPriceFlag,
   327  		utils.GpoMaxGasPriceFlag,
   328  		utils.GpoFullBlockRatioFlag,
   329  		utils.GpobaseStepDownFlag,
   330  		utils.GpobaseStepUpFlag,
   331  		utils.GpobaseCorrectionFactorFlag,
   332  	}
   333  	app.Before = func(ctx *cli.Context) error {
   334  		utils.SetupLogger(ctx)
   335  		utils.SetupVM(ctx)
   336  		if ctx.GlobalBool(utils.PProfEanbledFlag.Name) {
   337  			utils.StartPProf(ctx)
   338  		}
   339  		return nil
   340  	}
   341  	// Start system runtime metrics collection
   342  	go metrics.CollectProcessMetrics(3 * time.Second)
   343  }
   344  
   345  func main() {
   346  	runtime.GOMAXPROCS(runtime.NumCPU())
   347  	defer logger.Flush()
   348  	if err := app.Run(os.Args); err != nil {
   349  		fmt.Fprintln(os.Stderr, err)
   350  		os.Exit(1)
   351  	}
   352  }
   353  
   354  func makeDefaultExtra() []byte {
   355  	var clientInfo = struct {
   356  		Version   uint
   357  		Name      string
   358  		GoVersion string
   359  		Os        string
   360  	}{uint(VersionMajor<<16 | VersionMinor<<8 | VersionPatch), ClientIdentifier, runtime.Version(), runtime.GOOS}
   361  	extra, err := rlp.EncodeToBytes(clientInfo)
   362  	if err != nil {
   363  		glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
   364  	}
   365  
   366  	if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
   367  		glog.V(logger.Warn).Infoln("error setting canonical miner information: extra exceeds", params.MaximumExtraDataSize)
   368  		glog.V(logger.Debug).Infof("extra: %x\n", extra)
   369  		return nil
   370  	}
   371  
   372  	return extra
   373  }
   374  
   375  func run(ctx *cli.Context) {
   376  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   377  	if ctx.GlobalBool(utils.OlympicFlag.Name) {
   378  		utils.InitOlympic()
   379  	}
   380  
   381  	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
   382  	cfg.ExtraData = makeDefaultExtra()
   383  
   384  	ethereum, err := eth.New(cfg)
   385  	if err != nil {
   386  		utils.Fatalf("%v", err)
   387  	}
   388  
   389  	startEth(ctx, ethereum)
   390  	// this blocks the thread
   391  	ethereum.WaitForShutdown()
   392  }
   393  
   394  func attach(ctx *cli.Context) {
   395  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   396  
   397  	var client comms.EthereumClient
   398  	var err error
   399  	if ctx.Args().Present() {
   400  		client, err = comms.ClientFromEndpoint(ctx.Args().First(), codec.JSON)
   401  	} else {
   402  		cfg := comms.IpcConfig{
   403  			Endpoint: ctx.GlobalString(utils.IPCPathFlag.Name),
   404  		}
   405  		client, err = comms.NewIpcClient(cfg, codec.JSON)
   406  	}
   407  
   408  	if err != nil {
   409  		utils.Fatalf("Unable to attach to geth node - %v", err)
   410  	}
   411  
   412  	repl := newLightweightJSRE(
   413  		ctx.GlobalString(utils.JSpathFlag.Name),
   414  		client,
   415  		true,
   416  	)
   417  
   418  	if ctx.GlobalString(utils.ExecFlag.Name) != "" {
   419  		repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
   420  	} else {
   421  		repl.welcome()
   422  		repl.interactive()
   423  	}
   424  }
   425  
   426  func console(ctx *cli.Context) {
   427  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   428  
   429  	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
   430  	ethereum, err := eth.New(cfg)
   431  	if err != nil {
   432  		utils.Fatalf("%v", err)
   433  	}
   434  
   435  	client := comms.NewInProcClient(codec.JSON)
   436  
   437  	startEth(ctx, ethereum)
   438  	repl := newJSRE(
   439  		ethereum,
   440  		ctx.GlobalString(utils.JSpathFlag.Name),
   441  		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
   442  		client,
   443  		true,
   444  		nil,
   445  	)
   446  
   447  	if ctx.GlobalString(utils.ExecFlag.Name) != "" {
   448  		repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
   449  	} else {
   450  		repl.welcome()
   451  		repl.interactive()
   452  	}
   453  
   454  	ethereum.Stop()
   455  	ethereum.WaitForShutdown()
   456  }
   457  
   458  func execJSFiles(ctx *cli.Context) {
   459  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   460  
   461  	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
   462  	ethereum, err := eth.New(cfg)
   463  	if err != nil {
   464  		utils.Fatalf("%v", err)
   465  	}
   466  
   467  	client := comms.NewInProcClient(codec.JSON)
   468  	startEth(ctx, ethereum)
   469  	repl := newJSRE(
   470  		ethereum,
   471  		ctx.GlobalString(utils.JSpathFlag.Name),
   472  		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
   473  		client,
   474  		false,
   475  		nil,
   476  	)
   477  	for _, file := range ctx.Args() {
   478  		repl.exec(file)
   479  	}
   480  
   481  	ethereum.Stop()
   482  	ethereum.WaitForShutdown()
   483  }
   484  
   485  func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int) (addrHex, auth string) {
   486  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   487  
   488  	var err error
   489  	addrHex, err = utils.ParamToAddress(addr, am)
   490  	if err == nil {
   491  		// Attempt to unlock the account 3 times
   492  		attempts := 3
   493  		for tries := 0; tries < attempts; tries++ {
   494  			msg := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", addr, tries+1, attempts)
   495  			auth = getPassPhrase(ctx, msg, false, i)
   496  			err = am.Unlock(common.HexToAddress(addrHex), auth)
   497  			if err == nil {
   498  				break
   499  			}
   500  		}
   501  	}
   502  
   503  	if err != nil {
   504  		utils.Fatalf("Unlock account failed '%v'", err)
   505  	}
   506  	fmt.Printf("Account '%s' unlocked.\n", addr)
   507  	return
   508  }
   509  
   510  func blockRecovery(ctx *cli.Context) {
   511  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   512  
   513  	arg := ctx.Args().First()
   514  	if len(ctx.Args()) < 1 && len(arg) > 0 {
   515  		glog.Fatal("recover requires block number or hash")
   516  	}
   517  
   518  	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
   519  	utils.CheckLegalese(cfg.DataDir)
   520  
   521  	blockDb, err := ethdb.NewLDBDatabase(filepath.Join(cfg.DataDir, "blockchain"), cfg.DatabaseCache)
   522  	if err != nil {
   523  		glog.Fatalln("could not open db:", err)
   524  	}
   525  
   526  	var block *types.Block
   527  	if arg[0] == '#' {
   528  		block = core.GetBlockByNumber(blockDb, common.String2Big(arg[1:]).Uint64())
   529  	} else {
   530  		block = core.GetBlockByHash(blockDb, common.HexToHash(arg))
   531  	}
   532  
   533  	if block == nil {
   534  		glog.Fatalln("block not found. Recovery failed")
   535  	}
   536  
   537  	err = core.WriteHead(blockDb, block)
   538  	if err != nil {
   539  		glog.Fatalln("block write err", err)
   540  	}
   541  	glog.Infof("Recovery succesful. New HEAD %x\n", block.Hash())
   542  }
   543  
   544  func startEth(ctx *cli.Context, eth *eth.Ethereum) {
   545  	// Start Ethereum itself
   546  	utils.StartEthereum(eth)
   547  
   548  	am := eth.AccountManager()
   549  	account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
   550  	accounts := strings.Split(account, " ")
   551  	for i, account := range accounts {
   552  		if len(account) > 0 {
   553  			if account == "primary" {
   554  				utils.Fatalf("the 'primary' keyword is deprecated. You can use integer indexes, but the indexes are not permanent, they can change if you add external keys, export your keys or copy your keystore to another node.")
   555  			}
   556  			unlockAccount(ctx, am, account, i)
   557  		}
   558  	}
   559  	// Start auxiliary services if enabled.
   560  	if !ctx.GlobalBool(utils.IPCDisabledFlag.Name) {
   561  		if err := utils.StartIPC(eth, ctx); err != nil {
   562  			utils.Fatalf("Error string IPC: %v", err)
   563  		}
   564  	}
   565  	if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
   566  		if err := utils.StartRPC(eth, ctx); err != nil {
   567  			utils.Fatalf("Error starting RPC: %v", err)
   568  		}
   569  	}
   570  	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
   571  		if err := eth.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name)); err != nil {
   572  			utils.Fatalf("%v", err)
   573  		}
   574  	}
   575  }
   576  
   577  func accountList(ctx *cli.Context) {
   578  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   579  
   580  	am := utils.MakeAccountManager(ctx)
   581  	accts, err := am.Accounts()
   582  	if err != nil {
   583  		utils.Fatalf("Could not list accounts: %v", err)
   584  	}
   585  	for i, acct := range accts {
   586  		fmt.Printf("Account #%d: %x\n", i, acct)
   587  	}
   588  }
   589  
   590  func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int) (passphrase string) {
   591  	passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
   592  	if len(passfile) == 0 {
   593  		fmt.Println(desc)
   594  		auth, err := utils.PromptPassword("Passphrase: ", true)
   595  		if err != nil {
   596  			utils.Fatalf("%v", err)
   597  		}
   598  		if confirmation {
   599  			confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
   600  			if err != nil {
   601  				utils.Fatalf("%v", err)
   602  			}
   603  			if auth != confirm {
   604  				utils.Fatalf("Passphrases did not match.")
   605  			}
   606  		}
   607  		passphrase = auth
   608  
   609  	} else {
   610  		passbytes, err := ioutil.ReadFile(passfile)
   611  		if err != nil {
   612  			utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
   613  		}
   614  		// this is backwards compatible if the same password unlocks several accounts
   615  		// it also has the consequence that trailing newlines will not count as part
   616  		// of the password, so --password <(echo -n 'pass') will now work without -n
   617  		passphrases := strings.Split(string(passbytes), "\n")
   618  		if i >= len(passphrases) {
   619  			passphrase = passphrases[len(passphrases)-1]
   620  		} else {
   621  			passphrase = passphrases[i]
   622  		}
   623  	}
   624  	return
   625  }
   626  
   627  func accountCreate(ctx *cli.Context) {
   628  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   629  
   630  	am := utils.MakeAccountManager(ctx)
   631  	passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0)
   632  	acct, err := am.NewAccount(passphrase)
   633  	if err != nil {
   634  		utils.Fatalf("Could not create the account: %v", err)
   635  	}
   636  	fmt.Printf("Address: %x\n", acct)
   637  }
   638  
   639  func accountUpdate(ctx *cli.Context) {
   640  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   641  
   642  	am := utils.MakeAccountManager(ctx)
   643  	arg := ctx.Args().First()
   644  	if len(arg) == 0 {
   645  		utils.Fatalf("account address or index must be given as argument")
   646  	}
   647  
   648  	addr, authFrom := unlockAccount(ctx, am, arg, 0)
   649  	authTo := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0)
   650  	err := am.Update(common.HexToAddress(addr), authFrom, authTo)
   651  	if err != nil {
   652  		utils.Fatalf("Could not update the account: %v", err)
   653  	}
   654  }
   655  
   656  func importWallet(ctx *cli.Context) {
   657  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   658  
   659  	keyfile := ctx.Args().First()
   660  	if len(keyfile) == 0 {
   661  		utils.Fatalf("keyfile must be given as argument")
   662  	}
   663  	keyJson, err := ioutil.ReadFile(keyfile)
   664  	if err != nil {
   665  		utils.Fatalf("Could not read wallet file: %v", err)
   666  	}
   667  
   668  	am := utils.MakeAccountManager(ctx)
   669  	passphrase := getPassPhrase(ctx, "", false, 0)
   670  
   671  	acct, err := am.ImportPreSaleKey(keyJson, passphrase)
   672  	if err != nil {
   673  		utils.Fatalf("Could not create the account: %v", err)
   674  	}
   675  	fmt.Printf("Address: %x\n", acct)
   676  }
   677  
   678  func accountImport(ctx *cli.Context) {
   679  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   680  
   681  	keyfile := ctx.Args().First()
   682  	if len(keyfile) == 0 {
   683  		utils.Fatalf("keyfile must be given as argument")
   684  	}
   685  	am := utils.MakeAccountManager(ctx)
   686  	passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0)
   687  	acct, err := am.Import(keyfile, passphrase)
   688  	if err != nil {
   689  		utils.Fatalf("Could not create the account: %v", err)
   690  	}
   691  	fmt.Printf("Address: %x\n", acct)
   692  }
   693  
   694  func makedag(ctx *cli.Context) {
   695  	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
   696  
   697  	args := ctx.Args()
   698  	wrongArgs := func() {
   699  		utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
   700  	}
   701  	switch {
   702  	case len(args) == 2:
   703  		blockNum, err := strconv.ParseUint(args[0], 0, 64)
   704  		dir := args[1]
   705  		if err != nil {
   706  			wrongArgs()
   707  		} else {
   708  			dir = filepath.Clean(dir)
   709  			// seems to require a trailing slash
   710  			if !strings.HasSuffix(dir, "/") {
   711  				dir = dir + "/"
   712  			}
   713  			_, err = ioutil.ReadDir(dir)
   714  			if err != nil {
   715  				utils.Fatalf("Can't find dir")
   716  			}
   717  			fmt.Println("making DAG, this could take awhile...")
   718  			ethash.MakeDAG(blockNum, dir)
   719  		}
   720  	default:
   721  		wrongArgs()
   722  	}
   723  }
   724  
   725  func version(c *cli.Context) {
   726  	fmt.Println(ClientIdentifier)
   727  	fmt.Println("Version:", Version)
   728  	if gitCommit != "" {
   729  		fmt.Println("Git Commit:", gitCommit)
   730  	}
   731  	fmt.Println("Protocol Versions:", eth.ProtocolVersions)
   732  	fmt.Println("Network Id:", c.GlobalInt(utils.NetworkIdFlag.Name))
   733  	fmt.Println("Go Version:", runtime.Version())
   734  	fmt.Println("OS:", runtime.GOOS)
   735  	fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
   736  	fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
   737  }