main.go 18.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 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
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
Felix Lange's avatar
Felix Lange committed
16

17
// geth is the official command-line client for Ethereum.
18 19 20
package main

import (
obscuren's avatar
obscuren committed
21
	"fmt"
22
	"io"
23
	"io/ioutil"
24
	_ "net/http/pprof"
obscuren's avatar
obscuren committed
25
	"os"
26
	"path/filepath"
obscuren's avatar
obscuren committed
27
	"runtime"
28
	"strconv"
29
	"strings"
30
	"time"
obscuren's avatar
obscuren committed
31

32
	"github.com/codegangsta/cli"
33
	"github.com/ethereum/ethash"
zelig's avatar
zelig committed
34
	"github.com/ethereum/go-ethereum/accounts"
obscuren's avatar
obscuren committed
35
	"github.com/ethereum/go-ethereum/cmd/utils"
36
	"github.com/ethereum/go-ethereum/common"
37 38
	"github.com/ethereum/go-ethereum/core"
	"github.com/ethereum/go-ethereum/core/types"
obscuren's avatar
obscuren committed
39
	"github.com/ethereum/go-ethereum/eth"
40
	"github.com/ethereum/go-ethereum/ethdb"
obscuren's avatar
obscuren committed
41
	"github.com/ethereum/go-ethereum/logger"
42
	"github.com/ethereum/go-ethereum/logger/glog"
43
	"github.com/ethereum/go-ethereum/metrics"
44 45
	"github.com/ethereum/go-ethereum/rpc/codec"
	"github.com/ethereum/go-ethereum/rpc/comms"
obscuren's avatar
obscuren committed
46 47
	"github.com/mattn/go-colorable"
	"github.com/mattn/go-isatty"
48 49
)

zelig's avatar
zelig committed
50
const (
obscuren's avatar
obscuren committed
51
	ClientIdentifier = "Geth"
52
	Version          = "0.9.39"
zelig's avatar
zelig committed
53 54
)

55 56 57 58 59
var (
	gitCommit       string // set via linker flag
	nodeNameVersion string
	app             *cli.App
)
60

