aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/geth
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2015-11-18 00:33:25 +0800
committerPéter Szilágyi <peterke@gmail.com>2015-11-27 17:06:12 +0800
commit1e806c4c775bd98b224eb0249007502d348e737b (patch)
treea34bfcac320df6f65e73eb1578b212289be86b5f /cmd/geth
parent8a44451edfa36ea40da564a2fa7ea905d45440a4 (diff)
downloaddexon-1e806c4c775bd98b224eb0249007502d348e737b.tar
dexon-1e806c4c775bd98b224eb0249007502d348e737b.tar.gz
dexon-1e806c4c775bd98b224eb0249007502d348e737b.tar.bz2
dexon-1e806c4c775bd98b224eb0249007502d348e737b.tar.lz
dexon-1e806c4c775bd98b224eb0249007502d348e737b.tar.xz
dexon-1e806c4c775bd98b224eb0249007502d348e737b.tar.zst
dexon-1e806c4c775bd98b224eb0249007502d348e737b.zip
cmd, common, core, eth, node, rpc, tests, whisper, xeth: use protocol stacks
Diffstat (limited to 'cmd/geth')
-rw-r--r--cmd/geth/js.go33
-rw-r--r--cmd/geth/js_test.go128
-rw-r--r--cmd/geth/main.go307
3 files changed, 195 insertions, 273 deletions
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index 4d5462539..a0e8bdb21 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/common/registrar"
"github.com/ethereum/go-ethereum/eth"
re "github.com/ethereum/go-ethereum/jsre"
+ "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec"
@@ -77,7 +78,7 @@ func (r dumbterm) AppendHistory(string) {}
type jsre struct {
re *re.JSRE
- ethereum *eth.Ethereum
+ stack *node.Node
xeth *xeth.XEth
wait chan *big.Int
ps1 string
@@ -176,18 +177,18 @@ func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir str
return js
}
-func newJSRE(ethereum *eth.Ethereum, docRoot, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
- js := &jsre{ethereum: ethereum, ps1: "> "}
+func newJSRE(stack *node.Node, docRoot, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
+ js := &jsre{stack: stack, ps1: "> "}
// set default cors domain used by startRpc from CLI flag
js.corsDomain = corsDomain
if f == nil {
f = js
}
- js.xeth = xeth.New(ethereum, f)
+ js.xeth = xeth.New(stack, f)
js.wait = js.xeth.UpdateState()
js.client = client
if clt, ok := js.client.(*comms.InProcClient); ok {
- if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, ethereum); err == nil {
+ if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, stack); err == nil {
clt.Initialize(api.Merge(offeredApis...))
}
}
@@ -202,14 +203,14 @@ func newJSRE(ethereum *eth.Ethereum, docRoot, corsDomain string, client comms.Et
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
} else {
lr := liner.NewLiner()
- js.withHistory(ethereum.DataDir, func(hist *os.File) { lr.ReadHistory(hist) })
+ js.withHistory(stack.DataDir(), func(hist *os.File) { lr.ReadHistory(hist) })
lr.SetCtrlCAborts(true)
js.loadAutoCompletion()
lr.SetWordCompleter(apiWordCompleter)
lr.SetTabCompletionStyle(liner.TabPrints)
js.prompter = lr
js.atexit = func() {
- js.withHistory(ethereum.DataDir, func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
+ js.withHistory(stack.DataDir(), func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
lr.Close()
close(js.wait)
}
@@ -276,7 +277,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
apiNames = append(apiNames, a)
}
- apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum)
+ apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.stack)
if err != nil {
utils.Fatalf("Unable to determine supported api's: %v", err)
}
@@ -342,8 +343,14 @@ func (self *jsre) AskPassword() (string, bool) {
}
func (self *jsre) ConfirmTransaction(tx string) bool {
- if self.ethereum.NatSpec {
- notice := natspec.GetNotice(self.xeth, tx, self.ethereum.HTTPClient())
+ // Retrieve the Ethereum instance from the node
+ var ethereum *eth.Ethereum
+ if _, err := self.stack.SingletonService(&ethereum); err != nil {
+ return false
+ }
+ // If natspec is enabled, ask for permission
+ if ethereum.NatSpec {
+ notice := natspec.GetNotice(self.xeth, tx, ethereum.HTTPClient())
fmt.Println(notice)
answer, _ := self.Prompt("Confirm Transaction [y/n]")
return strings.HasPrefix(strings.Trim(answer, " "), "y")
@@ -359,7 +366,11 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
return false
}
// TODO: allow retry
- if err := self.ethereum.AccountManager().Unlock(common.BytesToAddress(addr), pass); err != nil {
+ var ethereum *eth.Ethereum
+ if _, err := self.stack.SingletonService(&ethereum); err != nil {
+ return false
+ }
+ if err := ethereum.AccountManager().Unlock(common.BytesToAddress(addr), pass); err != nil {
return false
} else {
fmt.Println("Account is now unlocked for this session.")
diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go
index 477079706..ed4d04b48 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
)
@@ -66,7 +67,10 @@ type testjethre struct {
}
func (self *testjethre) UnlockAccount(acc []byte) bool {
- err := self.ethereum.AccountManager().Unlock(common.BytesToAddress(acc), "")
+ var ethereum *eth.Ethereum
+ self.stack.SingletonService(&ethereum)
+
+ err := ethereum.AccountManager().Unlock(common.BytesToAddress(acc), "")
if err != nil {
panic("unable to unlock")
}
@@ -74,67 +78,74 @@ func (self *testjethre) UnlockAccount(acc []byte) bool {
}
func (self *testjethre) ConfirmTransaction(tx string) bool {
- if self.ethereum.NatSpec {
+ var ethereum *eth.Ethereum
+ self.stack.SingletonService(&ethereum)
+
+ if ethereum.NatSpec {
self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.client)
}
return true
}
-func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) {
+func testJEthRE(t *testing.T) (string, *testjethre, *node.Node) {
return testREPL(t, nil)
}
-func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *eth.Ethereum) {
+func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *node.Node) {
tmp, err := ioutil.TempDir("", "geth-test")
if err != nil {
t.Fatal(err)
}
+ // Create a networkless protocol stack
+ stack, err := node.New(&node.Config{PrivateKey: testNodeKey, Name: "test", NoDiscovery: true})
+ if err != nil {
+ t.Fatalf("failed to create node: %v", err)
+ }
+ // Initialize and register the Ethereum protocol
+ keystore := crypto.NewKeyStorePlain(filepath.Join(tmp, "keystore"))
+ accman := accounts.NewManager(keystore)
db, _ := ethdb.NewMemDatabase()
-
core.WriteGenesisBlockForTesting(db, core.GenesisAccount{common.HexToAddress(testAddress), common.String2Big(testBalance)})
- ks := crypto.NewKeyStorePlain(filepath.Join(tmp, "keystore"))
- am := accounts.NewManager(ks)
- conf := &eth.Config{
- NodeKey: testNodeKey,
- DataDir: tmp,
- AccountManager: am,
- MaxPeers: 0,
- Name: "test",
- DocRoot: "/",
- SolcPath: testSolcPath,
- PowTest: true,
- NewDB: func(path string) (ethdb.Database, error) { return db, nil },
+
+ ethConf := &eth.Config{
+ TestGenesisState: db,
+ AccountManager: accman,
+ DocRoot: "/",
+ SolcPath: testSolcPath,
+ PowTest: true,
}
if config != nil {
- config(conf)
+ config(ethConf)
}
- ethereum, err := eth.New(conf)
- if err != nil {
- t.Fatal("%v", err)
+ if err := stack.Register("ethereum", func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil {
+ t.Fatalf("failed to register ethereum protocol: %v", err)
}
-
+ // Initialize all the keys for testing
keyb, err := crypto.HexToECDSA(testKey)
if err != nil {
t.Fatal(err)
}
key := crypto.NewKeyFromECDSA(keyb)
- err = ks.StoreKey(key, "")
- if err != nil {
+ if err := keystore.StoreKey(key, ""); err != nil {
t.Fatal(err)
}
-
- err = am.Unlock(key.Address, "")
- if err != nil {
+ if err := accman.Unlock(key.Address, ""); err != nil {
t.Fatal(err)
}
+ // Start the node and assemble the REPL tester
+ if err := stack.Start(); err != nil {
+ t.Fatalf("failed to start test stack: %v", err)
+ }
+ var ethereum *eth.Ethereum
+ stack.SingletonService(&ethereum)
assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
client := comms.NewInProcClient(codec.JSON)
tf := &testjethre{client: ethereum.HTTPClient()}
- repl := newJSRE(ethereum, assetPath, "", client, false, tf)
+ repl := newJSRE(stack, assetPath, "", client, false, tf)
tf.jsre = repl
- return tmp, tf, ethereum
+ return tmp, tf, stack
}
func TestNodeInfo(t *testing.T) {
@@ -151,11 +162,8 @@ func TestNodeInfo(t *testing.T) {
}
func TestAccounts(t *testing.T) {
- tmp, repl, ethereum := testJEthRE(t)
- if err := ethereum.Start(); err != nil {
- t.Fatalf("error starting ethereum: %v", err)
- }
- defer ethereum.Stop()
+ tmp, repl, node := testJEthRE(t)
+ defer node.Stop()
defer os.RemoveAll(tmp)
checkEvalJSON(t, repl, `eth.accounts`, `["`+testAddress+`"]`)
@@ -174,11 +182,8 @@ func TestAccounts(t *testing.T) {
}
func TestBlockChain(t *testing.T) {
- tmp, repl, ethereum := testJEthRE(t)
- if err := ethereum.Start(); err != nil {
- t.Fatalf("error starting ethereum: %v", err)
- }
- defer ethereum.Stop()
+ tmp, repl, node := testJEthRE(t)
+ defer node.Stop()
defer os.RemoveAll(tmp)
// get current block dump before export/import.
val, err := repl.re.Run("JSON.stringify(debug.dumpBlock(eth.blockNumber))")
@@ -196,6 +201,8 @@ func TestBlockChain(t *testing.T) {
tmpfile := filepath.Join(extmp, "export.chain")
tmpfileq := strconv.Quote(tmpfile)
+ var ethereum *eth.Ethereum
+ node.SingletonService(&ethereum)
ethereum.BlockChain().Reset()
checkEvalJSON(t, repl, `admin.exportChain(`+tmpfileq+`)`, `true`)
@@ -209,22 +216,15 @@ func TestBlockChain(t *testing.T) {
}
func TestMining(t *testing.T) {
- tmp, repl, ethereum := testJEthRE(t)
- if err := ethereum.Start(); err != nil {
- t.Fatalf("error starting ethereum: %v", err)
- }
- defer ethereum.Stop()
+ tmp, repl, node := testJEthRE(t)
+ defer node.Stop()
defer os.RemoveAll(tmp)
checkEvalJSON(t, repl, `eth.mining`, `false`)
}
func TestRPC(t *testing.T) {
- tmp, repl, ethereum := testJEthRE(t)
- if err := ethereum.Start(); err != nil {
- t.Errorf("error starting ethereum: %v", err)
- return
- }
- defer ethereum.Stop()
+ tmp, repl, node := testJEthRE(t)
+ defer node.Stop()
defer os.RemoveAll(tmp)
checkEvalJSON(t, repl, `admin.startRPC("127.0.0.1", 5004, "*", "web3,eth,net")`, `true`)
@@ -234,12 +234,8 @@ func TestCheckTestAccountBalance(t *testing.T) {
t.Skip() // i don't think it tests the correct behaviour here. it's actually testing
// internals which shouldn't be tested. This now fails because of a change in the core
// and i have no means to fix this, sorry - @obscuren
- tmp, repl, ethereum := testJEthRE(t)
- if err := ethereum.Start(); err != nil {
- t.Errorf("error starting ethereum: %v", err)
- return
- }
- defer ethereum.Stop()
+ tmp, repl, node := testJEthRE(t)
+ defer node.Stop()
defer os.RemoveAll(tmp)
repl.re.Run(`primary = "` + testAddress + `"`)
@@ -247,12 +243,8 @@ func TestCheckTestAccountBalance(t *testing.T) {
}
func TestSignature(t *testing.T) {
- tmp, repl, ethereum := testJEthRE(t)
- if err := ethereum.Start(); err != nil {
- t.Errorf("error starting ethereum: %v", err)
- return
- }
- defer ethereum.Stop()
+ tmp, repl, node := testJEthRE(t)
+ defer node.Stop()
defer os.RemoveAll(tmp)
val, err := repl.re.Run(`eth.sign("` + testAddress + `", "` + testHash + `")`)
@@ -443,7 +435,10 @@ multiply7 = Multiply7.at(contractaddress);
}
func pendingTransactions(repl *testjethre, t *testing.T) (txc int64, err error) {
- txs := repl.ethereum.TxPool().GetTransactions()
+ var ethereum *eth.Ethereum
+ repl.stack.SingletonService(&ethereum)
+
+ txs := ethereum.TxPool().GetTransactions()
return int64(len(txs)), nil
}
@@ -468,12 +463,15 @@ func processTxs(repl *testjethre, t *testing.T, expTxc int) bool {
t.Errorf("incorrect number of pending transactions, expected %v, got %v", expTxc, txc)
return false
}
- err = repl.ethereum.StartMining(runtime.NumCPU(), "")
+ var ethereum *eth.Ethereum
+ repl.stack.SingletonService(&ethereum)
+
+ err = ethereum.StartMining(runtime.NumCPU(), "")
if err != nil {
t.Errorf("unexpected error mining: %v", err)
return false
}
- defer repl.ethereum.StopMining()
+ defer ethereum.StopMining()
timer := time.NewTimer(100 * time.Second)
height := new(big.Int).Add(repl.xeth.CurrentBlock().Number(), big.NewInt(1))
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 82bc21ab0..6fac4f458 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -33,13 +33,11 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc/codec"
@@ -68,22 +66,9 @@ func init() {
}
app = utils.NewApp(Version, "the go-ethereum command line interface")
- app.Action = run
+ app.Action = geth
app.HideVersion = true // we have a command to print the version
app.Commands = []cli.Command{
- {
- Action: blockRecovery,
- Name: "recover",
- Usage: "Attempts to recover a corrupted database by setting a new block by number or hash",
- Description: `
-The recover commands will attempt to read out the last
-block based on that.
-
-recover #number recovers by number
-recover <hex> recovers by hash
-`,
- },
- blocktestCommand,
importCommand,
exportCommand,
upgradedbCommand,
@@ -285,7 +270,7 @@ This command allows to open a console on a running geth node.
`,
},
{
- Action: execJSFiles,
+ Action: execScripts,
Name: "js",
Usage: `executes the given JavaScript files in the Geth JavaScript VM`,
Description: `
@@ -376,14 +361,6 @@ func main() {
}
}
-// makeExtra resolves extradata for the miner from a flag or returns a default.
-func makeExtra(ctx *cli.Context) []byte {
- if ctx.GlobalIsSet(utils.ExtraDataFlag.Name) {
- return []byte(ctx.GlobalString(utils.ExtraDataFlag.Name))
- }
- return makeDefaultExtra()
-}
-
func makeDefaultExtra() []byte {
var clientInfo = struct {
Version uint
@@ -404,18 +381,13 @@ func makeDefaultExtra() []byte {
return extra
}
-func run(ctx *cli.Context) {
- cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
- cfg.ExtraData = makeExtra(ctx)
-
- ethereum, err := eth.New(cfg)
- if err != nil {
- utils.Fatalf("%v", err)
- }
-
- startEth(ctx, ethereum)
- // this blocks the thread
- ethereum.WaitForShutdown()
+// 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()
}
func attach(ctx *cli.Context) {
@@ -449,156 +421,107 @@ func attach(ctx *cli.Context) {
}
}
+// console starts a new geth node, attaching a JavaScript console to it at the
+// same time.
func console(ctx *cli.Context) {
- cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
- cfg.ExtraData = makeExtra(ctx)
-
- ethereum, err := eth.New(cfg)
- if err != nil {
- utils.Fatalf("%v", err)
- }
+ // Create and start the node based on the CLI flags
+ node := utils.MakeSystemNode(ClientIdentifier, nodeNameVersion, makeDefaultExtra(), ctx)
+ startNode(ctx, node)
+ // Attach to the newly started node, and either execute script or become interactive
client := comms.NewInProcClient(codec.JSON)
-
- startEth(ctx, ethereum)
- repl := newJSRE(
- ethereum,
+ repl := newJSRE(node,
ctx.GlobalString(utils.JSpathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
- client,
- true,
- nil,
- )
+ client, true, nil)
- if ctx.GlobalString(utils.ExecFlag.Name) != "" {
- repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
+ if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
+ repl.batch(script)
} else {
repl.welcome()
repl.interactive()
}
-
- ethereum.Stop()
- ethereum.WaitForShutdown()
+ node.Stop()
}
-func execJSFiles(ctx *cli.Context) {
- cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
- ethereum, err := eth.New(cfg)
- if err != nil {
- utils.Fatalf("%v", err)
- }
+// 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)
+ // Attach to the newly started node and execute the given scripts
client := comms.NewInProcClient(codec.JSON)
- startEth(ctx, ethereum)
- repl := newJSRE(
- ethereum,
+ repl := newJSRE(node,
ctx.GlobalString(utils.JSpathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
- client,
- false,
- nil,
- )
+ client, false, nil)
+
for _, file := range ctx.Args() {
repl.exec(file)
}
-
- ethereum.Stop()
- ethereum.WaitForShutdown()
+ node.Stop()
}
-func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int, inputpassphrases []string) (addrHex, auth string, passphrases []string) {
- var err error
- passphrases = inputpassphrases
- 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, passphrases = getPassPhrase(ctx, msg, false, i, passphrases)
- err = am.Unlock(common.HexToAddress(addrHex), auth)
- if err == nil || passphrases != nil {
- break
- }
- }
- }
+func unlockAccount(ctx *cli.Context, accman *accounts.Manager, address string, i int, passwords []string) (common.Address, string) {
+ // Try to unlock the specified account a few times
+ account := utils.MakeAddress(accman, address)
- if err != nil {
- utils.Fatalf("Unlock account '%s' (%v) failed: %v", addr, addrHex, err)
+ 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
+ }
}
- fmt.Printf("Account '%s' (%v) unlocked.\n", addr, addrHex)
- return
+ // All trials expended to unlock account, bail out
+ utils.Fatalf("Failed to unlock account: %s", address)
+ return common.Address{}, ""
}
-func blockRecovery(ctx *cli.Context) {
- if len(ctx.Args()) < 1 {
- glog.Fatal("recover requires block number or hash")
- }
- arg := ctx.Args().First()
-
- cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
- blockDb, err := ethdb.NewLDBDatabase(filepath.Join(cfg.DataDir, "blockchain"), cfg.DatabaseCache)
- if err != nil {
- glog.Fatalln("could not open db:", err)
- }
-
- var block *types.Block
- if arg[0] == '#' {
- block = core.GetBlock(blockDb, core.GetCanonicalHash(blockDb, common.String2Big(arg[1:]).Uint64()))
- } else {
- block = core.GetBlock(blockDb, common.HexToHash(arg))
- }
-
- if block == nil {
- glog.Fatalln("block not found. Recovery failed")
- }
+// 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)
- if err = core.WriteHeadBlockHash(blockDb, block.Hash()); err != nil {
- glog.Fatalln("block write err", err)
+ // Unlock any account specifically requested
+ var ethereum *eth.Ethereum
+ if _, err := stack.SingletonService(&ethereum); err != nil {
+ utils.Fatalf("ethereum service not running: %v", err)
}
- glog.Infof("Recovery succesful. New HEAD %x\n", block.Hash())
-}
-
-func startEth(ctx *cli.Context, eth *eth.Ethereum) {
- // Start Ethereum itself
- utils.StartEthereum(eth)
+ accman := ethereum.AccountManager()
+ passwords := utils.MakePasswordList(ctx)
- am := eth.AccountManager()
- account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
- accounts := strings.Split(account, " ")
- var passphrases []string
+ accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
for i, account := range accounts {
- if len(account) > 0 {
- if account == "primary" {
- 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.")
- }
- _, _, passphrases = unlockAccount(ctx, am, account, i, passphrases)
+ if trimmed := strings.TrimSpace(account); trimmed != "" {
+ unlockAccount(ctx, accman, trimmed, i, passwords)
}
}
// Start auxiliary services if enabled.
if !ctx.GlobalBool(utils.IPCDisabledFlag.Name) {
- if err := utils.StartIPC(eth, ctx); err != nil {
- utils.Fatalf("Error string IPC: %v", err)
+ if err := utils.StartIPC(stack, ctx); err != nil {
+ utils.Fatalf("Failed to start IPC: %v", err)
}
}
if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
- if err := utils.StartRPC(eth, ctx); err != nil {
- utils.Fatalf("Error starting RPC: %v", err)
+ if err := utils.StartRPC(stack, ctx); err != nil {
+ utils.Fatalf("Failed to start RPC: %v", err)
}
}
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
- err := eth.StartMining(
- ctx.GlobalInt(utils.MinerThreadsFlag.Name),
- ctx.GlobalString(utils.MiningGPUFlag.Name))
- if err != nil {
- utils.Fatalf("%v", err)
+ if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
+ utils.Fatalf("Failed to start mining: %v", err)
}
}
}
func accountList(ctx *cli.Context) {
- am := utils.MakeAccountManager(ctx)
- accts, err := am.Accounts()
+ accman := utils.MakeAccountManager(ctx)
+ accts, err := accman.Accounts()
if err != nil {
utils.Fatalf("Could not list accounts: %v", err)
}
@@ -607,67 +530,57 @@ func accountList(ctx *cli.Context) {
}
}
-func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int, inputpassphrases []string) (passphrase string, passphrases []string) {
- passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
- if len(passfile) == 0 {
- fmt.Println(desc)
- auth, err := utils.PromptPassword("Passphrase: ", true)
- if err != nil {
- utils.Fatalf("%v", err)
- }
- if confirmation {
- confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
- if err != nil {
- utils.Fatalf("%v", err)
- }
- if auth != confirm {
- utils.Fatalf("Passphrases did not match.")
- }
+// 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]
}
- passphrase = auth
-
- } else {
- passphrases = inputpassphrases
- if passphrases == nil {
- passbytes, err := ioutil.ReadFile(passfile)
- if err != nil {
- utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
- }
- // 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")
+ 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)
}
- if i >= len(passphrases) {
- passphrase = passphrases[len(passphrases)-1]
- } else {
- passphrase = passphrases[i]
+ if password != confirm {
+ utils.Fatalf("Passphrases do not match")
}
}
- return
+ return password
}
+// accountCreate creates a new account into the keystore defined by the CLI flags.
func accountCreate(ctx *cli.Context) {
- am := utils.MakeAccountManager(ctx)
- passphrase, _ := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, nil)
- acct, err := am.NewAccount(passphrase)
+ 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)
if err != nil {
- utils.Fatalf("Could not create the account: %v", err)
+ utils.Fatalf("Failed to create account: %v", err)
}
- fmt.Printf("Address: %x\n", acct)
+ fmt.Printf("Address: %x\n", account)
}
+// accountUpdate transitions an account from a previous format to the current
+// one, also providing the possibility to change the pass-phrase.
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")
+ if len(ctx.Args()) == 0 {
+ utils.Fatalf("No accounts specified to update")
}
+ accman := utils.MakeAccountManager(ctx)
- addr, authFrom, passphrases := unlockAccount(ctx, am, arg, 0, nil)
- authTo, _ := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0, passphrases)
- err := am.Update(common.HexToAddress(addr), authFrom, authTo)
- if err != nil {
+ 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 {
utils.Fatalf("Could not update the account: %v", err)
}
}
@@ -682,10 +595,10 @@ func importWallet(ctx *cli.Context) {
utils.Fatalf("Could not read wallet file: %v", err)
}
- am := utils.MakeAccountManager(ctx)
- passphrase, _ := getPassPhrase(ctx, "", false, 0, nil)
+ accman := utils.MakeAccountManager(ctx)
+ passphrase := getPassPhrase("", false, 0, utils.MakePasswordList(ctx))
- acct, err := am.ImportPreSaleKey(keyJson, passphrase)
+ acct, err := accman.ImportPreSaleKey(keyJson, passphrase)
if err != nil {
utils.Fatalf("Could not create the account: %v", err)
}
@@ -697,9 +610,9 @@ func accountImport(ctx *cli.Context) {
if len(keyfile) == 0 {
utils.Fatalf("keyfile must be given as argument")
}
- am := utils.MakeAccountManager(ctx)
- passphrase, _ := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, nil)
- acct, err := am.Import(keyfile, passphrase)
+ 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)
if err != nil {
utils.Fatalf("Could not create the account: %v", err)
}