2015-01-06 13:13:57 +02:00
|
|
|
/*
|
|
|
|
This file is part of go-ethereum
|
2014-10-23 16:48:53 +03:00
|
|
|
|
2015-01-06 13:13:57 +02:00
|
|
|
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/>.
|
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* @authors
|
|
|
|
* Jeffrey Wilcke <i@jev.io>
|
|
|
|
*/
|
2014-06-23 14:20:59 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2015-03-07 13:39:52 +02:00
|
|
|
"bufio"
|
2014-08-06 10:53:12 +03:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2014-07-30 02:05:40 +03:00
|
|
|
"runtime"
|
2015-03-06 04:00:41 +02:00
|
|
|
"strconv"
|
2014-12-23 19:35:36 +02: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"
|
2015-03-25 12:54:11 +02:00
|
|
|
"github.com/ethereum/go-ethereum/core/state"
|
2014-12-04 11:53:49 +02:00
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
2015-01-04 15:20:16 +02:00
|
|
|
"github.com/ethereum/go-ethereum/eth"
|
2014-10-31 13:56:05 +02:00
|
|
|
"github.com/ethereum/go-ethereum/logger"
|
2015-03-07 13:39:52 +02:00
|
|
|
"github.com/peterh/liner"
|
2014-06-23 14:20:59 +03:00
|
|
|
)
|
|
|
|
|
2014-07-03 19:36:24 +03:00
|
|
|
const (
|
|
|
|
ClientIdentifier = "Ethereum(G)"
|
2015-03-26 18:55:30 +02:00
|
|
|
Version = "0.9.4"
|
2014-07-03 19:36:24 +03:00
|
|
|
)
|
|
|
|
|
2015-03-06 04:00:41 +02:00
|
|
|
var (
|
|
|
|
clilogger = logger.NewLogger("CLI")
|
2015-03-09 23:51:50 +02:00
|
|
|
app = utils.NewApp(Version, "the go-ethereum command line interface")
|
2015-03-06 04:00:41 +02:00
|
|
|
)
|
2014-06-23 14:20:59 +03:00
|
|
|
|
2015-03-06 04:00:41 +02:00
|
|
|
func init() {
|
|
|
|
app.Action = run
|
|
|
|
app.HideVersion = true // we have a command to print the version
|
|
|
|
app.Commands = []cli.Command{
|
2015-03-13 19:37:13 +02:00
|
|
|
blocktestCmd,
|
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-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-07 13:39:52 +02:00
|
|
|
{
|
|
|
|
Action: accountList,
|
|
|
|
Name: "account",
|
|
|
|
Usage: "manage accounts",
|
|
|
|
Subcommands: []cli.Command{
|
|
|
|
{
|
|
|
|
Action: accountList,
|
|
|
|
Name: "list",
|
|
|
|
Usage: "print account addresses",
|
2015-03-23 15:00:06 +02:00
|
|
|
Description: `
|
|
|
|
|
|
|
|
`,
|
2015-03-07 13:39:52 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Action: accountCreate,
|
|
|
|
Name: "new",
|
|
|
|
Usage: "create a new account",
|
2015-03-23 15:00:06 +02:00
|
|
|
Description: `
|
|
|
|
|
|
|
|
ethereum account new
|
|
|
|
|
|
|
|
Creates a new accountThe account is saved in encrypted format, you are prompted for a passphrase.
|
|
|
|
You must remember this passphrase to unlock your account in future.
|
|
|
|
For non-interactive use the passphrase can be specified with the --password flag:
|
|
|
|
|
|
|
|
ethereum --password <passwordfile> account new
|
|
|
|
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Action: accountImport,
|
|
|
|
Name: "import",
|
|
|
|
Usage: "import a private key into a new account",
|
|
|
|
Description: `
|
|
|
|
|
|
|
|
ethereum account import <keyfile>
|
|
|
|
|
|
|
|
Imports a private key from <keyfile> and creates a new account with the address derived from the key.
|
|
|
|
The keyfile is assumed to contain an unencrypted private key in canonical EC format.
|
|
|
|
|
|
|
|
The account is saved in encrypted format, you are prompted for a passphrase.
|
|
|
|
You must remember this passphrase to unlock your account in future.
|
|
|
|
For non-interactive use the passphrase can be specified with the --password flag:
|
|
|
|
|
|
|
|
ethereum --password <passwordfile> account import <keyfile>
|
|
|
|
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Action: accountExport,
|
|
|
|
Name: "export",
|
|
|
|
Usage: "export an account into key file",
|
|
|
|
Description: `
|
|
|
|
|
|
|
|
ethereum account export <address> <keyfile>
|
|
|
|
|
|
|
|
Exports the given account's private key into keyfile using the canonical EC format.
|
|
|
|
The account needs to be unlocked, if it is not the user is prompted for a passphrase to unlock it.
|
|
|
|
For non-interactive use, the password can be specified with the --unlock flag:
|
|
|
|
|
2015-03-24 14:37:00 +02:00
|
|
|
ethereum --password <passwrdfile> account export <address> <keyfile>
|
2015-03-23 15:00:06 +02:00
|
|
|
|
|
|
|
Note:
|
|
|
|
Since you can directly copy your encrypted accounts to another ethereum instance, this import/export mechanism is not needed when you transfer an account between nodes.
|
|
|
|
`,
|
2015-03-07 13:39:52 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-03-06 04:00:41 +02:00
|
|
|
{
|
|
|
|
Action: dump,
|
|
|
|
Name: "dump",
|
|
|
|
Usage: `dump a specific block from storage`,
|
|
|
|
Description: `
|
|
|
|
The arguments are interpreted as block numbers or hashes.
|
|
|
|
Use "ethereum dump 0" to dump the genesis block.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
2015-03-15 08:31:40 +02:00
|
|
|
Action: console,
|
|
|
|
Name: "console",
|
2015-03-16 17:49:39 +02:00
|
|
|
Usage: `Ethereum Console: interactive JavaScript environment`,
|
2015-03-15 08:31:40 +02:00
|
|
|
Description: `
|
2015-03-16 17:49:39 +02:00
|
|
|
Console is an interactive shell for the Ethereum JavaScript runtime environment which exposes a node admin interface as well as the DAPP JavaScript API.
|
2015-03-15 08:31:40 +02:00
|
|
|
See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Action: execJSFiles,
|
2015-03-06 04:00:41 +02:00
|
|
|
Name: "js",
|
2015-03-15 08:31:40 +02:00
|
|
|
Usage: `executes the given JavaScript files in the Ethereum Frontier JavaScript VM`,
|
2015-03-06 04:00:41 +02:00
|
|
|
Description: `
|
2015-03-16 17:49:39 +02:00
|
|
|
The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
2015-03-06 04:00:41 +02:00
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Action: importchain,
|
|
|
|
Name: "import",
|
|
|
|
Usage: `import a blockchain file`,
|
|
|
|
},
|
2015-03-08 17:44:48 +02:00
|
|
|
{
|
|
|
|
Action: exportchain,
|
|
|
|
Name: "export",
|
|
|
|
Usage: `export blockchain into file`,
|
|
|
|
},
|
2015-03-06 04:00:41 +02:00
|
|
|
}
|
|
|
|
app.Flags = []cli.Flag{
|
2015-03-11 02:08:42 +02:00
|
|
|
utils.UnlockedAccountFlag,
|
2015-03-23 15:00:06 +02:00
|
|
|
utils.PasswordFileFlag,
|
2015-03-06 04:00:41 +02:00
|
|
|
utils.BootnodesFlag,
|
|
|
|
utils.DataDirFlag,
|
2015-03-15 08:31:40 +02:00
|
|
|
utils.JSpathFlag,
|
2015-03-06 04:00:41 +02:00
|
|
|
utils.ListenPortFlag,
|
|
|
|
utils.LogFileFlag,
|
2015-03-21 11:20:47 +02:00
|
|
|
utils.LogJSONFlag,
|
2015-03-06 04:00:41 +02:00
|
|
|
utils.LogLevelFlag,
|
|
|
|
utils.MaxPeersFlag,
|
|
|
|
utils.MinerThreadsFlag,
|
|
|
|
utils.MiningEnabledFlag,
|
|
|
|
utils.NATFlag,
|
|
|
|
utils.NodeKeyFileFlag,
|
|
|
|
utils.NodeKeyHexFlag,
|
|
|
|
utils.RPCEnabledFlag,
|
|
|
|
utils.RPCListenAddrFlag,
|
|
|
|
utils.RPCPortFlag,
|
2015-03-11 14:56:02 +02:00
|
|
|
utils.UnencryptedKeysFlag,
|
2015-03-06 17:58:52 +02:00
|
|
|
utils.VMDebugFlag,
|
2015-03-18 09:44:58 +02:00
|
|
|
utils.ProtocolVersionFlag,
|
|
|
|
utils.NetworkIdFlag,
|
2015-03-06 04:00:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// missing:
|
|
|
|
// flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
|
|
|
|
// flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
|
|
|
|
// flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
|
2014-06-23 14:20:59 +03:00
|
|
|
|
2015-03-06 04:00:41 +02:00
|
|
|
// potential subcommands:
|
|
|
|
// flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
|
|
|
|
// flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
|
|
|
|
// flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
|
|
|
|
}
|
2014-12-23 15:33:15 +02:00
|
|
|
|
2015-03-06 04:00:41 +02:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
2014-06-26 12:47:45 +03:00
|
|
|
|
2015-03-06 04:00:41 +02:00
|
|
|
func run(ctx *cli.Context) {
|
|
|
|
fmt.Printf("Welcome to the FRONTIER\n")
|
2015-03-06 13:18:44 +02:00
|
|
|
utils.HandleInterrupt()
|
2015-03-13 19:30:45 +02:00
|
|
|
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
|
|
|
ethereum, err := eth.New(cfg)
|
2015-03-12 00:41:51 +02:00
|
|
|
if err != nil {
|
2015-03-10 16:44:05 +02:00
|
|
|
utils.Fatalf("%v", err)
|
|
|
|
}
|
|
|
|
|
2015-03-13 19:30:45 +02:00
|
|
|
startEth(ctx, ethereum)
|
2015-03-06 04:00:41 +02:00
|
|
|
// this blocks the thread
|
2015-03-13 19:30:45 +02:00
|
|
|
ethereum.WaitForShutdown()
|
2015-03-06 04:00:41 +02:00
|
|
|
}
|
2014-07-11 17:04:27 +03:00
|
|
|
|
2015-03-15 08:31:40 +02:00
|
|
|
func console(ctx *cli.Context) {
|
2015-03-13 19:30:45 +02:00
|
|
|
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
|
|
|
ethereum, err := eth.New(cfg)
|
2015-03-12 00:41:51 +02:00
|
|
|
if err != nil {
|
2015-03-10 16:44:05 +02:00
|
|
|
utils.Fatalf("%v", err)
|
|
|
|
}
|
|
|
|
|
2015-03-13 19:30:45 +02:00
|
|
|
startEth(ctx, ethereum)
|
2015-03-24 16:09:06 +02:00
|
|
|
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name), true)
|
2015-03-15 08:31:40 +02:00
|
|
|
repl.interactive()
|
|
|
|
|
|
|
|
ethereum.Stop()
|
|
|
|
ethereum.WaitForShutdown()
|
|
|
|
}
|
|
|
|
|
|
|
|
func execJSFiles(ctx *cli.Context) {
|
|
|
|
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
|
|
|
ethereum, err := eth.New(cfg)
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("%v", err)
|
2015-01-07 02:21:55 +02:00
|
|
|
}
|
2015-03-15 08:31:40 +02:00
|
|
|
|
|
|
|
startEth(ctx, ethereum)
|
2015-03-24 16:09:06 +02:00
|
|
|
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name), false)
|
2015-03-15 08:31:40 +02:00
|
|
|
for _, file := range ctx.Args() {
|
|
|
|
repl.exec(file)
|
|
|
|
}
|
|
|
|
|
2015-03-13 19:30:45 +02:00
|
|
|
ethereum.Stop()
|
|
|
|
ethereum.WaitForShutdown()
|
2015-03-06 04:00:41 +02:00
|
|
|
}
|
2015-01-07 02:21:55 +02:00
|
|
|
|
2015-03-23 15:00:06 +02:00
|
|
|
func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (passphrase string) {
|
|
|
|
if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
|
|
|
|
var err error
|
|
|
|
// Load startup keys. XXX we are going to need a different format
|
|
|
|
// Attempt to unlock the account
|
|
|
|
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
|
|
|
|
if len(passfile) == 0 {
|
|
|
|
fmt.Println("Please enter a passphrase now.")
|
|
|
|
auth, err := readPassword("Passphrase: ", true)
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("%v", err)
|
|
|
|
}
|
2015-03-11 02:08:42 +02:00
|
|
|
|
2015-03-23 15:00:06 +02:00
|
|
|
passphrase = auth
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if passphrase, err = common.ReadAllFile(passfile); err != nil {
|
|
|
|
utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
|
|
|
|
}
|
2015-03-11 02:08:42 +02:00
|
|
|
}
|
2015-03-23 15:00:06 +02:00
|
|
|
|
|
|
|
err = am.Unlock(common.FromHex(account), passphrase)
|
2015-03-11 02:08:42 +02:00
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("Unlock account failed '%v'", err)
|
|
|
|
}
|
|
|
|
}
|
2015-03-23 15:00:06 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func startEth(ctx *cli.Context, eth *eth.Ethereum) {
|
|
|
|
utils.StartEthereum(eth)
|
|
|
|
am := eth.AccountManager()
|
|
|
|
|
|
|
|
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
|
|
|
|
if len(account) > 0 {
|
2015-03-24 14:37:00 +02:00
|
|
|
if account == "coinbase" {
|
|
|
|
account = ""
|
|
|
|
}
|
2015-03-23 15:00:06 +02:00
|
|
|
unlockAccount(ctx, am, account)
|
|
|
|
}
|
2015-03-10 17:44:22 +02:00
|
|
|
// Start auxiliary services if enabled.
|
2015-03-06 04:00:41 +02:00
|
|
|
if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
|
2015-03-10 00:00:27 +02:00
|
|
|
utils.StartRPC(eth, ctx)
|
2015-03-06 04:00:41 +02:00
|
|
|
}
|
|
|
|
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
|
2015-03-12 00:35:34 +02:00
|
|
|
eth.StartMining()
|
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) {
|
|
|
|
am := utils.GetAccountManager(ctx)
|
|
|
|
accts, err := am.Accounts()
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("Could not list accounts: %v", err)
|
|
|
|
}
|
|
|
|
for _, acct := range accts {
|
2015-03-20 13:52:03 +02:00
|
|
|
fmt.Printf("Address: %x\n", acct)
|
2015-03-07 13:39:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-23 15:00:06 +02:00
|
|
|
func getPassPhrase(ctx *cli.Context) (passphrase string) {
|
2015-03-11 14:56:02 +02:00
|
|
|
if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
|
2015-03-23 15:00:06 +02:00
|
|
|
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
|
|
|
|
if len(passfile) == 0 {
|
|
|
|
fmt.Println("The new account will be encrypted with a passphrase.")
|
|
|
|
fmt.Println("Please enter a passphrase now.")
|
|
|
|
auth, err := readPassword("Passphrase: ", true)
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("%v", err)
|
|
|
|
}
|
|
|
|
confirm, err := readPassword("Repeat Passphrase: ", false)
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("%v", err)
|
|
|
|
}
|
|
|
|
if auth != confirm {
|
|
|
|
utils.Fatalf("Passphrases did not match.")
|
|
|
|
}
|
|
|
|
passphrase = auth
|
|
|
|
|
|
|
|
} else {
|
|
|
|
var err error
|
|
|
|
if passphrase, err = common.ReadAllFile(passfile); err != nil {
|
|
|
|
utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
|
|
|
|
}
|
2015-03-11 14:56:02 +02:00
|
|
|
}
|
2015-03-07 13:39:52 +02:00
|
|
|
}
|
2015-03-23 15:00:06 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func accountCreate(ctx *cli.Context) {
|
|
|
|
am := utils.GetAccountManager(ctx)
|
|
|
|
passphrase := getPassPhrase(ctx)
|
2015-03-11 14:56:02 +02:00
|
|
|
acct, err := am.NewAccount(passphrase)
|
2015-03-07 13:39:52 +02:00
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("Could not create the account: %v", err)
|
|
|
|
}
|
2015-03-23 15:00:06 +02:00
|
|
|
fmt.Printf("Address: %x\n", acct)
|
|
|
|
}
|
|
|
|
|
|
|
|
func accountImport(ctx *cli.Context) {
|
|
|
|
keyfile := ctx.Args().First()
|
|
|
|
if len(keyfile) == 0 {
|
|
|
|
utils.Fatalf("keyfile must be given as argument")
|
|
|
|
}
|
|
|
|
am := utils.GetAccountManager(ctx)
|
|
|
|
passphrase := getPassPhrase(ctx)
|
|
|
|
acct, err := am.Import(keyfile, passphrase)
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("Could not create the account: %v", err)
|
|
|
|
}
|
|
|
|
fmt.Printf("Address: %x\n", acct)
|
|
|
|
}
|
|
|
|
|
|
|
|
func accountExport(ctx *cli.Context) {
|
|
|
|
account := ctx.Args().First()
|
|
|
|
if len(account) == 0 {
|
|
|
|
utils.Fatalf("account address must be given as first argument")
|
|
|
|
}
|
|
|
|
keyfile := ctx.Args().Get(1)
|
|
|
|
if len(keyfile) == 0 {
|
|
|
|
utils.Fatalf("keyfile must be given as second argument")
|
|
|
|
}
|
|
|
|
am := utils.GetAccountManager(ctx)
|
|
|
|
auth := unlockAccount(ctx, am, account)
|
|
|
|
err := am.Export(keyfile, common.FromHex(account), auth)
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("Account export failed: %v", err)
|
|
|
|
}
|
2015-03-07 13:39:52 +02:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:00:41 +02:00
|
|
|
func importchain(ctx *cli.Context) {
|
|
|
|
if len(ctx.Args()) != 1 {
|
|
|
|
utils.Fatalf("This command requires an argument.")
|
|
|
|
}
|
2015-03-08 17:44:48 +02:00
|
|
|
chainmgr, _, _ := utils.GetChain(ctx)
|
2015-03-06 04:00:41 +02:00
|
|
|
start := time.Now()
|
2015-03-08 17:44:48 +02:00
|
|
|
err := utils.ImportChain(chainmgr, ctx.Args().First())
|
2014-08-22 13:14:37 +03:00
|
|
|
if err != nil {
|
2015-03-06 04:00:41 +02:00
|
|
|
utils.Fatalf("Import error: %v\n", err)
|
2014-08-22 13:14:37 +03:00
|
|
|
}
|
2015-03-08 17:44:48 +02:00
|
|
|
fmt.Printf("Import done in %v", time.Since(start))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func exportchain(ctx *cli.Context) {
|
|
|
|
if len(ctx.Args()) != 1 {
|
|
|
|
utils.Fatalf("This command requires an argument.")
|
|
|
|
}
|
|
|
|
chainmgr, _, _ := utils.GetChain(ctx)
|
|
|
|
start := time.Now()
|
|
|
|
err := utils.ExportChain(chainmgr, ctx.Args().First())
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("Export error: %v\n", err)
|
|
|
|
}
|
|
|
|
fmt.Printf("Export done in %v", time.Since(start))
|
2015-03-06 04:00:41 +02:00
|
|
|
return
|
|
|
|
}
|
2015-01-05 18:10:42 +02:00
|
|
|
|
2015-03-06 04:00:41 +02:00
|
|
|
func dump(ctx *cli.Context) {
|
2015-03-08 17:44:48 +02:00
|
|
|
chainmgr, _, stateDb := utils.GetChain(ctx)
|
2015-03-06 04:00:41 +02:00
|
|
|
for _, arg := range ctx.Args() {
|
2014-11-18 20:52:45 +02:00
|
|
|
var block *types.Block
|
2015-03-06 04:00:41 +02:00
|
|
|
if hashish(arg) {
|
2015-03-18 14:00:01 +02:00
|
|
|
block = chainmgr.GetBlock(common.HexToHash(arg))
|
2014-08-06 10:53:12 +03:00
|
|
|
} else {
|
2015-03-06 04:00:41 +02:00
|
|
|
num, _ := strconv.Atoi(arg)
|
2015-03-08 17:44:48 +02:00
|
|
|
block = chainmgr.GetBlockByNumber(uint64(num))
|
2014-08-06 10:53:12 +03:00
|
|
|
}
|
|
|
|
if block == nil {
|
|
|
|
fmt.Println("{}")
|
2015-03-06 04:00:41 +02:00
|
|
|
utils.Fatalf("block not found")
|
|
|
|
} else {
|
2015-03-06 19:26:16 +02:00
|
|
|
statedb := state.New(block.Root(), stateDb)
|
2015-03-06 04:00:41 +02:00
|
|
|
fmt.Printf("%s\n", statedb.Dump())
|
|
|
|
// fmt.Println(block)
|
2014-12-23 15:33:15 +02:00
|
|
|
}
|
2015-03-01 00:01:41 +02:00
|
|
|
}
|
2015-03-06 04:00:41 +02:00
|
|
|
}
|
2015-03-01 00:01:41 +02:00
|
|
|
|
2015-03-17 15:12:34 +02:00
|
|
|
func makedag(ctx *cli.Context) {
|
|
|
|
chain, _, _ := utils.GetChain(ctx)
|
|
|
|
pow := ethash.New(chain)
|
|
|
|
fmt.Println("making cache")
|
|
|
|
pow.UpdateCache(true)
|
|
|
|
fmt.Println("making DAG")
|
|
|
|
pow.UpdateDAG()
|
|
|
|
}
|
|
|
|
|
2015-03-06 04:00:41 +02:00
|
|
|
func version(c *cli.Context) {
|
2015-03-08 17:50:27 +02:00
|
|
|
fmt.Printf(`%v
|
|
|
|
Version: %v
|
|
|
|
Protocol Version: %d
|
|
|
|
Network Id: %d
|
|
|
|
GO: %s
|
|
|
|
OS: %s
|
2015-01-07 02:21:55 +02:00
|
|
|
GOPATH=%s
|
|
|
|
GOROOT=%s
|
2015-03-18 09:44:58 +02:00
|
|
|
`, ClientIdentifier, Version, c.GlobalInt(utils.ProtocolVersionFlag.Name), c.GlobalInt(utils.NetworkIdFlag.Name), runtime.Version(), runtime.GOOS, os.Getenv("GOPATH"), runtime.GOROOT())
|
2015-01-07 02:21:55 +02:00
|
|
|
}
|
2015-03-07 13:39:52 +02:00
|
|
|
|
|
|
|
// hashish returns true for strings that look like hashes.
|
|
|
|
func hashish(x string) bool {
|
|
|
|
_, err := strconv.Atoi(x)
|
|
|
|
return err != nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func readPassword(prompt string, warnTerm bool) (string, error) {
|
|
|
|
if liner.TerminalSupported() {
|
|
|
|
lr := liner.NewLiner()
|
|
|
|
defer lr.Close()
|
|
|
|
return lr.PasswordPrompt(prompt)
|
|
|
|
}
|
|
|
|
if warnTerm {
|
|
|
|
fmt.Println("!! Unsupported terminal, password will be echoed.")
|
|
|
|
}
|
|
|
|
fmt.Print(prompt)
|
|
|
|
input, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
|
|
|
fmt.Println()
|
|
|
|
return input, err
|
|
|
|
}
|