Skip to content

Commit c7022c1

Browse files
committed
accounts/usbwallet: detect and report in Ledger is in browser mode
1 parent 26cd41f commit c7022c1

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

accounts/usbwallet/ledger_wallet.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ const (
7474
ledgerP2ReturnAddressChainCode ledgerParam2 = 0x01 // Require a user confirmation before returning the address
7575
)
7676

77+
// errReplyInvalidHeader is the error message returned by a Ledfer data exchange
78+
// if the device replies with a mismatching header. This usually means the device
79+
// is in browser mode.
80+
var errReplyInvalidHeader = errors.New("invalid reply header")
81+
7782
// ledgerWallet represents a live USB Ledger hardware wallet.
7883
type ledgerWallet struct {
7984
context *usb.Context // USB context to interface libusb through
@@ -87,6 +92,7 @@ type ledgerWallet struct {
8792
failure error // Any failure that would make the device unusable
8893

8994
version [3]byte // Current version of the Ledger Ethereum app (zero if app is offline)
95+
browser bool // Flag whether the Ledger is in browser mode (reply channel mismatch)
9096
accounts []accounts.Account // List of derive accounts pinned on the Ledger
9197
paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations
9298

@@ -138,6 +144,9 @@ func (w *ledgerWallet) Status() string {
138144
if w.device == nil {
139145
return "Closed"
140146
}
147+
if w.browser {
148+
return "Ethereum app in browser mode"
149+
}
141150
if w.offline() {
142151
return "Ethereum app offline"
143152
}
@@ -239,7 +248,10 @@ func (w *ledgerWallet) Open(passphrase string) error {
239248
}()
240249

241250
if _, err = w.ledgerDerive(accounts.DefaultBaseDerivationPath); err != nil {
242-
// Ethereum app is not running, nothing more to do, return
251+
// Ethereum app is not running or in browser mode, nothing more to do, return
252+
if err == errReplyInvalidHeader {
253+
w.browser = true
254+
}
243255
return nil
244256
}
245257
// Try to resolve the Ethereum app's version, will fail prior to v1.0.2
@@ -351,7 +363,8 @@ func (w *ledgerWallet) close() error {
351363
err := w.device.Close()
352364

353365
w.device, w.input, w.output = nil, nil, nil
354-
w.version, w.accounts, w.paths = [3]byte{}, nil, nil
366+
w.browser, w.version = false, [3]byte{}
367+
w.accounts, w.paths = nil, nil
355368

356369
return err
357370
}
@@ -463,7 +476,7 @@ func (w *ledgerWallet) selfDerive() {
463476

464477
// Display a log message to the user for new (or previously empty accounts)
465478
if _, known := w.paths[nextAddr]; !known || (!empty && nextAddr == w.deriveNextAddr) {
466-
glog.V(logger.Info).Infof("%s discovered %s (balance %d, nonce %d) at %s", w.url.String(), nextAddr.Hex(), balance, nonce, path)
479+
glog.V(logger.Info).Infof("%s discovered %s (balance %22v, nonce %4d) at %s", w.url.String(), nextAddr.Hex(), balance, nonce, path)
467480
}
468481
// Fetch the next potential account
469482
if !empty {
@@ -909,7 +922,7 @@ func (w *ledgerWallet) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 l
909922
}
910923
// Make sure the transport header matches
911924
if chunk[0] != 0x01 || chunk[1] != 0x01 || chunk[2] != 0x05 {
912-
return nil, fmt.Errorf("invalid reply header: %x", chunk[:3])
925+
return nil, errReplyInvalidHeader
913926
}
914927
// If it's the first chunk, retrieve the total message length
915928
if chunk[3] == 0x00 && chunk[4] == 0x00 {

0 commit comments

Comments
 (0)