61
func init() {
62 63 64 65 66 67 68
	if gitCommit == "" {
		nodeNameVersion = Version
	} else {
		nodeNameVersion = Version + "-" + gitCommit[:8]
	}

	app = utils.NewApp(Version, "the go-ethereum command line interface")
69 70 71
	app.Action = run
	app.HideVersion = true // we have a command to print the version
	app.Commands = []cli.Command{
72 73 74
		{
			Action: blockRecovery,
			Name:   "recover",
75
			Usage:  "attempts to recover a corrupted database by setting a new block by number or hash. See help recover.",
76 77 78
			Description: `
The recover commands will attempt to read out the last
block based on that.
79 80 81

recover #number recovers by number
recover <hex> recovers by hash
82 83
`,
		},
84 85 86 87 88 89
		blocktestCommand,
		importCommand,
		exportCommand,
		upgradedbCommand,
		removedbCommand,
		dumpCommand,
90
		monitorCommand,
91 92 93 94 95 96 97 98 99 100 101
		{
			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.
`,
		},
102 103 104 105 106 107 108 109
		{
			Action: version,
			Name:   "version",
			Usage:  "print ethereum version numbers",
			Description: `
The output of this command is supposed to be machine-readable.
`,
		},
110 111

		{
112 113
			Name:  "wallet",
			Usage: "ethereum presale wallet",
114 115 116 117 118 119 120
			Subcommands: []cli.Command{
				{
					Action: importWallet,
					Name:   "import",
					Usage:  "import ethereum presale wallet",
				},
			},
zelig's avatar
zelig committed
121 122 123 124 125 126 127 128 129
			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.

`},
130 131 132 133
		{
			Action: accountList,
			Name:   "account",
			Usage:  "manage accounts",
134 135 136 137 138
			Description: `

Manage accounts lets you create new accounts, list all existing accounts,
import a private key into a new account.

139
'            help' shows a list of subcommands or help for one subcommand.
140

141 142 143 144 145 146 147 148 149 150 151 152
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
153
between ethereum nodes by simply copying.
154 155
Make sure you backup your keys regularly.

156 157 158
In order to use your account to send transactions, you need to unlock them using the
'--unlock' option. The argument is a comma

159 160
And finally. DO NOT FORGET YOUR PASSWORD.
`,
161 162 163 164 165 166 167 168 169 170
			Subcommands: []cli.Command{
				{
					Action: accountList,
					Name:   "list",
					Usage:  "print account addresses",
				},
				{
					Action: accountCreate,
					Name:   "new",
					Usage:  "create a new account",
zelig's avatar
zelig committed
171 172 173 174
					Description: `

    ethereum account new

175 176 177 178 179 180
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.

zelig's avatar
zelig committed
181 182 183 184
For non-interactive use the passphrase can be specified with the --password flag:

    ethereum --password <passwordfile> account new

185 186
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.
zelig's avatar
zelig committed
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 214 215
				{
					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:

    ethereum --password <passwordfile> account new

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.
					`,
				},
zelig's avatar
zelig committed
216 217 218 219 220 221 222 223
				{
					Action: accountImport,
					Name:   "import",
					Usage:  "import a private key into a new account",
					Description: `

    ethereum account import <keyfile>

224 225 226
Imports an unencrypted private key from <keyfile> and creates a new account.
Prints the address.

227
The keyfile is assumed to contain an unencrypted private key in hexadecimal format.
zelig's avatar
zelig committed
228 229 230

The account is saved in encrypted format, you are prompted for a passphrase.

231
You must remember this passphrase to unlock your account in the future.
zelig's avatar
zelig committed
232

233
For non-interactive use the passphrase can be specified with the -password flag:
zelig's avatar
zelig committed
234

235
    ethereum --password <passwordfile> account import <keyfile>
zelig's avatar
zelig committed
236 237

Note:
zelig's avatar
zelig committed
238
As you can directly copy your encrypted accounts to another ethereum instance,
239
this import mechanism is not needed when you transfer an account between
zelig's avatar
zelig committed
240
nodes.
zelig's avatar
zelig committed
241
					`,
242 243 244
				},
			},
		},
245
		{
zelig's avatar
zelig committed
246 247
			Action: console,
			Name:   "console",
obscuren's avatar
obscuren committed
248
			Usage:  `Geth Console: interactive JavaScript environment`,
zelig's avatar
zelig committed
249
			Description: `
obscuren's avatar
obscuren committed
250
The Geth console is an interactive shell for the JavaScript runtime environment
251 252
which exposes a node admin interface as well as the Ðapp JavaScript API.
See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
253 254 255 256
`},
		{
			Action: attach,
			Name:   "attach",
257
			Usage:  `Geth Console: interactive JavaScript environment (connect to node)`,
258 259 260 261 262
			Description: `
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.
zelig's avatar
zelig committed
263 264 265 266
`,
		},
		{
			Action: execJSFiles,
267
			Name:   "js",
obscuren's avatar
obscuren committed
268
			Usage:  `executes the given JavaScript files in the Geth JavaScript VM`,
269
			Description: `
270
The JavaScript VM exposes a node admin interface as well as the Ðapp
zelig's avatar
zelig committed
271
JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
272 273 274 275
`,
		},
	}
	app.Flags = []cli.Flag{
276
		utils.IdentityFlag,
277
		utils.UnlockedAccountFlag,
zelig's avatar
zelig committed
278
		utils.PasswordFileFlag,
279
		utils.GenesisNonceFlag,
280
		utils.GenesisFileFlag,
281 282
		utils.BootnodesFlag,
		utils.DataDirFlag,
283
		utils.BlockchainVersionFlag,
zelig's avatar
zelig committed
284
		utils.JSpathFlag,
285 286
		utils.ListenPortFlag,
		utils.MaxPeersFlag,
287
		utils.MaxPendingPeersFlag,
zelig's avatar
zelig committed
288
		utils.EtherbaseFlag,
289
		utils.GasPriceFlag,
290 291
		utils.MinerThreadsFlag,
		utils.MiningEnabledFlag,
292
		utils.AutoDAGFlag,
293
		utils.NATFlag,
294
		utils.NatspecEnabledFlag,
295
		utils.NoDiscoverFlag,
296 297 298 299 300
		utils.NodeKeyFileFlag,
		utils.NodeKeyHexFlag,
		utils.RPCEnabledFlag,
		utils.RPCListenAddrFlag,
		utils.RPCPortFlag,
301
		utils.RpcApiFlag,
302 303 304
		utils.IPCDisabledFlag,
		utils.IPCApiFlag,
		utils.IPCPathFlag,
305
		utils.ExecFlag,
306
		utils.WhisperEnabledFlag,
307
		utils.VMDebugFlag,
zelig's avatar
zelig committed
308
		utils.NetworkIdFlag,
309
		utils.RPCCORSDomainFlag,
310
		utils.VerbosityFlag,
obscuren's avatar
obscuren committed
311 312
		utils.BacktraceAtFlag,
		utils.LogToStdErrFlag,
obscuren's avatar
obscuren committed
313 314 315
		utils.LogVModuleFlag,
		utils.LogFileFlag,
		utils.LogJSONFlag,
316
		utils.PProfEanbledFlag,
317
		utils.PProfPortFlag,
318
		utils.MetricsEnabledFlag,
319
		utils.SolcPathFlag,
zsfelfoldi's avatar
zsfelfoldi committed
320 321 322 323 324 325
		utils.GpoMinGasPriceFlag,
		utils.GpoMaxGasPriceFlag,
		utils.GpoFullBlockRatioFlag,
		utils.GpobaseStepDownFlag,
		utils.GpobaseStepUpFlag,
		utils.GpobaseCorrectionFactorFlag,
326
	}
327
	app.Before = func(ctx *cli.Context) error {
328
		utils.SetupLogger(ctx)
329
		if ctx.GlobalBool(utils.PProfEanbledFlag.Name) {
330 331 332
			utils.StartPProf(ctx)
		}
		return nil
333
	}
334
	// Start system runtime metrics collection
335
	go metrics.CollectProcessMetrics(3 * time.Second)
336
}
obscuren's avatar
obscuren committed
337

338 339 340 341 342 343 344 345
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	defer logger.Flush()
	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
zelig's avatar
zelig committed
346

347
func run(ctx *cli.Context) {
348
	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
349
	ethereum, err := eth.New(cfg)
350
	if err != nil {
351 352 353
		utils.Fatalf("%v", err)
	}

354
	startEth(ctx, ethereum)
355
	// this blocks the thread
356
	ethereum.WaitForShutdown()
357
}
358

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
func attach(ctx *cli.Context) {
	// Wrap the standard output with a colorified stream (windows)
	if isatty.IsTerminal(os.Stdout.Fd()) {
		if pr, pw, err := os.Pipe(); err == nil {
			go io.Copy(colorable.NewColorableStdout(), pr)
			os.Stdout = pw
		}
	}

	var client comms.EthereumClient
	var err error
	if ctx.Args().Present() {
		client, err = comms.ClientFromEndpoint(ctx.Args().First(), codec.JSON)
	} else {
		cfg := comms.IpcConfig{
			Endpoint: ctx.GlobalString(utils.IPCPathFlag.Name),
		}
		client, err = comms.NewIpcClient(cfg, codec.JSON)
	}

	if err != nil {
		utils.Fatalf("Unable to attach to geth node - %v", err)
	}

	repl := newLightweightJSRE(
384
		ctx.GlobalString(utils.JSpathFlag.Name),
385 386 387 388
		client,
		true,
		nil)

389 390 391 392 393 394
	if ctx.GlobalString(utils.ExecFlag.Name) != "" {
		repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
	} else {
		repl.welcome()
		repl.interactive()
	}
395 396
}

zelig's avatar
zelig committed
397
func console(ctx *cli.Context) {
398 399 400 401 402 403 404 405
	// Wrap the standard output with a colorified stream (windows)
	if isatty.IsTerminal(os.Stdout.Fd()) {
		if pr, pw, err := os.Pipe(); err == nil {
			go io.Copy(colorable.NewColorableStdout(), pr)
			os.Stdout = pw
		}
	}

406
	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
407
	ethereum, err := eth.New(cfg)
408
	if err != nil {
409 410 411
		utils.Fatalf("%v", err)
	}

412 413
	client := comms.NewInProcClient(codec.JSON)

414
	startEth(ctx, ethereum)
415 416
	repl := newJSRE(
		ethereum,
417
		ctx.GlobalString(utils.JSpathFlag.Name),
418
		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
419
		client,
420 421 422
		true,
		nil,
	)
423

424 425 426 427 428 429
	if ctx.GlobalString(utils.ExecFlag.Name) != "" {
		repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
	} else {
		repl.welcome()
		repl.interactive()
	}
zelig's avatar
zelig committed
430 431 432 433 434 435

	ethereum.Stop()
	ethereum.WaitForShutdown()
}

