@ -26,11 +26,11 @@ import (
"os"
"os"
"runtime"
"runtime"
"strconv"
"strconv"
"strings"
"time"
"time"
"github.com/codegangsta/cli"
"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
@ -83,11 +83,62 @@ The output of this command is supposed to be machine-readable.
Action : accountList ,
Action : accountList ,
Name : "list" ,
Name : "list" ,
Usage : "print account addresses" ,
Usage : "print account addresses" ,
Description : `
` ,
} ,
} ,
{
{
Action : accountCreate ,
Action : accountCreate ,
Name : "new" ,
Name : "new" ,
Usage : "create a new account" ,
Usage : "create a new account" ,
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 :
ethereum -- unlock < passwrdfile > account export < address > < keyfile >
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 .
` ,
} ,
} ,
} ,
} ,
} ,
} ,
@ -130,6 +181,7 @@ The Ethereum JavaScript VM exposes a node admin interface as well as the DAPP Ja
}
}
app . Flags = [ ] cli . Flag {
app . Flags = [ ] cli . Flag {
utils . UnlockedAccountFlag ,
utils . UnlockedAccountFlag ,
utils . PasswordFileFlag ,
utils . BootnodesFlag ,
utils . BootnodesFlag ,
utils . DataDirFlag ,
utils . DataDirFlag ,
utils . JSpathFlag ,
utils . JSpathFlag ,
@ -218,23 +270,43 @@ func execJSFiles(ctx *cli.Context) {
ethereum . WaitForShutdown ( )
ethereum . WaitForShutdown ( )
}
}
func startEth ( ctx * cli . Context , eth * eth . Ethereum ) {
func unlockAccount ( ctx * cli . Context , am * accounts . Manager , account string ) ( passphrase string ) {
utils . StartEthereum ( eth )
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 )
}
// Load startup keys. XXX we are going to need a different format
passphrase = auth
account := ctx . GlobalString ( utils . UnlockedAccountFlag . Name )
if len ( account ) > 0 {
} else {
split := strings . Split ( account , ":" )
if passphrase , err = common . ReadAllFile ( passfile ) ; err != nil {
if len ( split ) != 2 {
utils . Fatalf ( "Unable to read password file '%s': %v" , passfile , err )
utils . Fatalf ( "Illegal 'unlock' format (address:password)" )
}
}
}
am := eth . AccountManager ( )
// Attempt to unlock the account
err = am . Unlock ( common . FromHex ( account ) , passphrase )
err := am . Unlock ( common . FromHex ( split [ 0 ] ) , split [ 1 ] )
if err != nil {
if err != nil {
utils . Fatalf ( "Unlock account failed '%v'" , err )
utils . Fatalf ( "Unlock account failed '%v'" , err )
}
}
}
}
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 {
unlockAccount ( ctx , am , account )
}
// Start auxiliary services if enabled.
// Start auxiliary services if enabled.
if ctx . GlobalBool ( utils . RPCEnabledFlag . Name ) {
if ctx . GlobalBool ( utils . RPCEnabledFlag . Name ) {
utils . StartRPC ( eth , ctx )
utils . StartRPC ( eth , ctx )
@ -255,30 +327,74 @@ func accountList(ctx *cli.Context) {
}
}
}
}
func accountCreate ( ctx * cli . Context ) {
func getPassPhrase ( ctx * cli . Context ) ( passphrase string ) {
am := utils . GetAccountManager ( ctx )
passphrase := ""
if ! ctx . GlobalBool ( utils . UnencryptedKeysFlag . Name ) {
if ! ctx . GlobalBool ( utils . UnencryptedKeysFlag . Name ) {
fmt . Println ( "The new account will be encrypted with a passphrase." )
passfile := ctx . GlobalString ( utils . PasswordFileFlag . Name )
fmt . Println ( "Please enter a passphrase now." )
if len ( passfile ) == 0 {
auth , err := readPassword ( "Passphrase: " , true )
fmt . Println ( "The new account will be encrypted with a passphrase." )
if err != nil {
fmt . Println ( "Please enter a passphrase now." )
utils . Fatalf ( "%v" , err )
auth , err := readPassword ( "Passphrase: " , true )
}
if err != nil {
confirm , err := readPassword ( "Repeat Passphrase: " , false )
utils . Fatalf ( "%v" , err )
if err != nil {
}
utils . Fatalf ( "%v" , err )
confirm , err := readPassword ( "Repeat Passphrase: " , false )
}
if err != nil {
if auth != confirm {
utils . Fatalf ( "%v" , err )
utils . Fatalf ( "Passphrases did not match." )
}
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 )
}
}
}
passphrase = auth
}
}
return
}
func accountCreate ( ctx * cli . Context ) {
am := utils . GetAccountManager ( ctx )
passphrase := getPassPhrase ( ctx )
acct , err := am . NewAccount ( passphrase )
acct , err := am . NewAccount ( passphrase )
if err != nil {
if err != nil {
utils . Fatalf ( "Could not create the account: %v" , err )
utils . Fatalf ( "Could not create the account: %v" , err )
}
}
fmt . Printf ( "Address: %x\n" , acct . Address )
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 )
}
}
}
func importchain ( ctx * cli . Context ) {
func importchain ( ctx * cli . Context ) {