Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
c5215fdd
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
c5215fdd
编写于
2月 08, 2017
作者:
P
Péter Szilágyi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
accounts, cmd, internal, mobile, node: canonical account URLs
上级
fad5eb0a
变更
19
显示空白变更内容
内联
并排
Showing
19 changed file
with
195 addition
and
116 deletion
+195
-116
accounts/accounts.go
accounts/accounts.go
+2
-5
accounts/keystore/account_cache.go
accounts/keystore/account_cache.go
+7
-7
accounts/keystore/account_cache_test.go
accounts/keystore/account_cache_test.go
+25
-24
accounts/keystore/key.go
accounts/keystore/key.go
+2
-2
accounts/keystore/keystore.go
accounts/keystore/keystore.go
+11
-9
accounts/keystore/keystore_plain_test.go
accounts/keystore/keystore_plain_test.go
+4
-4
accounts/keystore/keystore_test.go
accounts/keystore/keystore_test.go
+4
-6
accounts/keystore/keystore_wallet.go
accounts/keystore/keystore_wallet.go
+13
-12
accounts/keystore/presale.go
accounts/keystore/presale.go
+2
-2
accounts/manager.go
accounts/manager.go
+7
-3
accounts/url.go
accounts/url.go
+79
-0
accounts/usbwallet/ledger_hub.go
accounts/usbwallet/ledger_hub.go
+9
-5
accounts/usbwallet/ledger_wallet.go
accounts/usbwallet/ledger_wallet.go
+9
-14
cmd/geth/accountcmd.go
cmd/geth/accountcmd.go
+1
-1
cmd/geth/accountcmd_test.go
cmd/geth/accountcmd_test.go
+12
-12
cmd/swarm/main.go
cmd/swarm/main.go
+1
-1
internal/ethapi/api.go
internal/ethapi/api.go
+1
-3
mobile/accounts.go
mobile/accounts.go
+3
-3
node/config.go
node/config.go
+3
-3
未找到文件。
accounts/accounts.go
浏览文件 @
c5215fdd
...
...
@@ -29,19 +29,16 @@ import (
// by the optional URL field.
type
Account
struct
{
Address
common
.
Address
`json:"address"`
// Ethereum account address derived from the key
URL
string
`json:"url"`
// Optional resource locator within a backend
URL
URL
`json:"url"`
// Optional resource locator within a backend
}
// Wallet represents a software or hardware wallet that might contain one or more
// accounts (derived from the same seed).
type
Wallet
interface
{
// Type retrieves a textual representation of the type of the wallet.
Type
()
string
// URL retrieves the canonical path under which this wallet is reachable. It is
// user by upper layers to define a sorting order over all wallets from multiple
// backends.
URL
()
string
URL
()
URL
// Status returns a textual status to aid the user in the current state of the
// wallet.
...
...
accounts/keystore/account_cache.go
浏览文件 @
c5215fdd
...
...
@@ -42,7 +42,7 @@ const minReloadInterval = 2 * time.Second
type
accountsByURL
[]
accounts
.
Account
func
(
s
accountsByURL
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
accountsByURL
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
.
URL
<
s
[
j
]
.
URL
}
func
(
s
accountsByURL
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
.
URL
.
Cmp
(
s
[
j
]
.
URL
)
<
0
}
func
(
s
accountsByURL
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
// AmbiguousAddrError is returned when attempting to unlock
...
...
@@ -55,7 +55,7 @@ type AmbiguousAddrError struct {
func
(
err
*
AmbiguousAddrError
)
Error
()
string
{
files
:=
""
for
i
,
a
:=
range
err
.
Matches
{
files
+=
a
.
URL
files
+=
a
.
URL
.
Path
if
i
<
len
(
err
.
Matches
)
-
1
{
files
+=
", "
}
...
...
@@ -104,7 +104,7 @@ func (ac *accountCache) add(newAccount accounts.Account) {
ac
.
mu
.
Lock
()
defer
ac
.
mu
.
Unlock
()
i
:=
sort
.
Search
(
len
(
ac
.
all
),
func
(
i
int
)
bool
{
return
ac
.
all
[
i
]
.
URL
>=
newAccount
.
URL
})
i
:=
sort
.
Search
(
len
(
ac
.
all
),
func
(
i
int
)
bool
{
return
ac
.
all
[
i
]
.
URL
.
Cmp
(
newAccount
.
URL
)
>=
0
})
if
i
<
len
(
ac
.
all
)
&&
ac
.
all
[
i
]
==
newAccount
{
return
}
...
...
@@ -155,10 +155,10 @@ func (ac *accountCache) find(a accounts.Account) (accounts.Account, error) {
if
(
a
.
Address
!=
common
.
Address
{})
{
matches
=
ac
.
byAddr
[
a
.
Address
]
}
if
a
.
URL
!=
""
{
if
a
.
URL
.
Path
!=
""
{
// If only the basename is specified, complete the path.
if
!
strings
.
ContainsRune
(
a
.
URL
,
filepath
.
Separator
)
{
a
.
URL
=
filepath
.
Join
(
ac
.
keydir
,
a
.
URL
)
if
!
strings
.
ContainsRune
(
a
.
URL
.
Path
,
filepath
.
Separator
)
{
a
.
URL
.
Path
=
filepath
.
Join
(
ac
.
keydir
,
a
.
URL
.
Path
)
}
for
i
:=
range
matches
{
if
matches
[
i
]
.
URL
==
a
.
URL
{
...
...
@@ -272,7 +272,7 @@ func (ac *accountCache) scan() ([]accounts.Account, error) {
case
(
addr
==
common
.
Address
{})
:
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"can't decode key %s: missing or zero address"
,
path
)
default
:
addrs
=
append
(
addrs
,
accounts
.
Account
{
Address
:
addr
,
URL
:
path
})
addrs
=
append
(
addrs
,
accounts
.
Account
{
Address
:
addr
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
path
}
})
}
fd
.
Close
()
}
...
...
accounts/keystore/account_cache_test.go
浏览文件 @
c5215fdd
...
...
@@ -37,15 +37,15 @@ var (
cachetestAccounts
=
[]
accounts
.
Account
{
{
Address
:
common
.
HexToAddress
(
"7ef5a6135f1fd6a02593eedc869c6d41d934aef8"
),
URL
:
filepath
.
Join
(
cachetestDir
,
"UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8"
)
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
cachetestDir
,
"UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8"
)}
,
},
{
Address
:
common
.
HexToAddress
(
"f466859ead1932d743d622cb74fc058882e8648a"
),
URL
:
filepath
.
Join
(
cachetestDir
,
"aaa"
)
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
cachetestDir
,
"aaa"
)}
,
},
{
Address
:
common
.
HexToAddress
(
"289d485d9771714cce91d3393d764e1311907acc"
),
URL
:
filepath
.
Join
(
cachetestDir
,
"zzz"
)
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
cachetestDir
,
"zzz"
)}
,
},
}
)
...
...
@@ -63,10 +63,11 @@ func TestWatchNewFile(t *testing.T) {
// Move in the files.
wantAccounts
:=
make
([]
accounts
.
Account
,
len
(
cachetestAccounts
))
for
i
:=
range
cachetestAccounts
{
a
:=
cachetestAccounts
[
i
]
a
.
URL
=
filepath
.
Join
(
dir
,
filepath
.
Base
(
a
.
URL
))
wantAccounts
[
i
]
=
a
if
err
:=
cp
.
CopyFile
(
a
.
URL
,
cachetestAccounts
[
i
]
.
URL
);
err
!=
nil
{
wantAccounts
[
i
]
=
accounts
.
Account
{
Address
:
cachetestAccounts
[
i
]
.
Address
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
dir
,
filepath
.
Base
(
cachetestAccounts
[
i
]
.
URL
.
Path
))},
}
if
err
:=
cp
.
CopyFile
(
wantAccounts
[
i
]
.
URL
.
Path
,
cachetestAccounts
[
i
]
.
URL
.
Path
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
...
...
@@ -107,13 +108,13 @@ func TestWatchNoDir(t *testing.T) {
os
.
MkdirAll
(
dir
,
0700
)
defer
os
.
RemoveAll
(
dir
)
file
:=
filepath
.
Join
(
dir
,
"aaa"
)
if
err
:=
cp
.
CopyFile
(
file
,
cachetestAccounts
[
0
]
.
URL
);
err
!=
nil
{
if
err
:=
cp
.
CopyFile
(
file
,
cachetestAccounts
[
0
]
.
URL
.
Path
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
// ks should see the account.
wantAccounts
:=
[]
accounts
.
Account
{
cachetestAccounts
[
0
]}
wantAccounts
[
0
]
.
URL
=
file
wantAccounts
[
0
]
.
URL
=
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
file
}
for
d
:=
200
*
time
.
Millisecond
;
d
<
8
*
time
.
Second
;
d
*=
2
{
list
=
ks
.
Accounts
()
if
reflect
.
DeepEqual
(
list
,
wantAccounts
)
{
...
...
@@ -145,31 +146,31 @@ func TestCacheAddDeleteOrder(t *testing.T) {
accs
:=
[]
accounts
.
Account
{
{
Address
:
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
),
URL
:
"-309830980"
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
"-309830980"
}
,
},
{
Address
:
common
.
HexToAddress
(
"2cac1adea150210703ba75ed097ddfe24e14f213"
),
URL
:
"ggg"
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
"ggg"
}
,
},
{
Address
:
common
.
HexToAddress
(
"8bda78331c916a08481428e4b07c96d3e916d165"
),
URL
:
"zzzzzz-the-very-last-one.keyXXX"
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
"zzzzzz-the-very-last-one.keyXXX"
}
,
},
{
Address
:
common
.
HexToAddress
(
"d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"
),
URL
:
"SOMETHING.key"
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
"SOMETHING.key"
}
,
},
{
Address
:
common
.
HexToAddress
(
"7ef5a6135f1fd6a02593eedc869c6d41d934aef8"
),
URL
:
"UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8"
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
"UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8"
}
,
},
{
Address
:
common
.
HexToAddress
(
"f466859ead1932d743d622cb74fc058882e8648a"
),
URL
:
"aaa"
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
"aaa"
}
,
},
{
Address
:
common
.
HexToAddress
(
"289d485d9771714cce91d3393d764e1311907acc"
),
URL
:
"zzz"
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
"zzz"
}
,
},
}
for
_
,
a
:=
range
accs
{
...
...
@@ -210,7 +211,7 @@ func TestCacheAddDeleteOrder(t *testing.T) {
for
i
:=
0
;
i
<
len
(
accs
);
i
+=
2
{
cache
.
delete
(
wantAccounts
[
i
])
}
cache
.
delete
(
accounts
.
Account
{
Address
:
common
.
HexToAddress
(
"fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e"
),
URL
:
"something"
})
cache
.
delete
(
accounts
.
Account
{
Address
:
common
.
HexToAddress
(
"fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e"
),
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
"something"
}
})
select
{
case
<-
notify
:
...
...
@@ -245,19 +246,19 @@ func TestCacheFind(t *testing.T) {
accs
:=
[]
accounts
.
Account
{
{
Address
:
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
),
URL
:
filepath
.
Join
(
dir
,
"a.key"
)
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
dir
,
"a.key"
)}
,
},
{
Address
:
common
.
HexToAddress
(
"2cac1adea150210703ba75ed097ddfe24e14f213"
),
URL
:
filepath
.
Join
(
dir
,
"b.key"
)
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
dir
,
"b.key"
)}
,
},
{
Address
:
common
.
HexToAddress
(
"d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"
),
URL
:
filepath
.
Join
(
dir
,
"c.key"
)
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
dir
,
"c.key"
)}
,
},
{
Address
:
common
.
HexToAddress
(
"d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"
),
URL
:
filepath
.
Join
(
dir
,
"c2.key"
)
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
dir
,
"c2.key"
)}
,
},
}
for
_
,
a
:=
range
accs
{
...
...
@@ -266,7 +267,7 @@ func TestCacheFind(t *testing.T) {
nomatchAccount
:=
accounts
.
Account
{
Address
:
common
.
HexToAddress
(
"f466859ead1932d743d622cb74fc058882e8648a"
),
URL
:
filepath
.
Join
(
dir
,
"something"
)
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Join
(
dir
,
"something"
)}
,
}
tests
:=
[]
struct
{
Query
accounts
.
Account
...
...
@@ -278,7 +279,7 @@ func TestCacheFind(t *testing.T) {
// by file
{
Query
:
accounts
.
Account
{
URL
:
accs
[
0
]
.
URL
},
WantResult
:
accs
[
0
]},
// by basename
{
Query
:
accounts
.
Account
{
URL
:
filepath
.
Base
(
accs
[
0
]
.
URL
)
},
WantResult
:
accs
[
0
]},
{
Query
:
accounts
.
Account
{
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Base
(
accs
[
0
]
.
URL
.
Path
)}
},
WantResult
:
accs
[
0
]},
// by file and address
{
Query
:
accs
[
0
],
WantResult
:
accs
[
0
]},
// ambiguous address, tie resolved by file
...
...
@@ -294,7 +295,7 @@ func TestCacheFind(t *testing.T) {
// no match error
{
Query
:
nomatchAccount
,
WantError
:
ErrNoMatch
},
{
Query
:
accounts
.
Account
{
URL
:
nomatchAccount
.
URL
},
WantError
:
ErrNoMatch
},
{
Query
:
accounts
.
Account
{
URL
:
filepath
.
Base
(
nomatchAccount
.
URL
)
},
WantError
:
ErrNoMatch
},
{
Query
:
accounts
.
Account
{
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
filepath
.
Base
(
nomatchAccount
.
URL
.
Path
)}
},
WantError
:
ErrNoMatch
},
{
Query
:
accounts
.
Account
{
Address
:
nomatchAccount
.
Address
},
WantError
:
ErrNoMatch
},
}
for
i
,
test
:=
range
tests
{
...
...
accounts/keystore/key.go
浏览文件 @
c5215fdd
...
...
@@ -181,8 +181,8 @@ func storeNewKey(ks keyStore, rand io.Reader, auth string) (*Key, accounts.Accou
if
err
!=
nil
{
return
nil
,
accounts
.
Account
{},
err
}
a
:=
accounts
.
Account
{
Address
:
key
.
Address
,
URL
:
ks
.
JoinPath
(
keyFileName
(
key
.
Address
))
}
if
err
:=
ks
.
StoreKey
(
a
.
URL
,
key
,
auth
);
err
!=
nil
{
a
:=
accounts
.
Account
{
Address
:
key
.
Address
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
ks
.
JoinPath
(
keyFileName
(
key
.
Address
))}
}
if
err
:=
ks
.
StoreKey
(
a
.
URL
.
Path
,
key
,
auth
);
err
!=
nil
{
zeroKey
(
key
.
PrivateKey
)
return
nil
,
a
,
err
}
...
...
accounts/keystore/keystore.go
浏览文件 @
c5215fdd
...
...
@@ -49,6 +49,9 @@ var (
// KeyStoreType is the reflect type of a keystore backend.
var
KeyStoreType
=
reflect
.
TypeOf
(
&
KeyStore
{})
// KeyStoreScheme is the protocol scheme prefixing account and wallet URLs.
var
KeyStoreScheme
=
"keystore"
// Maximum time between wallet refreshes (if filesystem notifications don't work).
const
walletRefreshCycle
=
3
*
time
.
Second
...
...
@@ -130,22 +133,21 @@ func (ks *KeyStore) Wallets() []accounts.Wallet {
// necessary wallet refreshes.
func
(
ks
*
KeyStore
)
refreshWallets
()
{
// Retrieve the current list of accounts
ks
.
mu
.
Lock
()
accs
:=
ks
.
cache
.
accounts
()
// Transform the current list of wallets into the new one
ks
.
mu
.
Lock
()
wallets
:=
make
([]
accounts
.
Wallet
,
0
,
len
(
accs
))
events
:=
[]
accounts
.
WalletEvent
{}
for
_
,
account
:=
range
accs
{
// Drop wallets while they were in front of the next account
for
len
(
ks
.
wallets
)
>
0
&&
ks
.
wallets
[
0
]
.
URL
()
<
account
.
URL
{
for
len
(
ks
.
wallets
)
>
0
&&
ks
.
wallets
[
0
]
.
URL
()
.
Cmp
(
account
.
URL
)
<
0
{
events
=
append
(
events
,
accounts
.
WalletEvent
{
Wallet
:
ks
.
wallets
[
0
],
Arrive
:
false
})
ks
.
wallets
=
ks
.
wallets
[
1
:
]
}
// If there are no more wallets or the account is before the next, wrap new wallet
if
len
(
ks
.
wallets
)
==
0
||
ks
.
wallets
[
0
]
.
URL
()
>
account
.
URL
{
if
len
(
ks
.
wallets
)
==
0
||
ks
.
wallets
[
0
]
.
URL
()
.
Cmp
(
account
.
URL
)
>
0
{
wallet
:=
&
keystoreWallet
{
account
:
account
,
keystore
:
ks
}
events
=
append
(
events
,
accounts
.
WalletEvent
{
Wallet
:
wallet
,
Arrive
:
true
})
...
...
@@ -242,7 +244,7 @@ func (ks *KeyStore) Delete(a accounts.Account, passphrase string) error {
// The order is crucial here. The key is dropped from the
// cache after the file is gone so that a reload happening in
// between won't insert it into the cache again.
err
=
os
.
Remove
(
a
.
URL
)
err
=
os
.
Remove
(
a
.
URL
.
Path
)
if
err
==
nil
{
ks
.
cache
.
delete
(
a
)
ks
.
refreshWallets
()
...
...
@@ -377,7 +379,7 @@ func (ks *KeyStore) getDecryptedKey(a accounts.Account, auth string) (accounts.A
if
err
!=
nil
{
return
a
,
nil
,
err
}
key
,
err
:=
ks
.
storage
.
GetKey
(
a
.
Address
,
a
.
URL
,
auth
)
key
,
err
:=
ks
.
storage
.
GetKey
(
a
.
Address
,
a
.
URL
.
Path
,
auth
)
return
a
,
key
,
err
}
...
...
@@ -453,8 +455,8 @@ func (ks *KeyStore) ImportECDSA(priv *ecdsa.PrivateKey, passphrase string) (acco
}
func
(
ks
*
KeyStore
)
importKey
(
key
*
Key
,
passphrase
string
)
(
accounts
.
Account
,
error
)
{
a
:=
accounts
.
Account
{
Address
:
key
.
Address
,
URL
:
ks
.
storage
.
JoinPath
(
keyFileName
(
key
.
Address
))
}
if
err
:=
ks
.
storage
.
StoreKey
(
a
.
URL
,
key
,
passphrase
);
err
!=
nil
{
a
:=
accounts
.
Account
{
Address
:
key
.
Address
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
ks
.
storage
.
JoinPath
(
keyFileName
(
key
.
Address
))}
}
if
err
:=
ks
.
storage
.
StoreKey
(
a
.
URL
.
Path
,
key
,
passphrase
);
err
!=
nil
{
return
accounts
.
Account
{},
err
}
ks
.
cache
.
add
(
a
)
...
...
@@ -468,7 +470,7 @@ func (ks *KeyStore) Update(a accounts.Account, passphrase, newPassphrase string)
if
err
!=
nil
{
return
err
}
return
ks
.
storage
.
StoreKey
(
a
.
URL
,
key
,
newPassphrase
)
return
ks
.
storage
.
StoreKey
(
a
.
URL
.
Path
,
key
,
newPassphrase
)
}
// ImportPreSaleKey decrypts the given Ethereum presale wallet and stores
...
...
accounts/keystore/keystore_plain_test.go
浏览文件 @
c5215fdd
...
...
@@ -52,7 +52,7 @@ func TestKeyStorePlain(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
k2
,
err
:=
ks
.
GetKey
(
k1
.
Address
,
account
.
URL
,
pass
)
k2
,
err
:=
ks
.
GetKey
(
k1
.
Address
,
account
.
URL
.
Path
,
pass
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -73,7 +73,7 @@ func TestKeyStorePassphrase(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
k2
,
err
:=
ks
.
GetKey
(
k1
.
Address
,
account
.
URL
,
pass
)
k2
,
err
:=
ks
.
GetKey
(
k1
.
Address
,
account
.
URL
.
Path
,
pass
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -94,7 +94,7 @@ func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
_
,
err
=
ks
.
GetKey
(
k1
.
Address
,
account
.
URL
,
"bar"
);
err
!=
ErrDecrypt
{
if
_
,
err
=
ks
.
GetKey
(
k1
.
Address
,
account
.
URL
.
Path
,
"bar"
);
err
!=
ErrDecrypt
{
t
.
Fatalf
(
"wrong error for invalid passphrase
\n
got %q
\n
want %q"
,
err
,
ErrDecrypt
)
}
}
...
...
@@ -115,7 +115,7 @@ func TestImportPreSaleKey(t *testing.T) {
if
account
.
Address
!=
common
.
HexToAddress
(
"d4584b5f6229b7be90727b0fc8c6b91bb427821f"
)
{
t
.
Errorf
(
"imported account has wrong address %x"
,
account
.
Address
)
}
if
!
strings
.
HasPrefix
(
account
.
URL
,
dir
)
{
if
!
strings
.
HasPrefix
(
account
.
URL
.
Path
,
dir
)
{
t
.
Errorf
(
"imported account file not in keystore directory: %q"
,
account
.
URL
)
}
}
...
...
accounts/keystore/keystore_test.go
浏览文件 @
c5215fdd
...
...
@@ -41,10 +41,10 @@ func TestKeyStore(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
strings
.
HasPrefix
(
a
.
URL
,
dir
)
{
if
!
strings
.
HasPrefix
(
a
.
URL
.
Path
,
dir
)
{
t
.
Errorf
(
"account file %s doesn't have dir prefix"
,
a
.
URL
)
}
stat
,
err
:=
os
.
Stat
(
a
.
URL
)
stat
,
err
:=
os
.
Stat
(
a
.
URL
.
Path
)
if
err
!=
nil
{
t
.
Fatalf
(
"account file %s doesn't exist (%v)"
,
a
.
URL
,
err
)
}
...
...
@@ -60,7 +60,7 @@ func TestKeyStore(t *testing.T) {
if
err
:=
ks
.
Delete
(
a
,
"bar"
);
err
!=
nil
{
t
.
Errorf
(
"Delete error: %v"
,
err
)
}
if
common
.
FileExist
(
a
.
URL
)
{
if
common
.
FileExist
(
a
.
URL
.
Path
)
{
t
.
Errorf
(
"account file %s should be gone after Delete"
,
a
.
URL
)
}
if
ks
.
HasAddress
(
a
.
Address
)
{
...
...
@@ -286,7 +286,7 @@ func TestWalletNotifications(t *testing.T) {
// Randomly add and remove account and make sure events and wallets are in sync
live
:=
make
(
map
[
common
.
Address
]
accounts
.
Account
)
for
i
:=
0
;
i
<
1024
;
i
++
{
for
i
:=
0
;
i
<
256
;
i
++
{
// Execute a creation or deletion and ensure event arrival
if
create
:=
len
(
live
)
==
0
||
rand
.
Int
()
%
4
>
0
;
create
{
// Add a new account and ensure wallet notifications arrives
...
...
@@ -349,8 +349,6 @@ func TestWalletNotifications(t *testing.T) {
}
}
}
// Sleep a bit to avoid same-timestamp keyfiles
time
.
Sleep
(
10
*
time
.
Millisecond
)
}
}
...
...
accounts/keystore/keystore_wallet.go
浏览文件 @
c5215fdd
...
...
@@ -30,20 +30,21 @@ type keystoreWallet struct {
keystore
*
KeyStore
// Keystore where the account originates from
}
// Type implements accounts.Wallet, returning the textual type of the wallet.
func
(
w
*
keystoreWallet
)
Type
()
string
{
return
"secret-storage"
}
// URL implements accounts.Wallet, returning the URL of the account within.
func
(
w
*
keystoreWallet
)
URL
()
string
{
func
(
w
*
keystoreWallet
)
URL
()
accounts
.
URL
{
return
w
.
account
.
URL
}
// Status implements accounts.Wallet, always returning "open", since there is no
// concept of open/close for plain keystore accounts.
func
(
w
*
keystoreWallet
)
Status
()
string
{
return
"Open"
w
.
keystore
.
mu
.
RLock
()
defer
w
.
keystore
.
mu
.
RUnlock
()
if
_
,
ok
:=
w
.
keystore
.
unlocked
[
w
.
account
.
Address
];
ok
{
return
"Unlocked"
}
return
"Locked"
}
// Open implements accounts.Wallet, but is a noop for plain wallets since there
...
...
@@ -63,7 +64,7 @@ func (w *keystoreWallet) Accounts() []accounts.Account {
// Contains implements accounts.Wallet, returning whether a particular account is
// or is not wrapped by this wallet instance.
func
(
w
*
keystoreWallet
)
Contains
(
account
accounts
.
Account
)
bool
{
return
account
.
Address
==
w
.
account
.
Address
&&
(
account
.
URL
==
""
||
account
.
URL
==
w
.
account
.
URL
)
return
account
.
Address
==
w
.
account
.
Address
&&
(
account
.
URL
==
(
accounts
.
URL
{})
||
account
.
URL
==
w
.
account
.
URL
)
}
// Derive implements accounts.Wallet, but is a noop for plain wallets since there
...
...
@@ -81,7 +82,7 @@ func (w *keystoreWallet) SignHash(account accounts.Account, hash []byte) ([]byte
if
account
.
Address
!=
w
.
account
.
Address
{
return
nil
,
accounts
.
ErrUnknownAccount
}
if
account
.
URL
!=
""
&&
account
.
URL
!=
w
.
account
.
URL
{
if
account
.
URL
!=
(
accounts
.
URL
{})
&&
account
.
URL
!=
w
.
account
.
URL
{
return
nil
,
accounts
.
ErrUnknownAccount
}
// Account seems valid, request the keystore to sign
...
...
@@ -97,7 +98,7 @@ func (w *keystoreWallet) SignTx(account accounts.Account, tx *types.Transaction,
if
account
.
Address
!=
w
.
account
.
Address
{
return
nil
,
accounts
.
ErrUnknownAccount
}
if
account
.
URL
!=
""
&&
account
.
URL
!=
w
.
account
.
URL
{
if
account
.
URL
!=
(
accounts
.
URL
{})
&&
account
.
URL
!=
w
.
account
.
URL
{
return
nil
,
accounts
.
ErrUnknownAccount
}
// Account seems valid, request the keystore to sign
...
...
@@ -111,7 +112,7 @@ func (w *keystoreWallet) SignHashWithPassphrase(account accounts.Account, passph
if
account
.
Address
!=
w
.
account
.
Address
{
return
nil
,
accounts
.
ErrUnknownAccount
}
if
account
.
URL
!=
""
&&
account
.
URL
!=
w
.
account
.
URL
{
if
account
.
URL
!=
(
accounts
.
URL
{})
&&
account
.
URL
!=
w
.
account
.
URL
{
return
nil
,
accounts
.
ErrUnknownAccount
}
// Account seems valid, request the keystore to sign
...
...
@@ -125,7 +126,7 @@ func (w *keystoreWallet) SignTxWithPassphrase(account accounts.Account, passphra
if
account
.
Address
!=
w
.
account
.
Address
{
return
nil
,
accounts
.
ErrUnknownAccount
}
if
account
.
URL
!=
""
&&
account
.
URL
!=
w
.
account
.
URL
{
if
account
.
URL
!=
(
accounts
.
URL
{})
&&
account
.
URL
!=
w
.
account
.
URL
{
return
nil
,
accounts
.
ErrUnknownAccount
}
// Account seems valid, request the keystore to sign
...
...
accounts/keystore/presale.go
浏览文件 @
c5215fdd
...
...
@@ -38,8 +38,8 @@ func importPreSaleKey(keyStore keyStore, keyJSON []byte, password string) (accou
return
accounts
.
Account
{},
nil
,
err
}
key
.
Id
=
uuid
.
NewRandom
()
a
:=
accounts
.
Account
{
Address
:
key
.
Address
,
URL
:
keyStore
.
JoinPath
(
keyFileName
(
key
.
Address
))
}
err
=
keyStore
.
StoreKey
(
a
.
URL
,
key
,
password
)
a
:=
accounts
.
Account
{
Address
:
key
.
Address
,
URL
:
accounts
.
URL
{
Scheme
:
KeyStoreScheme
,
Path
:
keyStore
.
JoinPath
(
keyFileName
(
key
.
Address
))}
}
err
=
keyStore
.
StoreKey
(
a
.
URL
.
Path
,
key
,
password
)
return
a
,
key
,
err
}
...
...
accounts/manager.go
浏览文件 @
c5215fdd
...
...
@@ -134,8 +134,12 @@ func (am *Manager) Wallet(url string) (Wallet, error) {
am
.
lock
.
RLock
()
defer
am
.
lock
.
RUnlock
()
parsed
,
err
:=
parseURL
(
url
)
if
err
!=
nil
{
return
nil
,
err
}
for
_
,
wallet
:=
range
am
.
Wallets
()
{
if
wallet
.
URL
()
==
url
{
if
wallet
.
URL
()
==
parsed
{
return
wallet
,
nil
}
}
...
...
@@ -169,7 +173,7 @@ func (am *Manager) Subscribe(sink chan<- WalletEvent) event.Subscription {
// The original slice is assumed to be already sorted by URL.
func
merge
(
slice
[]
Wallet
,
wallets
...
Wallet
)
[]
Wallet
{
for
_
,
wallet
:=
range
wallets
{
n
:=
sort
.
Search
(
len
(
slice
),
func
(
i
int
)
bool
{
return
slice
[
i
]
.
URL
()
>=
wallet
.
URL
()
})
n
:=
sort
.
Search
(
len
(
slice
),
func
(
i
int
)
bool
{
return
slice
[
i
]
.
URL
()
.
Cmp
(
wallet
.
URL
())
>=
0
})
if
n
==
len
(
slice
)
{
slice
=
append
(
slice
,
wallet
)
continue
...
...
@@ -183,7 +187,7 @@ func merge(slice []Wallet, wallets ...Wallet) []Wallet {
// cache and removes the ones specified.
func
drop
(
slice
[]
Wallet
,
wallets
...
Wallet
)
[]
Wallet
{
for
_
,
wallet
:=
range
wallets
{
n
:=
sort
.
Search
(
len
(
slice
),
func
(
i
int
)
bool
{
return
slice
[
i
]
.
URL
()
>=
wallet
.
URL
()
})
n
:=
sort
.
Search
(
len
(
slice
),
func
(
i
int
)
bool
{
return
slice
[
i
]
.
URL
()
.
Cmp
(
wallet
.
URL
())
>=
0
})
if
n
==
len
(
slice
)
{
// Wallet not found, may happen during startup
continue
...
...
accounts/url.go
0 → 100644
浏览文件 @
c5215fdd
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
accounts
import
(
"encoding/json"
"errors"
"fmt"
"strings"
)
// URL represents the canonical identification URL of a wallet or account.
//
// It is a simplified version of url.URL, with the important limitations (which
// are considered features here) that it contains value-copyable components only,
// as well as that it doesn't do any URL encoding/decoding of special characters.
//
// The former is important to allow an account to be copied without leaving live
// references to the original version, whereas the latter is important to ensure
// one single canonical form opposed to many allowed ones by the RFC 3986 spec.
//
// As such, these URLs should not be used outside of the scope of an Ethereum
// wallet or account.
type
URL
struct
{
Scheme
string
// Protocol scheme to identify a capable account backend
Path
string
// Path for the backend to identify a unique entity
}
// parseURL converts a user supplied URL into the accounts specific structure.
func
parseURL
(
url
string
)
(
URL
,
error
)
{
parts
:=
strings
.
Split
(
url
,
"://"
)
if
len
(
parts
)
!=
2
||
parts
[
0
]
==
""
{
return
URL
{},
errors
.
New
(
"protocol scheme missing"
)
}
return
URL
{
Scheme
:
parts
[
0
],
Path
:
parts
[
1
],
},
nil
}
// String implements the stringer interface.
func
(
u
URL
)
String
()
string
{
if
u
.
Scheme
!=
""
{
return
fmt
.
Sprintf
(
"%s://%s"
,
u
.
Scheme
,
u
.
Path
)
}
return
u
.
Path
}
// MarshalJSON implements the json.Marshaller interface.
func
(
u
URL
)
MarshalJSON
()
([]
byte
,
error
)
{
return
json
.
Marshal
(
u
.
String
())
}
// Cmp compares x and y and returns:
//
// -1 if x < y
// 0 if x == y
// +1 if x > y
//
func
(
u
URL
)
Cmp
(
url
URL
)
int
{
if
u
.
Scheme
==
url
.
Scheme
{
return
strings
.
Compare
(
u
.
Path
,
url
.
Path
)
}
return
strings
.
Compare
(
u
.
Scheme
,
url
.
Scheme
)
}
accounts/usbwallet/ledger_hub.go
浏览文件 @
c5215fdd
...
...
@@ -32,6 +32,9 @@ import (
"github.com/karalabe/gousb/usb"
)
// LedgerScheme is the protocol scheme prefixing account and wallet URLs.
var
LedgerScheme
=
"ledger"
// ledgerDeviceIDs are the known device IDs that Ledger wallets use.
var
ledgerDeviceIDs
=
[]
deviceID
{
{
Vendor
:
0x2c97
,
Product
:
0x0000
},
// Ledger Blue
...
...
@@ -124,23 +127,24 @@ func (hub *LedgerHub) refreshWallets() {
for
i
:=
0
;
i
<
len
(
devIDs
);
i
++
{
devID
,
busID
:=
devIDs
[
i
],
busIDs
[
i
]
url
:=
fmt
.
Sprintf
(
"ledger://%03d:%03d"
,
busID
>>
8
,
busID
&
0xff
)
url
:=
accounts
.
URL
{
Scheme
:
LedgerScheme
,
Path
:
fmt
.
Sprintf
(
"%03d:%03d"
,
busID
>>
8
,
busID
&
0xff
)}
// Drop wallets while they were in front of the next account
for
len
(
hub
.
wallets
)
>
0
&&
hub
.
wallets
[
0
]
.
URL
()
<
url
{
for
len
(
hub
.
wallets
)
>
0
&&
hub
.
wallets
[
0
]
.
URL
()
.
Cmp
(
url
)
<
0
{
events
=
append
(
events
,
accounts
.
WalletEvent
{
Wallet
:
hub
.
wallets
[
0
],
Arrive
:
false
})
hub
.
wallets
=
hub
.
wallets
[
1
:
]
}
// If there are no more wallets or the account is before the next, wrap new wallet
if
len
(
hub
.
wallets
)
==
0
||
hub
.
wallets
[
0
]
.
URL
()
>
url
{
wallet
:=
&
ledgerWallet
{
context
:
hub
.
ctx
,
hardwareID
:
devID
,
locationID
:
busID
,
url
:
url
}
if
len
(
hub
.
wallets
)
==
0
||
hub
.
wallets
[
0
]
.
URL
()
.
Cmp
(
url
)
>
0
{
wallet
:=
&
ledgerWallet
{
context
:
hub
.
ctx
,
hardwareID
:
devID
,
locationID
:
busID
,
url
:
&
url
}
events
=
append
(
events
,
accounts
.
WalletEvent
{
Wallet
:
wallet
,
Arrive
:
true
})
wallets
=
append
(
wallets
,
wallet
)
continue
}
// If the account is the same as the first wallet, keep it
if
hub
.
wallets
[
0
]
.
URL
()
==
url
{
if
hub
.
wallets
[
0
]
.
URL
()
.
Cmp
(
url
)
==
0
{
wallets
=
append
(
wallets
,
hub
.
wallets
[
0
])
hub
.
wallets
=
hub
.
wallets
[
1
:
]
continue
...
...
accounts/usbwallet/ledger_wallet.go
浏览文件 @
c5215fdd
...
...
@@ -75,7 +75,7 @@ type ledgerWallet struct {
context
*
usb
.
Context
// USB context to interface libusb through
hardwareID
deviceID
// USB identifiers to identify this device type
locationID
uint16
// USB bus and address to identify this device instance
url
string
// Textual URL uniquely identifying this wallet
url
*
accounts
.
URL
// Textual URL uniquely identifying this wallet
device
*
usb
.
Device
// USB device advertising itself as a Ledger wallet
input
usb
.
Endpoint
// Input endpoint to send data to this device
...
...
@@ -90,14 +90,9 @@ type ledgerWallet struct {
lock
sync
.
RWMutex
}
// Type implements accounts.Wallet, returning the textual type of the wallet.
func
(
w
*
ledgerWallet
)
Type
()
string
{
return
"ledger"
}
// URL implements accounts.Wallet, returning the URL of the Ledger device.
func
(
w
*
ledgerWallet
)
URL
()
string
{
return
w
.
url
func
(
w
*
ledgerWallet
)
URL
()
accounts
.
URL
{
return
*
w
.
url
}
// Status implements accounts.Wallet, always whether the Ledger is opened, closed
...
...
@@ -113,9 +108,9 @@ func (w *ledgerWallet) Status() string {
return
"Closed"
}
if
w
.
version
==
[
3
]
byte
{
0
,
0
,
0
}
{
return
"Ethereum app
not started
"
return
"Ethereum app
offline
"
}
return
fmt
.
Sprintf
(
"Ethereum app v%d.%d.%d"
,
w
.
version
[
0
],
w
.
version
[
1
],
w
.
version
[
2
])
return
fmt
.
Sprintf
(
"Ethereum app v%d.%d.%d
online
"
,
w
.
version
[
0
],
w
.
version
[
1
],
w
.
version
[
2
])
}
// Open implements accounts.Wallet, attempting to open a USB connection to the
...
...
@@ -309,7 +304,7 @@ func (w *ledgerWallet) Derive(path string, pin bool) (accounts.Account, error) {
}
account
:=
accounts
.
Account
{
Address
:
address
,
URL
:
fmt
.
Sprintf
(
"%s/%s"
,
w
.
url
,
path
)
,
URL
:
accounts
.
URL
{
Scheme
:
w
.
url
.
Scheme
,
Path
:
fmt
.
Sprintf
(
"%s/%s"
,
w
.
url
.
Path
,
path
)}
,
}
// If pinning was requested, track the account
if
pin
{
...
...
cmd/geth/accountcmd.go
浏览文件 @
c5215fdd
...
...
@@ -185,7 +185,7 @@ func accountList(ctx *cli.Context) error {
var
index
int
for
_
,
wallet
:=
range
stack
.
AccountManager
()
.
Wallets
()
{
for
_
,
account
:=
range
wallet
.
Accounts
()
{
fmt
.
Printf
(
"Account #%d: {%x} %s
\n
"
,
index
,
account
.
Address
,
account
.
URL
)
fmt
.
Printf
(
"Account #%d: {%x} %s
\n
"
,
index
,
account
.
Address
,
&
account
.
URL
)
index
++
}
}
...
...
cmd/geth/accountcmd_test.go
浏览文件 @
c5215fdd
...
...
@@ -53,15 +53,15 @@ func TestAccountList(t *testing.T) {
defer
geth
.
expectExit
()
if
runtime
.
GOOS
==
"windows"
{
geth
.
expect
(
`
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} {{.Datadir}}\keystore\UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} {{.Datadir}}\keystore\aaa
Account #2: {289d485d9771714cce91d3393d764e1311907acc} {{.Datadir}}\keystore\zzz
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8}
keystore://
{{.Datadir}}\keystore\UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
Account #1: {f466859ead1932d743d622cb74fc058882e8648a}
keystore://
{{.Datadir}}\keystore\aaa
Account #2: {289d485d9771714cce91d3393d764e1311907acc}
keystore://
{{.Datadir}}\keystore\zzz
`
)
}
else
{
geth
.
expect
(
`
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} {{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} {{.Datadir}}/keystore/aaa
Account #2: {289d485d9771714cce91d3393d764e1311907acc} {{.Datadir}}/keystore/zzz
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8}
keystore://
{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
Account #1: {f466859ead1932d743d622cb74fc058882e8648a}
keystore://
{{.Datadir}}/keystore/aaa
Account #2: {289d485d9771714cce91d3393d764e1311907acc}
keystore://
{{.Datadir}}/keystore/zzz
`
)
}
}
...
...
@@ -247,12 +247,12 @@ Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
!! Unsupported terminal, password will be echoed.
Passphrase: {{.InputLine "foobar"}}
Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a:
{{keypath "1"}}
{{keypath "2"}}
keystore://
{{keypath "1"}}
keystore://
{{keypath "2"}}
Testing your passphrase against all of them...
Your passphrase unlocked {{keypath "1"}}
Your passphrase unlocked
keystore://
{{keypath "1"}}
In order to avoid this warning, you need to remove the following duplicate key files:
{{keypath "2"}}
keystore://
{{keypath "2"}}
`
)
geth
.
expectExit
()
...
...
@@ -283,8 +283,8 @@ Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
!! Unsupported terminal, password will be echoed.
Passphrase: {{.InputLine "wrong"}}
Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a:
{{keypath "1"}}
{{keypath "2"}}
keystore://
{{keypath "1"}}
keystore://
{{keypath "2"}}
Testing your passphrase against all of them...
Fatal: None of the listed files could be unlocked.
`
)
...
...
cmd/swarm/main.go
浏览文件 @
c5215fdd
...
...
@@ -351,7 +351,7 @@ func decryptStoreAccount(ks *keystore.KeyStore, account string) *ecdsa.PrivateKe
if
err
!=
nil
{
utils
.
Fatalf
(
"Can't find swarm account key: %v"
,
err
)
}
keyjson
,
err
:=
ioutil
.
ReadFile
(
a
.
URL
)
keyjson
,
err
:=
ioutil
.
ReadFile
(
a
.
URL
.
Path
)
if
err
!=
nil
{
utils
.
Fatalf
(
"Can't load swarm account key: %v"
,
err
)
}
...
...
internal/ethapi/api.go
浏览文件 @
c5215fdd
...
...
@@ -228,7 +228,6 @@ func (s *PrivateAccountAPI) ListAccounts() []common.Address {
// rawWallet is a JSON representation of an accounts.Wallet interface, with its
// data contents extracted into plain fields.
type
rawWallet
struct
{
Type
string
`json:"type"`
URL
string
`json:"url"`
Status
string
`json:"status"`
Accounts
[]
accounts
.
Account
`json:"accounts"`
...
...
@@ -239,8 +238,7 @@ func (s *PrivateAccountAPI) ListWallets() []rawWallet {
var
wallets
[]
rawWallet
for
_
,
wallet
:=
range
s
.
am
.
Wallets
()
{
wallets
=
append
(
wallets
,
rawWallet
{
Type
:
wallet
.
Type
(),
URL
:
wallet
.
URL
(),
URL
:
wallet
.
URL
()
.
String
(),
Status
:
wallet
.
Status
(),
Accounts
:
wallet
.
Accounts
(),
})
...
...
mobile/accounts.go
浏览文件 @
c5215fdd
...
...
@@ -78,9 +78,9 @@ func (a *Account) GetAddress() *Address {
return
&
Address
{
a
.
account
.
Address
}
}
// Get
File retrieves the path of the file containing the account key
.
func
(
a
*
Account
)
Get
File
()
string
{
return
a
.
account
.
URL
// Get
URL retrieves the canonical URL of the account
.
func
(
a
*
Account
)
Get
URL
()
string
{
return
a
.
account
.
URL
.
String
()
}
// KeyStore manages a key storage directory on disk.
...
...
node/config.go
浏览文件 @
c5215fdd
...
...
@@ -454,12 +454,12 @@ func makeAccountManager(conf *Config) (*accounts.Manager, string, error) {
go
func
()
{
for
event
:=
range
changes
{
if
event
.
Arrive
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"New
%s wallet appeared: %s"
,
event
.
Wallet
.
Type
()
,
event
.
Wallet
.
URL
())
glog
.
V
(
logger
.
Info
)
.
Infof
(
"New
wallet appeared: %s"
,
event
.
Wallet
.
URL
())
if
err
:=
event
.
Wallet
.
Open
(
""
);
err
!=
nil
{
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"Failed to open
%s wallet %s: %v"
,
event
.
Wallet
.
Type
()
,
event
.
Wallet
.
URL
(),
err
)
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"Failed to open
wallet %s: %v"
,
event
.
Wallet
.
URL
(),
err
)
}
}
else
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Old
%s wallet disappeared: %s"
,
event
.
Wallet
.
Type
()
,
event
.
Wallet
.
URL
())
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Old
wallet disappeared: %s"
,
event
.
Wallet
.
URL
())
}
}
}()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录