func execJSFiles(ctx *cli.Context) {
436
	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
zelig's avatar
zelig committed
437 438 439
	ethereum, err := eth.New(cfg)
	if err != nil {
		utils.Fatalf("%v", err)
obscuren's avatar
obscuren committed
440
	}
zelig's avatar
zelig committed
441

442
	client := comms.NewInProcClient(codec.JSON)
zelig's avatar
zelig committed
443
	startEth(ctx, ethereum)
444 445
	repl := newJSRE(
		ethereum,
446
		ctx.GlobalString(utils.JSpathFlag.Name),
447
		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
448
		client,
449 450 451
		false,
		nil,
	)
zelig's avatar
zelig committed
452 453 454 455
	for _, file := range ctx.Args() {
		repl.exec(file)
	}

456 457
	ethereum.Stop()
	ethereum.WaitForShutdown()
458
}
obscuren's avatar
obscuren committed
459

460
func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int) (addrHex, auth string) {
461
	var err error
462 463 464 465 466 467 468 469 470 471 472
	addrHex, err = utils.ParamToAddress(addr, am)
	if err == nil {
		// Attempt to unlock the account 3 times
		attempts := 3
		for tries := 0; tries < attempts; tries++ {
			msg := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", addr, tries+1, attempts)
			auth = getPassPhrase(ctx, msg, false, i)
			err = am.Unlock(common.HexToAddress(addrHex), auth)
			if err == nil {
				break
			}
473 474
		}
	}
475

476 477
	if err != nil {
		utils.Fatalf("Unlock account failed '%v'", err)
478
	}
479 480
	fmt.Printf("Account '%s' unlocked.\n", addr)
	return
zelig's avatar
zelig committed
481 482
}

483
func blockRecovery(ctx *cli.Context) {
484 485 486
	arg := ctx.Args().First()
	if len(ctx.Args()) < 1 && len(arg) > 0 {
		glog.Fatal("recover requires block number or hash")
487 488 489
	}

	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
490
	blockDb, err := ethdb.NewLDBDatabase(filepath.Join(cfg.DataDir, "blockchain"))
491
	if err != nil {
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
		glog.Fatalln("could not open db:", err)
	}

	var block *types.Block
	if arg[0] == '#' {
		block = core.GetBlockByNumber(blockDb, common.String2Big(arg[1:]).Uint64())
	} else {
		block = core.GetBlockByHash(blockDb, common.HexToHash(arg))
	}

	if block == nil {
		glog.Fatalln("block not found. Recovery failed")
	}

	err = core.WriteHead(blockDb, block)
	if err != nil {
		glog.Fatalln("block write err", err)
509
	}
510
	glog.Infof("Recovery succesful. New HEAD %x\n", block.Hash())
511 512
}

zelig's avatar
zelig committed
513
func startEth(ctx *cli.Context, eth *eth.Ethereum) {
514
	// Start Ethereum itself
zelig's avatar
zelig committed
515 516
	utils.StartEthereum(eth)

517
	am := eth.AccountManager()
zelig's avatar
zelig committed
518
	account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
519
	accounts := strings.Split(account, " ")
520
	for i, account := range accounts {
521 522
		if len(account) > 0 {
			if account == "primary" {
523
				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.")
524
			}
525
			unlockAccount(ctx, am, account, i)
zelig's avatar
zelig committed
526
		}
zelig's avatar
zelig committed
527
	}
528
	// Start auxiliary services if enabled.
529 530 531 532 533
	if !ctx.GlobalBool(utils.IPCDisabledFlag.Name) {
		if err := utils.StartIPC(eth, ctx); err != nil {
			utils.Fatalf("Error string IPC: %v", err)
		}
	}
534
	if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
535 536 537
		if err := utils.StartRPC(eth, ctx); err != nil {
			utils.Fatalf("Error starting RPC: %v", err)
		}
538 539
	}
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
540
		if err := eth.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name)); err != nil {
541 542
			utils.Fatalf("%v", err)
		}
