cmd/ethereum: add account commands
This commit is contained in:
parent
d66f93cecd
commit
a2810c06d7
|
@ -21,6 +21,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -34,6 +35,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
|
"github.com/peterh/liner"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -60,6 +62,23 @@ func init() {
|
||||||
The output of this command is supposed to be machine-readable.
|
The output of this command is supposed to be machine-readable.
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Action: accountList,
|
||||||
|
Name: "account",
|
||||||
|
Usage: "manage accounts",
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
{
|
||||||
|
Action: accountList,
|
||||||
|
Name: "list",
|
||||||
|
Usage: "print account addresses",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: accountCreate,
|
||||||
|
Name: "new",
|
||||||
|
Usage: "create a new account",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Action: dump,
|
Action: dump,
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
|
@ -93,8 +112,6 @@ runtime will execute the file and exit.
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
utils.BootnodesFlag,
|
utils.BootnodesFlag,
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
utils.KeyRingFlag,
|
|
||||||
utils.KeyStoreFlag,
|
|
||||||
utils.ListenPortFlag,
|
utils.ListenPortFlag,
|
||||||
utils.LogFileFlag,
|
utils.LogFileFlag,
|
||||||
utils.LogFormatFlag,
|
utils.LogFormatFlag,
|
||||||
|
@ -166,6 +183,37 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
fmt.Printf("Address: %#x\n", acct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func accountCreate(ctx *cli.Context) {
|
||||||
|
am := utils.GetAccountManager(ctx)
|
||||||
|
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.")
|
||||||
|
}
|
||||||
|
acct, err := am.NewAccount(auth)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Could not create the account: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Address: %#x\n", acct.Address)
|
||||||
|
}
|
||||||
|
|
||||||
func importchain(ctx *cli.Context) {
|
func importchain(ctx *cli.Context) {
|
||||||
if len(ctx.Args()) != 1 {
|
if len(ctx.Args()) != 1 {
|
||||||
utils.Fatalf("This command requires an argument.")
|
utils.Fatalf("This command requires an argument.")
|
||||||
|
@ -201,12 +249,6 @@ func dump(ctx *cli.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashish returns true for strings that look like hashes.
|
|
||||||
func hashish(x string) bool {
|
|
||||||
_, err := strconv.Atoi(x)
|
|
||||||
return err != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func version(c *cli.Context) {
|
func version(c *cli.Context) {
|
||||||
fmt.Printf(`%v %v
|
fmt.Printf(`%v %v
|
||||||
PV=%d
|
PV=%d
|
||||||
|
@ -216,3 +258,24 @@ GOPATH=%s
|
||||||
GOROOT=%s
|
GOROOT=%s
|
||||||
`, ClientIdentifier, Version, eth.ProtocolVersion, runtime.GOOS, runtime.Version(), os.Getenv("GOPATH"), runtime.GOROOT())
|
`, ClientIdentifier, Version, eth.ProtocolVersion, runtime.GOOS, runtime.Version(), os.Getenv("GOPATH"), runtime.GOROOT())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
|
@ -4,8 +4,10 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
|
@ -30,16 +32,6 @@ var (
|
||||||
Name: "vm",
|
Name: "vm",
|
||||||
Usage: "Virtual Machine type: 0 is standard VM, 1 is debug VM",
|
Usage: "Virtual Machine type: 0 is standard VM, 1 is debug VM",
|
||||||
}
|
}
|
||||||
KeyRingFlag = cli.StringFlag{
|
|
||||||
Name: "keyring",
|
|
||||||
Usage: "Name of keyring to be used",
|
|
||||||
Value: "",
|
|
||||||
}
|
|
||||||
KeyStoreFlag = cli.StringFlag{
|
|
||||||
Name: "keystore",
|
|
||||||
Usage: `Where to store keyrings: "db" or "file"`,
|
|
||||||
Value: "db",
|
|
||||||
}
|
|
||||||
DataDirFlag = cli.StringFlag{
|
DataDirFlag = cli.StringFlag{
|
||||||
Name: "datadir",
|
Name: "datadir",
|
||||||
Usage: "Data directory to be used",
|
Usage: "Data directory to be used",
|
||||||
|
@ -145,22 +137,20 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
|
||||||
|
|
||||||
func GetEthereum(clientID, version string, ctx *cli.Context) *eth.Ethereum {
|
func GetEthereum(clientID, version string, ctx *cli.Context) *eth.Ethereum {
|
||||||
ethereum, err := eth.New(ð.Config{
|
ethereum, err := eth.New(ð.Config{
|
||||||
Name: p2p.MakeName(clientID, version),
|
Name: p2p.MakeName(clientID, version),
|
||||||
KeyStore: ctx.GlobalString(KeyStoreFlag.Name),
|
DataDir: ctx.GlobalString(DataDirFlag.Name),
|
||||||
DataDir: ctx.GlobalString(DataDirFlag.Name),
|
LogFile: ctx.GlobalString(LogFileFlag.Name),
|
||||||
LogFile: ctx.GlobalString(LogFileFlag.Name),
|
LogLevel: ctx.GlobalInt(LogLevelFlag.Name),
|
||||||
LogLevel: ctx.GlobalInt(LogLevelFlag.Name),
|
LogFormat: ctx.GlobalString(LogFormatFlag.Name),
|
||||||
LogFormat: ctx.GlobalString(LogFormatFlag.Name),
|
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
||||||
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
AccountManager: GetAccountManager(ctx),
|
||||||
|
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
|
||||||
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
|
Port: ctx.GlobalString(ListenPortFlag.Name),
|
||||||
Port: ctx.GlobalString(ListenPortFlag.Name),
|
NAT: GetNAT(ctx),
|
||||||
NAT: GetNAT(ctx),
|
NodeKey: GetNodeKey(ctx),
|
||||||
NodeKey: GetNodeKey(ctx),
|
Shh: true,
|
||||||
KeyRing: ctx.GlobalString(KeyRingFlag.Name),
|
Dial: true,
|
||||||
Shh: true,
|
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
|
||||||
Dial: true,
|
|
||||||
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
|
@ -176,3 +166,9 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database) {
|
||||||
}
|
}
|
||||||
return core.NewChainManager(db, new(event.TypeMux)), db
|
return core.NewChainManager(db, new(event.TypeMux)), db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAccountManager(ctx *cli.Context) *accounts.AccountManager {
|
||||||
|
dataDir := ctx.GlobalString(DataDirFlag.Name)
|
||||||
|
ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
|
||||||
|
return accounts.NewAccountManager(ks, 300*time.Second)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue