Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
9bb575be
Commit
9bb575be
authored
Jul 04, 2015
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1283 from ethersphere/frontier/accounts
Account management improvements
parents
6f69b4d6
19593467
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
358 additions
and
174 deletions
+358
-174
account_manager.go
accounts/account_manager.go
+74
-71
accounts_test.go
accounts/accounts_test.go
+43
-1
js_test.go
cmd/geth/js_test.go
+4
-6
main.go
cmd/geth/main.go
+81
-23
flags.go
cmd/utils/flags.go
+1
-1
crypto.go
crypto/crypto.go
+1
-1
key_store_passphrase.go
crypto/key_store_passphrase.go
+26
-27
key_store_plain.go
crypto/key_store_plain.go
+122
-33
backend.go
eth/backend.go
+2
-10
xeth.go
xeth/xeth.go
+4
-1
No files found.
accounts/account_manager.go
View file @
9bb575be
...
@@ -26,7 +26,7 @@ This abstracts part of a user's interaction with an account she controls.
...
@@ -26,7 +26,7 @@ This abstracts part of a user's interaction with an account she controls.
It's not an abstraction of core Ethereum accounts data type / logic -
It's not an abstraction of core Ethereum accounts data type / logic -
for that see the core processing code of blocks / txs.
for that see the core processing code of blocks / txs.
Currently this is pretty much a passthrough to the KeyStore
2
interface,
Currently this is pretty much a passthrough to the KeyStore interface,
and accounts persistence is derived from stored keys' addresses
and accounts persistence is derived from stored keys' addresses
*/
*/
...
@@ -36,6 +36,7 @@ import (
...
@@ -36,6 +36,7 @@ import (
"crypto/ecdsa"
"crypto/ecdsa"
crand
"crypto/rand"
crand
"crypto/rand"
"errors"
"errors"
"fmt"
"os"
"os"
"sync"
"sync"
"time"
"time"
...
@@ -49,17 +50,12 @@ var (
...
@@ -49,17 +50,12 @@ var (
ErrNoKeys
=
errors
.
New
(
"no keys in store"
)
ErrNoKeys
=
errors
.
New
(
"no keys in store"
)
)
)
const
(
// Default unlock duration (in seconds) when an account is unlocked from the console
DefaultAccountUnlockDuration
=
300
)
type
Account
struct
{
type
Account
struct
{
Address
common
.
Address
Address
common
.
Address
}
}
type
Manager
struct
{
type
Manager
struct
{
keyStore
crypto
.
KeyStore
2
keyStore
crypto
.
KeyStore
unlocked
map
[
common
.
Address
]
*
unlocked
unlocked
map
[
common
.
Address
]
*
unlocked
mutex
sync
.
RWMutex
mutex
sync
.
RWMutex
}
}
...
@@ -69,7 +65,7 @@ type unlocked struct {
...
@@ -69,7 +65,7 @@ type unlocked struct {
abort
chan
struct
{}
abort
chan
struct
{}
}
}
func
NewManager
(
keyStore
crypto
.
KeyStore
2
)
*
Manager
{
func
NewManager
(
keyStore
crypto
.
KeyStore
)
*
Manager
{
return
&
Manager
{
return
&
Manager
{
keyStore
:
keyStore
,
keyStore
:
keyStore
,
unlocked
:
make
(
map
[
common
.
Address
]
*
unlocked
),
unlocked
:
make
(
map
[
common
.
Address
]
*
unlocked
),
...
@@ -86,19 +82,6 @@ func (am *Manager) HasAccount(addr common.Address) bool {
...
@@ -86,19 +82,6 @@ func (am *Manager) HasAccount(addr common.Address) bool {
return
false
return
false
}
}
func
(
am
*
Manager
)
Primary
()
(
addr
common
.
Address
,
err
error
)
{
addrs
,
err
:=
am
.
keyStore
.
GetKeyAddresses
()
if
os
.
IsNotExist
(
err
)
{
return
common
.
Address
{},
ErrNoKeys
}
else
if
err
!=
nil
{
return
common
.
Address
{},
err
}
if
len
(
addrs
)
==
0
{
return
common
.
Address
{},
ErrNoKeys
}
return
addrs
[
0
],
nil
}
func
(
am
*
Manager
)
DeleteAccount
(
address
common
.
Address
,
auth
string
)
error
{
func
(
am
*
Manager
)
DeleteAccount
(
address
common
.
Address
,
auth
string
)
error
{
return
am
.
keyStore
.
DeleteKey
(
address
,
auth
)
return
am
.
keyStore
.
DeleteKey
(
address
,
auth
)
}
}
...
@@ -114,28 +97,58 @@ func (am *Manager) Sign(a Account, toSign []byte) (signature []byte, err error)
...
@@ -114,28 +97,58 @@ func (am *Manager) Sign(a Account, toSign []byte) (signature []byte, err error)
return
signature
,
err
return
signature
,
err
}
}
// TimedUnlock unlocks the account with the given address.
// unlock indefinitely
// When timeout has passed, the account will be locked again.
func
(
am
*
Manager
)
Unlock
(
addr
common
.
Address
,
keyAuth
string
)
error
{
return
am
.
TimedUnlock
(
addr
,
keyAuth
,
0
)
}
// Unlock unlocks the account with the given address. The account
// stays unlocked for the duration of timeout
// it timeout is 0 the account is unlocked for the entire session
func
(
am
*
Manager
)
TimedUnlock
(
addr
common
.
Address
,
keyAuth
string
,
timeout
time
.
Duration
)
error
{
func
(
am
*
Manager
)
TimedUnlock
(
addr
common
.
Address
,
keyAuth
string
,
timeout
time
.
Duration
)
error
{
key
,
err
:=
am
.
keyStore
.
GetKey
(
addr
,
keyAuth
)
key
,
err
:=
am
.
keyStore
.
GetKey
(
addr
,
keyAuth
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
u
:=
am
.
addUnlocked
(
addr
,
key
)
var
u
*
unlocked
go
am
.
dropLater
(
addr
,
u
,
timeout
)
am
.
mutex
.
Lock
()
defer
am
.
mutex
.
Unlock
()
var
found
bool
u
,
found
=
am
.
unlocked
[
addr
]
if
found
{
// terminate dropLater for this key to avoid unexpected drops.
if
u
.
abort
!=
nil
{
close
(
u
.
abort
)
}
}
if
timeout
>
0
{
u
=
&
unlocked
{
Key
:
key
,
abort
:
make
(
chan
struct
{})}
go
am
.
expire
(
addr
,
u
,
timeout
)
}
else
{
u
=
&
unlocked
{
Key
:
key
}
}
am
.
unlocked
[
addr
]
=
u
return
nil
return
nil
}
}
// Unlock unlocks the account with the given address. The account
func
(
am
*
Manager
)
expire
(
addr
common
.
Address
,
u
*
unlocked
,
timeout
time
.
Duration
)
{
// stays unlocked until the program exits or until a TimedUnlock
t
:=
time
.
NewTimer
(
timeout
)
// timeout (started after the call to Unlock) expires.
defer
t
.
Stop
()
func
(
am
*
Manager
)
Unlock
(
addr
common
.
Address
,
keyAuth
string
)
error
{
select
{
key
,
err
:=
am
.
keyStore
.
GetKey
(
addr
,
keyAuth
)
case
<-
u
.
abort
:
if
err
!=
nil
{
// just quit
return
err
case
<-
t
.
C
:
am
.
mutex
.
Lock
()
// only drop if it's still the same key instance that dropLater
// was launched with. we can check that using pointer equality
// because the map stores a new pointer every time the key is
// unlocked.
if
am
.
unlocked
[
addr
]
==
u
{
zeroKey
(
u
.
PrivateKey
)
delete
(
am
.
unlocked
,
addr
)
}
am
.
mutex
.
Unlock
()
}
}
am
.
addUnlocked
(
addr
,
key
)
return
nil
}
}
func
(
am
*
Manager
)
NewAccount
(
auth
string
)
(
Account
,
error
)
{
func
(
am
*
Manager
)
NewAccount
(
auth
string
)
(
Account
,
error
)
{
...
@@ -146,6 +159,20 @@ func (am *Manager) NewAccount(auth string) (Account, error) {
...
@@ -146,6 +159,20 @@ func (am *Manager) NewAccount(auth string) (Account, error) {
return
Account
{
Address
:
key
.
Address
},
nil
return
Account
{
Address
:
key
.
Address
},
nil
}
}
func
(
am
*
Manager
)
AddressByIndex
(
index
int
)
(
addr
string
,
err
error
)
{
var
addrs
[]
common
.
Address
addrs
,
err
=
am
.
keyStore
.
GetKeyAddresses
()
if
err
!=
nil
{
return
}
if
index
<
0
||
index
>=
len
(
addrs
)
{
err
=
fmt
.
Errorf
(
"index out of range: %d (should be 0-%d)"
,
index
,
len
(
addrs
)
-
1
)
}
else
{
addr
=
addrs
[
index
]
.
Hex
()
}
return
}
func
(
am
*
Manager
)
Accounts
()
([]
Account
,
error
)
{
func
(
am
*
Manager
)
Accounts
()
([]
Account
,
error
)
{
addresses
,
err
:=
am
.
keyStore
.
GetKeyAddresses
()
addresses
,
err
:=
am
.
keyStore
.
GetKeyAddresses
()
if
os
.
IsNotExist
(
err
)
{
if
os
.
IsNotExist
(
err
)
{
...
@@ -162,43 +189,6 @@ func (am *Manager) Accounts() ([]Account, error) {
...
@@ -162,43 +189,6 @@ func (am *Manager) Accounts() ([]Account, error) {
return
accounts
,
err
return
accounts
,
err
}
}
func
(
am
*
Manager
)
addUnlocked
(
addr
common
.
Address
,
key
*
crypto
.
Key
)
*
unlocked
{
u
:=
&
unlocked
{
Key
:
key
,
abort
:
make
(
chan
struct
{})}
am
.
mutex
.
Lock
()
prev
,
found
:=
am
.
unlocked
[
addr
]
if
found
{
// terminate dropLater for this key to avoid unexpected drops.
close
(
prev
.
abort
)
// the key is zeroed here instead of in dropLater because
// there might not actually be a dropLater running for this
// key, i.e. when Unlock was used.
zeroKey
(
prev
.
PrivateKey
)
}
am
.
unlocked
[
addr
]
=
u
am
.
mutex
.
Unlock
()
return
u
}
func
(
am
*
Manager
)
dropLater
(
addr
common
.
Address
,
u
*
unlocked
,
timeout
time
.
Duration
)
{
t
:=
time
.
NewTimer
(
timeout
)
defer
t
.
Stop
()
select
{
case
<-
u
.
abort
:
// just quit
case
<-
t
.
C
:
am
.
mutex
.
Lock
()
// only drop if it's still the same key instance that dropLater
// was launched with. we can check that using pointer equality
// because the map stores a new pointer every time the key is
// unlocked.
if
am
.
unlocked
[
addr
]
==
u
{
zeroKey
(
u
.
PrivateKey
)
delete
(
am
.
unlocked
,
addr
)
}
am
.
mutex
.
Unlock
()
}
}
// zeroKey zeroes a private key in memory.
// zeroKey zeroes a private key in memory.
func
zeroKey
(
k
*
ecdsa
.
PrivateKey
)
{
func
zeroKey
(
k
*
ecdsa
.
PrivateKey
)
{
b
:=
k
.
D
.
Bits
()
b
:=
k
.
D
.
Bits
()
...
@@ -229,6 +219,19 @@ func (am *Manager) Import(path string, keyAuth string) (Account, error) {
...
@@ -229,6 +219,19 @@ func (am *Manager) Import(path string, keyAuth string) (Account, error) {
return
Account
{
Address
:
key
.
Address
},
nil
return
Account
{
Address
:
key
.
Address
},
nil
}
}
func
(
am
*
Manager
)
Update
(
addr
common
.
Address
,
authFrom
,
authTo
string
)
(
err
error
)
{
var
key
*
crypto
.
Key
key
,
err
=
am
.
keyStore
.
GetKey
(
addr
,
authFrom
)
if
err
==
nil
{
err
=
am
.
keyStore
.
StoreKey
(
key
,
authTo
)
if
err
==
nil
{
am
.
keyStore
.
Cleanup
(
addr
)
}
}
return
}
func
(
am
*
Manager
)
ImportPreSaleKey
(
keyJSON
[]
byte
,
password
string
)
(
acc
Account
,
err
error
)
{
func
(
am
*
Manager
)
ImportPreSaleKey
(
keyJSON
[]
byte
,
password
string
)
(
acc
Account
,
err
error
)
{
var
key
*
crypto
.
Key
var
key
*
crypto
.
Key
key
,
err
=
crypto
.
ImportPreSaleKey
(
am
.
keyStore
,
keyJSON
,
password
)
key
,
err
=
crypto
.
ImportPreSaleKey
(
am
.
keyStore
,
keyJSON
,
password
)
...
...
accounts/accounts_test.go
View file @
9bb575be
...
@@ -52,6 +52,46 @@ func TestTimedUnlock(t *testing.T) {
...
@@ -52,6 +52,46 @@ func TestTimedUnlock(t *testing.T) {
t
.
Fatal
(
"Signing shouldn't return an error after unlocking, got "
,
err
)
t
.
Fatal
(
"Signing shouldn't return an error after unlocking, got "
,
err
)
}
}
// Signing fails again after automatic locking
time
.
Sleep
(
150
*
time
.
Millisecond
)
_
,
err
=
am
.
Sign
(
a1
,
toSign
)
if
err
!=
ErrLocked
{
t
.
Fatal
(
"Signing should've failed with ErrLocked timeout expired, got "
,
err
)
}
}
func
TestOverrideUnlock
(
t
*
testing
.
T
)
{
dir
,
ks
:=
tmpKeyStore
(
t
,
crypto
.
NewKeyStorePassphrase
)
defer
os
.
RemoveAll
(
dir
)
am
:=
NewManager
(
ks
)
pass
:=
"foo"
a1
,
err
:=
am
.
NewAccount
(
pass
)
toSign
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
// Unlock indefinitely
if
err
=
am
.
Unlock
(
a1
.
Address
,
pass
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
// Signing without passphrase works because account is temp unlocked
_
,
err
=
am
.
Sign
(
a1
,
toSign
)
if
err
!=
nil
{
t
.
Fatal
(
"Signing shouldn't return an error after unlocking, got "
,
err
)
}
// reset unlock to a shorter period, invalidates the previous unlock
if
err
=
am
.
TimedUnlock
(
a1
.
Address
,
pass
,
100
*
time
.
Millisecond
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
// Signing without passphrase still works because account is temp unlocked
_
,
err
=
am
.
Sign
(
a1
,
toSign
)
if
err
!=
nil
{
t
.
Fatal
(
"Signing shouldn't return an error after unlocking, got "
,
err
)
}
// Signing fails again after automatic locking
// Signing fails again after automatic locking
time
.
Sleep
(
150
*
time
.
Millisecond
)
time
.
Sleep
(
150
*
time
.
Millisecond
)
_
,
err
=
am
.
Sign
(
a1
,
toSign
)
_
,
err
=
am
.
Sign
(
a1
,
toSign
)
...
@@ -60,7 +100,9 @@ func TestTimedUnlock(t *testing.T) {
...
@@ -60,7 +100,9 @@ func TestTimedUnlock(t *testing.T) {
}
}
}
}
func
tmpKeyStore
(
t
*
testing
.
T
,
new
func
(
string
)
crypto
.
KeyStore2
)
(
string
,
crypto
.
KeyStore2
)
{
//
func
tmpKeyStore
(
t
*
testing
.
T
,
new
func
(
string
)
crypto
.
KeyStore
)
(
string
,
crypto
.
KeyStore
)
{
d
,
err
:=
ioutil
.
TempDir
(
""
,
"eth-keystore-test"
)
d
,
err
:=
ioutil
.
TempDir
(
""
,
"eth-keystore-test"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
...
cmd/geth/js_test.go
View file @
9bb575be
...
@@ -20,8 +20,8 @@ import (
...
@@ -20,8 +20,8 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
)
)
const
(
const
(
...
@@ -127,6 +127,7 @@ func TestNodeInfo(t *testing.T) {
...
@@ -127,6 +127,7 @@ func TestNodeInfo(t *testing.T) {
}
}
defer
ethereum
.
Stop
()
defer
ethereum
.
Stop
()
defer
os
.
RemoveAll
(
tmp
)
defer
os
.
RemoveAll
(
tmp
)
want
:=
`{"DiscPort":0,"IP":"0.0.0.0","ListenAddr":"","Name":"test","NodeID":"4cb2fc32924e94277bf94b5e4c983beedb2eabd5a0bc941db32202735c6625d020ca14a5963d1738af43b6ac0a711d61b1a06de931a499fe2aa0b1a132a902b5","NodeUrl":"enode://4cb2fc32924e94277bf94b5e4c983beedb2eabd5a0bc941db32202735c6625d020ca14a5963d1738af43b6ac0a711d61b1a06de931a499fe2aa0b1a132a902b5@0.0.0.0:0","TCPPort":0,"Td":"131072"}`
want
:=
`{"DiscPort":0,"IP":"0.0.0.0","ListenAddr":"","Name":"test","NodeID":"4cb2fc32924e94277bf94b5e4c983beedb2eabd5a0bc941db32202735c6625d020ca14a5963d1738af43b6ac0a711d61b1a06de931a499fe2aa0b1a132a902b5","NodeUrl":"enode://4cb2fc32924e94277bf94b5e4c983beedb2eabd5a0bc941db32202735c6625d020ca14a5963d1738af43b6ac0a711d61b1a06de931a499fe2aa0b1a132a902b5@0.0.0.0:0","TCPPort":0,"Td":"131072"}`
checkEvalJSON
(
t
,
repl
,
`admin.nodeInfo`
,
want
)
checkEvalJSON
(
t
,
repl
,
`admin.nodeInfo`
,
want
)
}
}
...
@@ -140,8 +141,7 @@ func TestAccounts(t *testing.T) {
...
@@ -140,8 +141,7 @@ func TestAccounts(t *testing.T) {
defer
os
.
RemoveAll
(
tmp
)
defer
os
.
RemoveAll
(
tmp
)
checkEvalJSON
(
t
,
repl
,
`eth.accounts`
,
`["`
+
testAddress
+
`"]`
)
checkEvalJSON
(
t
,
repl
,
`eth.accounts`
,
`["`
+
testAddress
+
`"]`
)
checkEvalJSON
(
t
,
repl
,
`eth.coinbase`
,
`"`
+
testAddress
+
`"`
)
checkEvalJSON
(
t
,
repl
,
`eth.coinbase`
,
`null`
)
val
,
err
:=
repl
.
re
.
Run
(
`personal.newAccount("password")`
)
val
,
err
:=
repl
.
re
.
Run
(
`personal.newAccount("password")`
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"expected no error, got %v"
,
err
)
t
.
Errorf
(
"expected no error, got %v"
,
err
)
...
@@ -151,9 +151,7 @@ func TestAccounts(t *testing.T) {
...
@@ -151,9 +151,7 @@ func TestAccounts(t *testing.T) {
t
.
Errorf
(
"address not hex: %q"
,
addr
)
t
.
Errorf
(
"address not hex: %q"
,
addr
)
}
}
// skip until order fixed #824
checkEvalJSON
(
t
,
repl
,
`eth.accounts`
,
`["`
+
testAddress
+
`","`
+
addr
+
`"]`
)
// checkEvalJSON(t, repl, `eth.accounts`, `["`+testAddress+`", "`+addr+`"]`)
// checkEvalJSON(t, repl, `eth.coinbase`, `"`+testAddress+`"`)
}
}
func
TestBlockChain
(
t
*
testing
.
T
)
{
func
TestBlockChain
(
t
*
testing
.
T
)
{
...
...
cmd/geth/main.go
View file @
9bb575be
...
@@ -153,9 +153,12 @@ Note that exporting your key in unencrypted format is NOT supported.
...
@@ -153,9 +153,12 @@ Note that exporting your key in unencrypted format is NOT supported.
Keys are stored under <DATADIR>/keys.
Keys are stored under <DATADIR>/keys.
It is safe to transfer the entire directory or the individual keys therein
It is safe to transfer the entire directory or the individual keys therein
between ethereum nodes.
between ethereum nodes
by simply copying
.
Make sure you backup your keys regularly.
Make sure you backup your keys regularly.
In order to use your account to send transactions, you need to unlock them using the
'--unlock' option. The argument is a comma
And finally. DO NOT FORGET YOUR PASSWORD.
And finally. DO NOT FORGET YOUR PASSWORD.
`
,
`
,
Subcommands
:
[]
cli
.
Command
{
Subcommands
:
[]
cli
.
Command
{
...
@@ -186,6 +189,33 @@ Note, this is meant to be used for testing only, it is a bad idea to save your
...
@@ -186,6 +189,33 @@ 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.
password to file or expose in any other way.
`
,
`
,
},
},
{
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.
`
,
},
{
{
Action
:
accountImport
,
Action
:
accountImport
,
Name
:
"import"
,
Name
:
"import"
,
...
@@ -430,19 +460,30 @@ func execJSFiles(ctx *cli.Context) {
...
@@ -430,19 +460,30 @@ func execJSFiles(ctx *cli.Context) {
ethereum
.
WaitForShutdown
()
ethereum
.
WaitForShutdown
()
}
}
func
unlockAccount
(
ctx
*
cli
.
Context
,
am
*
accounts
.
Manager
,
a
ccount
string
)
(
passphrase
string
)
{
func
unlockAccount
(
ctx
*
cli
.
Context
,
am
*
accounts
.
Manager
,
a
ddr
string
,
i
int
)
(
addrHex
,
auth
string
)
{
var
err
error
var
err
error
// Load startup keys. XXX we are going to need a different format
// Load startup keys. XXX we are going to need a different format
if
!
((
len
(
account
)
==
40
)
||
(
len
(
account
)
==
42
))
{
// with or without 0x
if
!
((
len
(
addr
)
==
40
)
||
(
len
(
addr
)
==
42
))
{
// with or without 0x
utils
.
Fatalf
(
"Invalid account address '%s'"
,
account
)
var
index
int
index
,
err
=
strconv
.
Atoi
(
addr
)
if
err
!=
nil
{
utils
.
Fatalf
(
"Invalid account address '%s'"
,
addr
)
}
addrHex
,
err
=
am
.
AddressByIndex
(
index
)
if
err
!=
nil
{
utils
.
Fatalf
(
"%v"
,
err
)
}
}
else
{
addrHex
=
addr
}
}
// Attempt to unlock the account 3 times
// Attempt to unlock the account 3 times
attempts
:=
3
attempts
:=
3
for
tries
:=
0
;
tries
<
attempts
;
tries
++
{
for
tries
:=
0
;
tries
<
attempts
;
tries
++
{
msg
:=
fmt
.
Sprintf
(
"Unlocking account %s | Attempt %d/%d"
,
a
ccount
,
tries
+
1
,
attempts
)
msg
:=
fmt
.
Sprintf
(
"Unlocking account %s | Attempt %d/%d"
,
a
ddr
,
tries
+
1
,
attempts
)
passphrase
=
getPassPhrase
(
ctx
,
msg
,
false
)
auth
=
getPassPhrase
(
ctx
,
msg
,
false
,
i
)
err
=
am
.
Unlock
(
common
.
HexToAddress
(
a
ccount
),
passphrase
)
err
=
am
.
Unlock
(
common
.
HexToAddress
(
a
ddrHex
),
auth
)
if
err
==
nil
{
if
err
==
nil
{
break
break
}
}
...
@@ -450,7 +491,7 @@ func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (pass
...
@@ -450,7 +491,7 @@ func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (pass
if
err
!=
nil
{
if
err
!=
nil
{
utils
.
Fatalf
(
"Unlock account failed '%v'"
,
err
)
utils
.
Fatalf
(
"Unlock account failed '%v'"
,
err
)
}
}
fmt
.
Printf
(
"Account '%s' unlocked.
\n
"
,
a
ccount
)
fmt
.
Printf
(
"Account '%s' unlocked.
\n
"
,
a
ddr
)
return
return
}
}
...
@@ -492,16 +533,12 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) {
...
@@ -492,16 +533,12 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) {
account
:=
ctx
.
GlobalString
(
utils
.
UnlockedAccountFlag
.
Name
)
account
:=
ctx
.
GlobalString
(
utils
.
UnlockedAccountFlag
.
Name
)
accounts
:=
strings
.
Split
(
account
,
" "
)
accounts
:=
strings
.
Split
(
account
,
" "
)
for
_
,
account
:=
range
accounts
{
for
i
,
account
:=
range
accounts
{
if
len
(
account
)
>
0
{
if
len
(
account
)
>
0
{
if
account
==
"primary"
{
if
account
==
"primary"
{
primaryAcc
,
err
:=
am
.
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."
)
if
err
!=
nil
{
utils
.
Fatalf
(
"no primary account: %v"
,
err
)
}
account
=
primaryAcc
.
Hex
()
}
}
unlockAccount
(
ctx
,
am
,
account
)
unlockAccount
(
ctx
,
am
,
account
,
i
)
}
}
}
}
// Start auxiliary services if enabled.
// Start auxiliary services if enabled.
...
@@ -528,14 +565,12 @@ func accountList(ctx *cli.Context) {
...
@@ -528,14 +565,12 @@ func accountList(ctx *cli.Context) {
if
err
!=
nil
{
if
err
!=
nil
{
utils
.
Fatalf
(
"Could not list accounts: %v"
,
err
)
utils
.
Fatalf
(
"Could not list accounts: %v"
,
err
)
}
}
name
:=
"Primary"
for
i
,
acct
:=
range
accts
{
for
i
,
acct
:=
range
accts
{
fmt
.
Printf
(
"%s #%d: %x
\n
"
,
name
,
i
,
acct
)
fmt
.
Printf
(
"Account #%d: %x
\n
"
,
i
,
acct
)
name
=
"Account"
}
}
}
}
func
getPassPhrase
(
ctx
*
cli
.
Context
,
desc
string
,
confirmation
bool
)
(
passphrase
string
)
{
func
getPassPhrase
(
ctx
*
cli
.
Context
,
desc
string
,
confirmation
bool
,
i
int
)
(
passphrase
string
)
{
passfile
:=
ctx
.
GlobalString
(
utils
.
PasswordFileFlag
.
Name
)
passfile
:=
ctx
.
GlobalString
(
utils
.
PasswordFileFlag
.
Name
)
if
len
(
passfile
)
==
0
{
if
len
(
passfile
)
==
0
{
fmt
.
Println
(
desc
)
fmt
.
Println
(
desc
)
...
@@ -559,14 +594,22 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase
...
@@ -559,14 +594,22 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase
if
err
!=
nil
{
if
err
!=
nil
{
utils
.
Fatalf
(
"Unable to read password file '%s': %v"
,
passfile
,
err
)
utils
.
Fatalf
(
"Unable to read password file '%s': %v"
,
passfile
,
err
)
}
}
passphrase
=
string
(
passbytes
)
// 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
]
}
}
}
return
return
}
}
func
accountCreate
(
ctx
*
cli
.
Context
)
{
func
accountCreate
(
ctx
*
cli
.
Context
)
{
am
:=
utils
.
MakeAccountManager
(
ctx
)
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
)
passphrase
:=
getPassPhrase
(
ctx
,
"Your new account is locked with a password. Please give a password. Do not forget this password."
,
true
,
0
)
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
)
...
@@ -574,6 +617,21 @@ func accountCreate(ctx *cli.Context) {
...
@@ -574,6 +617,21 @@ func accountCreate(ctx *cli.Context) {
fmt
.
Printf
(
"Address: %x
\n
"
,
acct
)
fmt
.
Printf
(
"Address: %x
\n
"
,
acct
)
}
}
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
)
}
}
func
importWallet
(
ctx
*
cli
.
Context
)
{
func
importWallet
(
ctx
*
cli
.
Context
)
{
keyfile
:=
ctx
.
Args
()
.
First
()
keyfile
:=
ctx
.
Args
()
.
First
()
if
len
(
keyfile
)
==
0
{
if
len
(
keyfile
)
==
0
{
...
@@ -585,7 +643,7 @@ func importWallet(ctx *cli.Context) {
...
@@ -585,7 +643,7 @@ func importWallet(ctx *cli.Context) {
}
}
am
:=
utils
.
MakeAccountManager
(
ctx
)
am
:=
utils
.
MakeAccountManager
(
ctx
)
passphrase
:=
getPassPhrase
(
ctx
,
""
,
false
)
passphrase
:=
getPassPhrase
(
ctx
,
""
,
false
,
0
)
acct
,
err
:=
am
.
ImportPreSaleKey
(
keyJson
,
passphrase
)
acct
,
err
:=
am
.
ImportPreSaleKey
(
keyJson
,
passphrase
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -600,7 +658,7 @@ func accountImport(ctx *cli.Context) {
...
@@ -600,7 +658,7 @@ func accountImport(ctx *cli.Context) {
utils
.
Fatalf
(
"keyfile must be given as argument"
)
utils
.
Fatalf
(
"keyfile must be given as argument"
)
}
}
am
:=
utils
.
MakeAccountManager
(
ctx
)
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
)
passphrase
:=
getPassPhrase
(
ctx
,
"Your new account is locked with a password. Please give a password. Do not forget this password."
,
true
,
0
)
acct
,
err
:=
am
.
Import
(
keyfile
,
passphrase
)
acct
,
err
:=
am
.
Import
(
keyfile
,
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
)
...
...
cmd/utils/flags.go
View file @
9bb575be
...
@@ -133,7 +133,7 @@ var (
...
@@ -133,7 +133,7 @@ var (
UnlockedAccountFlag
=
cli
.
StringFlag
{
UnlockedAccountFlag
=
cli
.
StringFlag
{
Name
:
"unlock"
,
Name
:
"unlock"
,
Usage
:
"Unlock the account given until this program exits (prompts for password). '--unlock
primary' unlocks the primary account
"
,
Usage
:
"Unlock the account given until this program exits (prompts for password). '--unlock
n' unlocks the n-th account in order or creation.
"
,
Value
:
""
,
Value
:
""
,
}
}
PasswordFileFlag
=
cli
.
StringFlag
{
PasswordFileFlag
=
cli
.
StringFlag
{
...
...
crypto/crypto.go
View file @
9bb575be
...
@@ -209,7 +209,7 @@ func ImportBlockTestKey(privKeyBytes []byte) error {
...
@@ -209,7 +209,7 @@ func ImportBlockTestKey(privKeyBytes []byte) error {
}
}
// creates a Key and stores that in the given KeyStore by decrypting a presale key JSON
// creates a Key and stores that in the given KeyStore by decrypting a presale key JSON
func
ImportPreSaleKey
(
keyStore
KeyStore
2
,
keyJSON
[]
byte
,
password
string
)
(
*
Key
,
error
)
{
func
ImportPreSaleKey
(
keyStore
KeyStore
,
keyJSON
[]
byte
,
password
string
)
(
*
Key
,
error
)
{
key
,
err
:=
decryptPreSaleKey
(
keyJSON
,
password
)
key
,
err
:=
decryptPreSaleKey
(
keyJSON
,
password
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
crypto/key_store_passphrase.go
View file @
9bb575be
...
@@ -41,8 +41,6 @@ import (
...
@@ -41,8 +41,6 @@ import (
"errors"
"errors"
"fmt"
"fmt"
"io"
"io"
"os"
"path/filepath"
"reflect"
"reflect"
"code.google.com/p/go-uuid/uuid"
"code.google.com/p/go-uuid/uuid"
...
@@ -65,7 +63,7 @@ type keyStorePassphrase struct {
...
@@ -65,7 +63,7 @@ type keyStorePassphrase struct {
keysDirPath
string
keysDirPath
string
}
}
func
NewKeyStorePassphrase
(
path
string
)
KeyStore
2
{
func
NewKeyStorePassphrase
(
path
string
)
KeyStore
{
return
&
keyStorePassphrase
{
path
}
return
&
keyStorePassphrase
{
path
}
}
}
...
@@ -74,20 +72,23 @@ func (ks keyStorePassphrase) GenerateNewKey(rand io.Reader, auth string) (key *K
...
@@ -74,20 +72,23 @@ func (ks keyStorePassphrase) GenerateNewKey(rand io.Reader, auth string) (key *K
}
}
func
(
ks
keyStorePassphrase
)
GetKey
(
keyAddr
common
.
Address
,
auth
string
)
(
key
*
Key
,
err
error
)
{
func
(
ks
keyStorePassphrase
)
GetKey
(
keyAddr
common
.
Address
,
auth
string
)
(
key
*
Key
,
err
error
)
{
keyBytes
,
keyId
,
err
:=
DecryptKeyFromFile
(
ks
,
keyAddr
,
auth
)
keyBytes
,
keyId
,
err
:=
decryptKeyFromFile
(
ks
.
keysDirPath
,
keyAddr
,
auth
)
if
err
!=
nil
{
if
err
==
nil
{
return
nil
,
err
key
=
&
Key
{
}
Id
:
uuid
.
UUID
(
keyId
),
key
=
&
Key
{
Address
:
keyAddr
,
Id
:
uuid
.
UUID
(
keyId
),
PrivateKey
:
ToECDSA
(
keyBytes
),
Address
:
keyAddr
,
}
PrivateKey
:
ToECDSA
(
keyBytes
),
}
}
return
key
,
err
return
}
func
(
ks
keyStorePassphrase
)
Cleanup
(
keyAddr
common
.
Address
)
(
err
error
)
{
return
cleanup
(
ks
.
keysDirPath
,
keyAddr
)
}
}
func
(
ks
keyStorePassphrase
)
GetKeyAddresses
()
(
addresses
[]
common
.
Address
,
err
error
)
{
func
(
ks
keyStorePassphrase
)
GetKeyAddresses
()
(
addresses
[]
common
.
Address
,
err
error
)
{
return
G
etKeyAddresses
(
ks
.
keysDirPath
)
return
g
etKeyAddresses
(
ks
.
keysDirPath
)
}
}
func
(
ks
keyStorePassphrase
)
StoreKey
(
key
*
Key
,
auth
string
)
(
err
error
)
{
func
(
ks
keyStorePassphrase
)
StoreKey
(
key
*
Key
,
auth
string
)
(
err
error
)
{
...
@@ -139,42 +140,40 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) {
...
@@ -139,42 +140,40 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) {
return
err
return
err
}
}
return
W
riteKeyFile
(
key
.
Address
,
ks
.
keysDirPath
,
keyJSON
)
return
w
riteKeyFile
(
key
.
Address
,
ks
.
keysDirPath
,
keyJSON
)
}
}
func
(
ks
keyStorePassphrase
)
DeleteKey
(
keyAddr
common
.
Address
,
auth
string
)
(
err
error
)
{
func
(
ks
keyStorePassphrase
)
DeleteKey
(
keyAddr
common
.
Address
,
auth
string
)
(
err
error
)
{
// only delete if correct passphrase is given
// only delete if correct passphrase is given
_
,
_
,
err
=
DecryptKeyFromFile
(
ks
,
keyAddr
,
auth
)
_
,
_
,
err
=
decryptKeyFromFile
(
ks
.
keysDirPath
,
keyAddr
,
auth
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
keyDirPath
:=
filepath
.
Join
(
ks
.
keysDirPath
,
hex
.
EncodeToString
(
keyAddr
[
:
]))
return
deleteKey
(
ks
.
keysDirPath
,
keyAddr
)
return
os
.
RemoveAll
(
keyDirPath
)
}
}
func
DecryptKeyFromFile
(
ks
keyStorePassphrase
,
keyAddr
common
.
Address
,
auth
string
)
(
keyBytes
[]
byte
,
keyId
[]
byte
,
err
error
)
{
func
decryptKeyFromFile
(
keysDirPath
string
,
keyAddr
common
.
Address
,
auth
string
)
(
keyBytes
[]
byte
,
keyId
[]
byte
,
err
error
)
{
fileContent
,
err
:=
GetKeyFile
(
ks
.
keysDirPath
,
keyAddr
)
fmt
.
Printf
(
"%v
\n
"
,
keyAddr
.
Hex
())
m
:=
make
(
map
[
string
]
interface
{})
err
=
getKey
(
keysDirPath
,
keyAddr
,
&
m
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
}
}
m
:=
make
(
map
[
string
]
interface
{})
err
=
json
.
Unmarshal
(
fileContent
,
&
m
)
v
:=
reflect
.
ValueOf
(
m
[
"version"
])
v
:=
reflect
.
ValueOf
(
m
[
"version"
])
if
v
.
Kind
()
==
reflect
.
String
&&
v
.
String
()
==
"1"
{
if
v
.
Kind
()
==
reflect
.
String
&&
v
.
String
()
==
"1"
{
k
:=
new
(
encryptedKeyJSONV1
)
k
:=
new
(
encryptedKeyJSONV1
)
err
:=
json
.
Unmarshal
(
fileContent
,
k
)
err
=
getKey
(
keysDirPath
,
keyAddr
,
&
k
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
}
}
return
decryptKeyV1
(
k
,
auth
)
return
decryptKeyV1
(
k
,
auth
)
}
else
{
}
else
{
k
:=
new
(
encryptedKeyJSONV3
)
k
:=
new
(
encryptedKeyJSONV3
)
err
:=
json
.
Unmarshal
(
fileContent
,
k
)
err
=
getKey
(
keysDirPath
,
keyAddr
,
&
k
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
}
}
return
decryptKeyV3
(
k
,
auth
)
return
decryptKeyV3
(
k
,
auth
)
}
}
...
...
crypto/key_store_plain.go
View file @
9bb575be
...
@@ -27,28 +27,30 @@ import (
...
@@ -27,28 +27,30 @@ import (
"encoding/hex"
"encoding/hex"
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"github.com/ethereum/go-ethereum/common"
"io"
"io"
"io/ioutil"
"io/ioutil"
"os"
"os"
"path/filepath"
"path/filepath"
"time"
"github.com/ethereum/go-ethereum/common"
)
)
// TODO: rename to KeyStore when replacing existing KeyStore
type
KeyStore
interface
{
type
KeyStore2
interface
{
// create new key using io.Reader entropy source and optionally using auth string
// create new key using io.Reader entropy source and optionally using auth string
GenerateNewKey
(
io
.
Reader
,
string
)
(
*
Key
,
error
)
GenerateNewKey
(
io
.
Reader
,
string
)
(
*
Key
,
error
)
GetKey
(
common
.
Address
,
string
)
(
*
Key
,
error
)
// key from addr and auth string
GetKey
(
common
.
Address
,
string
)
(
*
Key
,
error
)
//
get
key from addr and auth string
GetKeyAddresses
()
([]
common
.
Address
,
error
)
// get all addresses
GetKeyAddresses
()
([]
common
.
Address
,
error
)
// get all addresses
StoreKey
(
*
Key
,
string
)
error
// store key optionally using auth string
StoreKey
(
*
Key
,
string
)
error
// store key optionally using auth string
DeleteKey
(
common
.
Address
,
string
)
error
// delete key by addr and auth string
DeleteKey
(
common
.
Address
,
string
)
error
// delete key by addr and auth string
Cleanup
(
keyAddr
common
.
Address
)
(
err
error
)
}
}
type
keyStorePlain
struct
{
type
keyStorePlain
struct
{
keysDirPath
string
keysDirPath
string
}
}
func
NewKeyStorePlain
(
path
string
)
KeyStore
2
{
func
NewKeyStorePlain
(
path
string
)
KeyStore
{
return
&
keyStorePlain
{
path
}
return
&
keyStorePlain
{
path
}
}
}
...
@@ -56,7 +58,7 @@ func (ks keyStorePlain) GenerateNewKey(rand io.Reader, auth string) (key *Key, e
...
@@ -56,7 +58,7 @@ func (ks keyStorePlain) GenerateNewKey(rand io.Reader, auth string) (key *Key, e
return
GenerateNewKeyDefault
(
ks
,
rand
,
auth
)
return
GenerateNewKeyDefault
(
ks
,
rand
,
auth
)
}
}
func
GenerateNewKeyDefault
(
ks
KeyStore
2
,
rand
io
.
Reader
,
auth
string
)
(
key
*
Key
,
err
error
)
{
func
GenerateNewKeyDefault
(
ks
KeyStore
,
rand
io
.
Reader
,
auth
string
)
(
key
*
Key
,
err
error
)
{
defer
func
()
{
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
if
r
:=
recover
();
r
!=
nil
{
err
=
fmt
.
Errorf
(
"GenerateNewKey error: %v"
,
r
)
err
=
fmt
.
Errorf
(
"GenerateNewKey error: %v"
,
r
)
...
@@ -68,62 +70,149 @@ func GenerateNewKeyDefault(ks KeyStore2, rand io.Reader, auth string) (key *Key,
...
@@ -68,62 +70,149 @@ func GenerateNewKeyDefault(ks KeyStore2, rand io.Reader, auth string) (key *Key,
}
}
func
(
ks
keyStorePlain
)
GetKey
(
keyAddr
common
.
Address
,
auth
string
)
(
key
*
Key
,
err
error
)
{
func
(
ks
keyStorePlain
)
GetKey
(
keyAddr
common
.
Address
,
auth
string
)
(
key
*
Key
,
err
error
)
{
fileContent
,
err
:=
GetKeyFile
(
ks
.
keysDirPath
,
keyAddr
)
key
=
new
(
Key
)
err
=
getKey
(
ks
.
keysDirPath
,
keyAddr
,
key
)
return
}
func
getKey
(
keysDirPath
string
,
keyAddr
common
.
Address
,
content
interface
{})
(
err
error
)
{
fileContent
,
err
:=
getKeyFile
(
keysDirPath
,
keyAddr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
}
}
return
json
.
Unmarshal
(
fileContent
,
content
)
key
=
new
(
Key
)
err
=
json
.
Unmarshal
(
fileContent
,
key
)
return
key
,
err
}
}
func
(
ks
keyStorePlain
)
GetKeyAddresses
()
(
addresses
[]
common
.
Address
,
err
error
)
{
func
(
ks
keyStorePlain
)
GetKeyAddresses
()
(
addresses
[]
common
.
Address
,
err
error
)
{
return
GetKeyAddresses
(
ks
.
keysDirPath
)
return
getKeyAddresses
(
ks
.
keysDirPath
)
}
func
(
ks
keyStorePlain
)
Cleanup
(
keyAddr
common
.
Address
)
(
err
error
)
{
return
cleanup
(
ks
.
keysDirPath
,
keyAddr
)
}
}
func
(
ks
keyStorePlain
)
StoreKey
(
key
*
Key
,
auth
string
)
(
err
error
)
{
func
(
ks
keyStorePlain
)
StoreKey
(
key
*
Key
,
auth
string
)
(
err
error
)
{
keyJSON
,
err
:=
json
.
Marshal
(
key
)
keyJSON
,
err
:=
json
.
Marshal
(
key
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
}
}
err
=
W
riteKeyFile
(
key
.
Address
,
ks
.
keysDirPath
,
keyJSON
)
err
=
w
riteKeyFile
(
key
.
Address
,
ks
.
keysDirPath
,
keyJSON
)
return
err
return
}
}
func
(
ks
keyStorePlain
)
DeleteKey
(
keyAddr
common
.
Address
,
auth
string
)
(
err
error
)
{
func
(
ks
keyStorePlain
)
DeleteKey
(
keyAddr
common
.
Address
,
auth
string
)
(
err
error
)
{
keyDirPath
:=
filepath
.
Join
(
ks
.
keysDirPath
,
keyAddr
.
Hex
())
return
deleteKey
(
ks
.
keysDirPath
,
keyAddr
)
err
=
os
.
RemoveAll
(
keyDirPath
)
return
err
}
}
func
GetKeyFile
(
keysDirPath
string
,
keyAddr
common
.
Address
)
(
fileContent
[]
byte
,
err
error
)
{
func
deleteKey
(
keysDirPath
string
,
keyAddr
common
.
Address
)
(
err
error
)
{
fileName
:=
hex
.
EncodeToString
(
keyAddr
[
:
])
var
path
string
return
ioutil
.
ReadFile
(
filepath
.
Join
(
keysDirPath
,
fileName
,
fileName
))
path
,
err
=
getKeyFilePath
(
keysDirPath
,
keyAddr
)
if
err
==
nil
{
addrHex
:=
hex
.
EncodeToString
(
keyAddr
[
:
])
if
path
==
filepath
.
Join
(
keysDirPath
,
addrHex
,
addrHex
)
{
path
=
filepath
.
Join
(
keysDirPath
,
addrHex
)
}
err
=
os
.
RemoveAll
(
path
)
}
return
}
func
getKeyFilePath
(
keysDirPath
string
,
keyAddr
common
.
Address
)
(
keyFilePath
string
,
err
error
)
{
addrHex
:=
hex
.
EncodeToString
(
keyAddr
[
:
])
matches
,
err
:=
filepath
.
Glob
(
filepath
.
Join
(
keysDirPath
,
fmt
.
Sprintf
(
"*--%s"
,
addrHex
)))
if
len
(
matches
)
>
0
{
if
err
==
nil
{
keyFilePath
=
matches
[
len
(
matches
)
-
1
]
}
return
}
keyFilePath
=
filepath
.
Join
(
keysDirPath
,
addrHex
,
addrHex
)
_
,
err
=
os
.
Stat
(
keyFilePath
)
return
}
}
func
WriteKeyFile
(
addr
common
.
Address
,
keysDirPath
string
,
content
[]
byte
)
(
err
error
)
{
func
cleanup
(
keysDirPath
string
,
keyAddr
common
.
Address
)
(
err
error
)
{
addrHex
:=
hex
.
EncodeToString
(
addr
[
:
])
fileInfos
,
err
:=
ioutil
.
ReadDir
(
keysDirPath
)
keyDirPath
:=
filepath
.
Join
(
keysDirPath
,
addrHex
)
if
err
!=
nil
{
keyFilePath
:=
filepath
.
Join
(
keyDirPath
,
addrHex
)
return
err
=
os
.
MkdirAll
(
keyDirPath
,
0700
)
// read, write and dir search for user
}
var
paths
[]
string
account
:=
hex
.
EncodeToString
(
keyAddr
[
:
])
for
_
,
fileInfo
:=
range
fileInfos
{
path
:=
filepath
.
Join
(
keysDirPath
,
fileInfo
.
Name
())
if
len
(
path
)
>=
40
{
addr
:=
path
[
len
(
path
)
-
40
:
len
(
path
)]
if
addr
==
account
{
if
path
==
filepath
.
Join
(
keysDirPath
,
addr
,
addr
)
{
path
=
filepath
.
Join
(
keysDirPath
,
addr
)
}
paths
=
append
(
paths
,
path
)
}
}
}
if
len
(
paths
)
>
1
{
for
i
:=
0
;
err
==
nil
&&
i
<
len
(
paths
)
-
1
;
i
++
{
err
=
os
.
RemoveAll
(
paths
[
i
])
if
err
!=
nil
{
break
}
}
}
return
}
func
getKeyFile
(
keysDirPath
string
,
keyAddr
common
.
Address
)
(
fileContent
[]
byte
,
err
error
)
{
var
keyFilePath
string
keyFilePath
,
err
=
getKeyFilePath
(
keysDirPath
,
keyAddr
)
if
err
==
nil
{
fileContent
,
err
=
ioutil
.
ReadFile
(
keyFilePath
)
}
return
}
func
writeKeyFile
(
addr
common
.
Address
,
keysDirPath
string
,
content
[]
byte
)
(
err
error
)
{
filename
:=
keyFileName
(
addr
)
// read, write and dir search for user
err
=
os
.
MkdirAll
(
keysDirPath
,
0700
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
return
ioutil
.
WriteFile
(
keyFilePath
,
content
,
0600
)
// read, write for user
// read, write for user
return
ioutil
.
WriteFile
(
filepath
.
Join
(
keysDirPath
,
filename
),
content
,
0600
)
}
// keyFilePath implements the naming convention for keyfiles:
// UTC--<created_at UTC ISO8601>-<address hex>
func
keyFileName
(
keyAddr
common
.
Address
)
string
{
ts
:=
time
.
Now
()
.
UTC
()
return
fmt
.
Sprintf
(
"UTC--%s--%s"
,
toISO8601
(
ts
),
hex
.
EncodeToString
(
keyAddr
[
:
]))
}
func
toISO8601
(
t
time
.
Time
)
string
{
var
tz
string
name
,
offset
:=
t
.
Zone
()
if
name
==
"UTC"
{
tz
=
"Z"
}
else
{
tz
=
fmt
.
Sprintf
(
"%03d00"
,
offset
/
3600
)
}
return
fmt
.
Sprintf
(
"%04d-%02d-%02dT%02d:%02d:%02d.%09d%s"
,
t
.
Year
(),
t
.
Month
(),
t
.
Day
(),
t
.
Hour
(),
t
.
Minute
(),
t
.
Second
(),
t
.
Nanosecond
(),
tz
)
}
}
func
G
etKeyAddresses
(
keysDirPath
string
)
(
addresses
[]
common
.
Address
,
err
error
)
{
func
g
etKeyAddresses
(
keysDirPath
string
)
(
addresses
[]
common
.
Address
,
err
error
)
{
fileInfos
,
err
:=
ioutil
.
ReadDir
(
keysDirPath
)
fileInfos
,
err
:=
ioutil
.
ReadDir
(
keysDirPath
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
for
_
,
fileInfo
:=
range
fileInfos
{
for
_
,
fileInfo
:=
range
fileInfos
{
address
,
err
:=
hex
.
DecodeString
(
fileInfo
.
Name
())
filename
:=
fileInfo
.
Name
()
if
err
!=
nil
{
if
len
(
filename
)
>=
40
{
continue
addr
:=
filename
[
len
(
filename
)
-
40
:
len
(
filename
)]
address
,
err
:=
hex
.
DecodeString
(
addr
)
if
err
==
nil
{
addresses
=
append
(
addresses
,
common
.
BytesToAddress
(
address
))
}
}
}
addresses
=
append
(
addresses
,
common
.
BytesToAddress
(
address
))
}
}
return
addresses
,
err
return
addresses
,
err
}
}
eth/backend.go
View file @
9bb575be
...
@@ -464,17 +464,9 @@ func (s *Ethereum) StartMining(threads int) error {
...
@@ -464,17 +464,9 @@ func (s *Ethereum) StartMining(threads int) error {
func
(
s
*
Ethereum
)
Etherbase
()
(
eb
common
.
Address
,
err
error
)
{
func
(
s
*
Ethereum
)
Etherbase
()
(
eb
common
.
Address
,
err
error
)
{
eb
=
s
.
etherbase
eb
=
s
.
etherbase
if
(
eb
==
common
.
Address
{})
{
if
(
eb
==
common
.
Address
{})
{
primary
,
err
:=
s
.
accountManager
.
Primary
()
err
=
fmt
.
Errorf
(
"etherbase address must be explicitly specified"
)
if
err
!=
nil
{
return
eb
,
err
}
if
(
primary
==
common
.
Address
{})
{
err
=
fmt
.
Errorf
(
"no accounts found"
)
return
eb
,
err
}
eb
=
primary
}
}
return
eb
,
nil
return
}
}
func
(
s
*
Ethereum
)
StopMining
()
{
s
.
miner
.
Stop
()
}
func
(
s
*
Ethereum
)
StopMining
()
{
s
.
miner
.
Stop
()
}
...
...
xeth/xeth.go
View file @
9bb575be
...
@@ -467,7 +467,10 @@ func (self *XEth) IsListening() bool {
...
@@ -467,7 +467,10 @@ func (self *XEth) IsListening() bool {
}
}
func
(
self
*
XEth
)
Coinbase
()
string
{
func
(
self
*
XEth
)
Coinbase
()
string
{
eb
,
_
:=
self
.
backend
.
Etherbase
()
eb
,
err
:=
self
.
backend
.
Etherbase
()
if
err
!=
nil
{
return
"0x0"
}
return
eb
.
Hex
()
return
eb
.
Hex
()
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment