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
26da6daa
Unverified
Commit
26da6daa
authored
Mar 20, 2017
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
accounts/usbwallet: fix Ledger hidapi/libusb protocol violation
parent
11e7a712
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
36 additions
and
13 deletions
+36
-13
ledger_hub.go
accounts/usbwallet/ledger_hub.go
+30
-13
ledger_wallet.go
accounts/usbwallet/ledger_wallet.go
+6
-0
No files found.
accounts/usbwallet/ledger_hub.go
View file @
26da6daa
...
@@ -22,6 +22,7 @@ package usbwallet
...
@@ -22,6 +22,7 @@ package usbwallet
import
(
import
(
"errors"
"errors"
"runtime"
"sync"
"sync"
"time"
"time"
...
@@ -55,7 +56,9 @@ type LedgerHub struct {
...
@@ -55,7 +56,9 @@ type LedgerHub struct {
updating
bool
// Whether the event notification loop is running
updating
bool
// Whether the event notification loop is running
quit
chan
chan
error
quit
chan
chan
error
lock
sync
.
RWMutex
stateLock
sync
.
RWMutex
// Protects the internals of the hub from racey access
commsLock
sync
.
RWMutex
// Allows wallets to lock enumeration (TODO(karalabe): remove if hotplug lands on Windows)
}
}
// NewLedgerHub creates a new hardware wallet manager for Ledger devices.
// NewLedgerHub creates a new hardware wallet manager for Ledger devices.
...
@@ -76,8 +79,8 @@ func (hub *LedgerHub) Wallets() []accounts.Wallet {
...
@@ -76,8 +79,8 @@ func (hub *LedgerHub) Wallets() []accounts.Wallet {
// Make sure the list of wallets is up to date
// Make sure the list of wallets is up to date
hub
.
refreshWallets
()
hub
.
refreshWallets
()
hub
.
l
ock
.
RLock
()
hub
.
stateL
ock
.
RLock
()
defer
hub
.
l
ock
.
RUnlock
()
defer
hub
.
stateL
ock
.
RUnlock
()
cpy
:=
make
([]
accounts
.
Wallet
,
len
(
hub
.
wallets
))
cpy
:=
make
([]
accounts
.
Wallet
,
len
(
hub
.
wallets
))
copy
(
cpy
,
hub
.
wallets
)
copy
(
cpy
,
hub
.
wallets
)
...
@@ -88,15 +91,25 @@ func (hub *LedgerHub) Wallets() []accounts.Wallet {
...
@@ -88,15 +91,25 @@ func (hub *LedgerHub) Wallets() []accounts.Wallet {
// list of wallets based on the found devices.
// list of wallets based on the found devices.
func
(
hub
*
LedgerHub
)
refreshWallets
()
{
func
(
hub
*
LedgerHub
)
refreshWallets
()
{
// Don't scan the USB like crazy it the user fetches wallets in a loop
// Don't scan the USB like crazy it the user fetches wallets in a loop
hub
.
l
ock
.
RLock
()
hub
.
stateL
ock
.
RLock
()
elapsed
:=
time
.
Since
(
hub
.
refreshed
)
elapsed
:=
time
.
Since
(
hub
.
refreshed
)
hub
.
l
ock
.
RUnlock
()
hub
.
stateL
ock
.
RUnlock
()
if
elapsed
<
ledgerRefreshThrottling
{
if
elapsed
<
ledgerRefreshThrottling
{
return
return
}
}
// Retrieve the current list of Ledger devices
// Retrieve the current list of Ledger devices
var
ledgers
[]
hid
.
DeviceInfo
var
ledgers
[]
hid
.
DeviceInfo
if
runtime
.
GOOS
==
"linux"
{
// hidapi on Linux opens the device during enumeration to retrieve some infos,
// breaking the Ledger protocol if that is waiting for user confirmation. This
// is a bug acknowledged at Ledger, but it won't be fixed on old devices so we
// need to prevent concurrent comms ourselves. The more elegant solution would
// be to ditch enumeration in favor of hutplug events, but that don't work yet
// on Windows so if we need to hack it anyway, this is more elegant for now.
hub
.
commsLock
.
Lock
()
}
for
_
,
info
:=
range
hid
.
Enumerate
(
0
,
0
)
{
// Can't enumerate directly, one valid ID is the 0 wildcard
for
_
,
info
:=
range
hid
.
Enumerate
(
0
,
0
)
{
// Can't enumerate directly, one valid ID is the 0 wildcard
for
_
,
id
:=
range
ledgerDeviceIDs
{
for
_
,
id
:=
range
ledgerDeviceIDs
{
if
info
.
VendorID
==
id
.
Vendor
&&
info
.
ProductID
==
id
.
Product
{
if
info
.
VendorID
==
id
.
Vendor
&&
info
.
ProductID
==
id
.
Product
{
...
@@ -105,8 +118,12 @@ func (hub *LedgerHub) refreshWallets() {
...
@@ -105,8 +118,12 @@ func (hub *LedgerHub) refreshWallets() {
}
}
}
}
}
}
if
runtime
.
GOOS
==
"linux"
{
// See rationale before the enumeration why this is needed and only on Linux.
hub
.
commsLock
.
Unlock
()
}
// Transform the current list of wallets into the new one
// Transform the current list of wallets into the new one
hub
.
l
ock
.
Lock
()
hub
.
stateL
ock
.
Lock
()
wallets
:=
make
([]
accounts
.
Wallet
,
0
,
len
(
ledgers
))
wallets
:=
make
([]
accounts
.
Wallet
,
0
,
len
(
ledgers
))
events
:=
[]
accounts
.
WalletEvent
{}
events
:=
[]
accounts
.
WalletEvent
{}
...
@@ -121,7 +138,7 @@ func (hub *LedgerHub) refreshWallets() {
...
@@ -121,7 +138,7 @@ func (hub *LedgerHub) refreshWallets() {
}
}
// If there are no more wallets or the device is before the next, wrap new wallet
// If there are no more wallets or the device is before the next, wrap new wallet
if
len
(
hub
.
wallets
)
==
0
||
hub
.
wallets
[
0
]
.
URL
()
.
Cmp
(
url
)
>
0
{
if
len
(
hub
.
wallets
)
==
0
||
hub
.
wallets
[
0
]
.
URL
()
.
Cmp
(
url
)
>
0
{
wallet
:=
&
ledgerWallet
{
url
:
&
url
,
info
:
ledger
,
log
:
log
.
New
(
"url"
,
url
)}
wallet
:=
&
ledgerWallet
{
hub
:
hub
,
url
:
&
url
,
info
:
ledger
,
log
:
log
.
New
(
"url"
,
url
)}
events
=
append
(
events
,
accounts
.
WalletEvent
{
Wallet
:
wallet
,
Arrive
:
true
})
events
=
append
(
events
,
accounts
.
WalletEvent
{
Wallet
:
wallet
,
Arrive
:
true
})
wallets
=
append
(
wallets
,
wallet
)
wallets
=
append
(
wallets
,
wallet
)
...
@@ -140,7 +157,7 @@ func (hub *LedgerHub) refreshWallets() {
...
@@ -140,7 +157,7 @@ func (hub *LedgerHub) refreshWallets() {
}
}
hub
.
refreshed
=
time
.
Now
()
hub
.
refreshed
=
time
.
Now
()
hub
.
wallets
=
wallets
hub
.
wallets
=
wallets
hub
.
l
ock
.
Unlock
()
hub
.
stateL
ock
.
Unlock
()
// Fire all wallet events and return
// Fire all wallet events and return
for
_
,
event
:=
range
events
{
for
_
,
event
:=
range
events
{
...
@@ -152,8 +169,8 @@ func (hub *LedgerHub) refreshWallets() {
...
@@ -152,8 +169,8 @@ func (hub *LedgerHub) refreshWallets() {
// receive notifications on the addition or removal of Ledger wallets.
// receive notifications on the addition or removal of Ledger wallets.
func
(
hub
*
LedgerHub
)
Subscribe
(
sink
chan
<-
accounts
.
WalletEvent
)
event
.
Subscription
{
func
(
hub
*
LedgerHub
)
Subscribe
(
sink
chan
<-
accounts
.
WalletEvent
)
event
.
Subscription
{
// We need the mutex to reliably start/stop the update loop
// We need the mutex to reliably start/stop the update loop
hub
.
l
ock
.
Lock
()
hub
.
stateL
ock
.
Lock
()
defer
hub
.
l
ock
.
Unlock
()
defer
hub
.
stateL
ock
.
Unlock
()
// Subscribe the caller and track the subscriber count
// Subscribe the caller and track the subscriber count
sub
:=
hub
.
updateScope
.
Track
(
hub
.
updateFeed
.
Subscribe
(
sink
))
sub
:=
hub
.
updateScope
.
Track
(
hub
.
updateFeed
.
Subscribe
(
sink
))
...
@@ -182,12 +199,12 @@ func (hub *LedgerHub) updater() {
...
@@ -182,12 +199,12 @@ func (hub *LedgerHub) updater() {
hub
.
refreshWallets
()
hub
.
refreshWallets
()
// If all our subscribers left, stop the updater
// If all our subscribers left, stop the updater
hub
.
l
ock
.
Lock
()
hub
.
stateL
ock
.
Lock
()
if
hub
.
updateScope
.
Count
()
==
0
{
if
hub
.
updateScope
.
Count
()
==
0
{
hub
.
updating
=
false
hub
.
updating
=
false
hub
.
l
ock
.
Unlock
()
hub
.
stateL
ock
.
Unlock
()
return
return
}
}
hub
.
l
ock
.
Unlock
()
hub
.
stateL
ock
.
Unlock
()
}
}
}
}
accounts/usbwallet/ledger_wallet.go
View file @
26da6daa
...
@@ -83,6 +83,7 @@ var errInvalidVersionReply = errors.New("invalid version reply")
...
@@ -83,6 +83,7 @@ var errInvalidVersionReply = errors.New("invalid version reply")
// ledgerWallet represents a live USB Ledger hardware wallet.
// ledgerWallet represents a live USB Ledger hardware wallet.
type
ledgerWallet
struct
{
type
ledgerWallet
struct
{
hub
*
LedgerHub
// USB hub the device originates from (TODO(karalabe): remove if hotplug lands on Windows)
url
*
accounts
.
URL
// Textual URL uniquely identifying this wallet
url
*
accounts
.
URL
// Textual URL uniquely identifying this wallet
info
hid
.
DeviceInfo
// Known USB device infos about the wallet
info
hid
.
DeviceInfo
// Known USB device infos about the wallet
...
@@ -576,6 +577,11 @@ func (w *ledgerWallet) SignTx(account accounts.Account, tx *types.Transaction, c
...
@@ -576,6 +577,11 @@ func (w *ledgerWallet) SignTx(account accounts.Account, tx *types.Transaction, c
<-
w
.
commsLock
<-
w
.
commsLock
defer
func
()
{
w
.
commsLock
<-
struct
{}{}
}()
defer
func
()
{
w
.
commsLock
<-
struct
{}{}
}()
// Ensure the device isn't screwed with while user confirmation is pending
// TODO(karalabe): remove if hotplug lands on Windows
w
.
hub
.
commsLock
.
RLock
()
defer
w
.
hub
.
commsLock
.
RUnlock
()
return
w
.
ledgerSign
(
path
,
account
.
Address
,
tx
,
chainID
)
return
w
.
ledgerSign
(
path
,
account
.
Address
,
tx
,
chainID
)
}
}
...
...
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