543 544
	}
}
obscuren's avatar
obscuren committed
545

546
func accountList(ctx *cli.Context) {
547
	am := utils.MakeAccountManager(ctx)
548 549 550 551
	accts, err := am.Accounts()
	if err != nil {
		utils.Fatalf("Could not list accounts: %v", err)
	}
552
	for i, acct := range accts {
553
		fmt.Printf("Account #%d: %x\n", i, acct)
554 555 556
	}
}

557
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int) (passphrase string) {
558 559 560
	passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
	if len(passfile) == 0 {
		fmt.Println(desc)
561
		auth, err := utils.PromptPassword("Passphrase: ", true)
562 563 564 565
		if err != nil {
			utils.Fatalf("%v", err)
		}
		if confirmation {
566
			confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
zelig's avatar
zelig committed
567 568 569
			if err != nil {
				utils.Fatalf("%v", err)
			}
570 571
			if auth != confirm {
				utils.Fatalf("Passphrases did not match.")
zelig's avatar
zelig committed
572
			}
573 574
		}
		passphrase = auth
zelig's avatar
zelig committed
575

576 577 578 579
	} else {
		passbytes, err := ioutil.ReadFile(passfile)
		if err != nil {
			utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
580
		}
581 582 583 584 585 586 587 588 589
		// this is backwards compatible if the same password unlocks several accounts
		// it also has the consequence that trailing newlines will not count as part
		// of the password, so --password <(echo -n 'pass') will now work without -n
		passphrases := strings.Split(string(passbytes), "\n")
		if i >= len(passphrases) {
			passphrase = passphrases[len(passphrases)-1]
		} else {
			passphrase = passphrases[i]
		}
590
	}
zelig's avatar
zelig committed
591 592 593 594
	return
}

func accountCreate(ctx *cli.Context) {
595
	am := utils.MakeAccountManager(ctx)
596
	passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0)
597
	acct, err := am.NewAccount(passphrase)
598 599 600
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
zelig's avatar
zelig committed
601 602 603
	fmt.Printf("Address: %x\n", acct)
}

604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
func accountUpdate(ctx *cli.Context) {
	am := utils.MakeAccountManager(ctx)
	arg := ctx.Args().First()
	if len(arg) == 0 {
		utils.Fatalf("account address or index must be given as argument")
	}

	addr, authFrom := unlockAccount(ctx, am, arg, 0)
	authTo := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0)
	err := am.Update(common.HexToAddress(addr), authFrom, authTo)
	if err != nil {
		utils.Fatalf("Could not update the account: %v", err)
	}
}

619 620 621 622 623 624 625 626 627 628
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)
	}

629
	am := utils.MakeAccountManager(ctx)
630
	passphrase := getPassPhrase(ctx, "", false, 0)
631 632 633 634 635 636 637 638

	acct, err := am.ImportPreSaleKey(keyJson, passphrase)
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
	fmt.Printf("Address: %x\n", acct)
}

zelig's avatar
zelig committed
639 640 641 642 643
func accountImport(ctx *cli.Context) {
	keyfile := ctx.Args().First()
	if len(keyfile) == 0 {
		utils.Fatalf("keyfile must be given as argument")
	}
644
	am := utils.MakeAccountManager(ctx)
645
	passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0)
zelig's avatar
zelig committed
646 647 648 649 650 651 652
	acct, err := am.Import(keyfile, passphrase)
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
	fmt.Printf("Address: %x\n", acct)
}

653
func makedag(ctx *cli.Context) {
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
	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()
	}
680 681
}

682
func version(c *cli.Context) {
683 684 685 686 687
	fmt.Println(ClientIdentifier)
	fmt.Println("Version:", Version)
	if gitCommit != "" {
		fmt.Println("Git Commit:", gitCommit)
	}
688
	fmt.Println("Protocol Versions:", eth.ProtocolVersions)
689 690 691 692 693
	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())
obscuren's avatar
obscuren committed
694
}