@@ -74,6 +74,11 @@ const (
74
74
ledgerP2ReturnAddressChainCode ledgerParam2 = 0x01 // Require a user confirmation before returning the address
75
75
)
76
76
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
+
77
82
// ledgerWallet represents a live USB Ledger hardware wallet.
78
83
type ledgerWallet struct {
79
84
context * usb.Context // USB context to interface libusb through
@@ -87,6 +92,7 @@ type ledgerWallet struct {
87
92
failure error // Any failure that would make the device unusable
88
93
89
94
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)
90
96
accounts []accounts.Account // List of derive accounts pinned on the Ledger
91
97
paths map [common.Address ]accounts.DerivationPath // Known derivation paths for signing operations
92
98
@@ -138,6 +144,9 @@ func (w *ledgerWallet) Status() string {
138
144
if w .device == nil {
139
145
return "Closed"
140
146
}
147
+ if w .browser {
148
+ return "Ethereum app in browser mode"
149
+ }
141
150
if w .offline () {
142
151
return "Ethereum app offline"
143
152
}
@@ -239,7 +248,10 @@ func (w *ledgerWallet) Open(passphrase string) error {
239
248
}()
240
249
241
250
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
+ }
243
255
return nil
244
256
}
245
257
// Try to resolve the Ethereum app's version, will fail prior to v1.0.2
@@ -351,7 +363,8 @@ func (w *ledgerWallet) close() error {
351
363
err := w .device .Close ()
352
364
353
365
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
355
368
356
369
return err
357
370
}
@@ -463,7 +476,7 @@ func (w *ledgerWallet) selfDerive() {
463
476
464
477
// Display a log message to the user for new (or previously empty accounts)
465
478
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 )
467
480
}
468
481
// Fetch the next potential account
469
482
if ! empty {
@@ -909,7 +922,7 @@ func (w *ledgerWallet) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 l
909
922
}
910
923
// Make sure the transport header matches
911
924
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
913
926
}
914
927
// If it's the first chunk, retrieve the total message length
915
928
if chunk [3 ] == 0x00 && chunk [4 ] == 0x00 {
0 commit comments