@@ -192,6 +192,9 @@ func (w *ledgerWallet) Open(passphrase string) error {
192
192
if err != nil {
193
193
return err
194
194
}
195
+ if len (devices ) == 0 {
196
+ return accounts .ErrUnknownWallet
197
+ }
195
198
// Device opened, attach to the input and output endpoints
196
199
device := devices [0 ]
197
200
@@ -767,7 +770,7 @@ func (w *ledgerWallet) ledgerDerive(derivationPath []uint32) (common.Address, er
767
770
func (w * ledgerWallet ) ledgerSign (derivationPath []uint32 , address common.Address , tx * types.Transaction , chainID * big.Int ) (* types.Transaction , error ) {
768
771
// We need to modify the timeouts to account for user feedback
769
772
defer func (old time.Duration ) { w .device .ReadTimeout = old }(w .device .ReadTimeout )
770
- w .device .ReadTimeout = time .Minute
773
+ w .device .ReadTimeout = time .Hour * 24 * 30 // Timeout requires a Ledger power cycle, only if you must
771
774
772
775
// Flatten the derivation path into the Ledger request
773
776
path := make ([]byte , 1 + 4 * len (derivationPath ))
@@ -823,7 +826,7 @@ func (w *ledgerWallet) ledgerSign(derivationPath []uint32, address common.Addres
823
826
signer = new (types.HomesteadSigner )
824
827
} else {
825
828
signer = types .NewEIP155Signer (chainID )
826
- signature [64 ] = ( signature [64 ]- 34 ) / 2 - byte (chainID .Uint64 ())
829
+ signature [64 ] = signature [64 ] - byte (chainID .Uint64 ()* 2 + 35 )
827
830
}
828
831
// Inject the final signature into the transaction and sanity check the sender
829
832
signed , err := tx .WithSignature (signer , signature )
@@ -875,45 +878,42 @@ func (w *ledgerWallet) ledgerSign(derivationPath []uint32, address common.Addres
875
878
// Optional APDU data | arbitrary
876
879
func (w * ledgerWallet ) ledgerExchange (opcode ledgerOpcode , p1 ledgerParam1 , p2 ledgerParam2 , data []byte ) ([]byte , error ) {
877
880
// Construct the message payload, possibly split into multiple chunks
878
- var chunks [][]byte
879
- for left := data ; len (left ) > 0 || len (chunks ) == 0 ; {
880
- // Create the chunk header
881
- var chunk []byte
882
-
883
- if len (chunks ) == 0 {
884
- // The first chunk encodes the length and all the opcodes
885
- chunk = []byte {0x00 , 0x00 , 0xe0 , byte (opcode ), byte (p1 ), byte (p2 ), byte (len (data ))}
886
- binary .BigEndian .PutUint16 (chunk , uint16 (5 + len (data )))
887
- }
888
- // Append the data blob to the end of the chunk
889
- space := 64 - len (chunk ) - 5 // 5 == header size
890
- if len (left ) > space {
891
- chunks , left = append (chunks , append (chunk , left [:space ]... )), left [space :]
892
- continue
893
- }
894
- chunks , left = append (chunks , append (chunk , left ... )), nil
895
- }
881
+ apdu := make ([]byte , 2 , 7 + len (data ))
882
+
883
+ binary .BigEndian .PutUint16 (apdu , uint16 (5 + len (data )))
884
+ apdu = append (apdu , []byte {0xe0 , byte (opcode ), byte (p1 ), byte (p2 ), byte (len (data ))}... )
885
+ apdu = append (apdu , data ... )
886
+
896
887
// Stream all the chunks to the device
897
- for i , chunk := range chunks {
898
- // Construct the new message to stream
899
- header := []byte {0x01 , 0x01 , 0x05 , 0x00 , 0x00 } // Channel ID and command tag appended
900
- binary .BigEndian .PutUint16 (header [3 :], uint16 (i ))
888
+ header := []byte {0x01 , 0x01 , 0x05 , 0x00 , 0x00 } // Channel ID and command tag appended
889
+ chunk := make ([]byte , 64 )
890
+ space := len (chunk ) - len (header )
901
891
902
- msg := append (header , chunk ... )
892
+ for i := 0 ; len (apdu ) > 0 ; i ++ {
893
+ // Construct the new message to stream
894
+ chunk = append (chunk [:0 ], header ... )
895
+ binary .BigEndian .PutUint16 (chunk [3 :], uint16 (i ))
903
896
897
+ if len (apdu ) > space {
898
+ chunk = append (chunk , apdu [:space ]... )
899
+ apdu = apdu [space :]
900
+ } else {
901
+ chunk = append (chunk , apdu ... )
902
+ apdu = nil
903
+ }
904
904
// Send over to the device
905
905
if glog .V (logger .Detail ) {
906
- glog .Infof ("-> %03d.%03d: %x" , w .device .Bus , w .device .Address , msg )
906
+ glog .Infof ("-> %03d.%03d: %x" , w .device .Bus , w .device .Address , chunk )
907
907
}
908
- if _ , err := w .input .Write (msg ); err != nil {
908
+ if _ , err := w .input .Write (chunk ); err != nil {
909
909
return nil , err
910
910
}
911
911
}
912
912
// Stream the reply back from the wallet in 64 byte chunks
913
913
var reply []byte
914
+ chunk = chunk [:64 ] // Yeah, we surely have enough space
914
915
for {
915
916
// Read the next chunk from the Ledger wallet
916
- chunk := make ([]byte , 64 )
917
917
if _ , err := io .ReadFull (w .output , chunk ); err != nil {
918
918
return nil , err
919
919
}
@@ -925,17 +925,19 @@ func (w *ledgerWallet) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 l
925
925
return nil , errReplyInvalidHeader
926
926
}
927
927
// If it's the first chunk, retrieve the total message length
928
+ var payload []byte
929
+
928
930
if chunk [3 ] == 0x00 && chunk [4 ] == 0x00 {
929
931
reply = make ([]byte , 0 , int (binary .BigEndian .Uint16 (chunk [5 :7 ])))
930
- chunk = chunk [7 :]
932
+ payload = chunk [7 :]
931
933
} else {
932
- chunk = chunk [5 :]
934
+ payload = chunk [5 :]
933
935
}
934
936
// Append to the reply and stop when filled up
935
- if left := cap (reply ) - len (reply ); left > len (chunk ) {
936
- reply = append (reply , chunk ... )
937
+ if left := cap (reply ) - len (reply ); left > len (payload ) {
938
+ reply = append (reply , payload ... )
937
939
} else {
938
- reply = append (reply , chunk [:left ]... )
940
+ reply = append (reply , payload [:left ]... )
939
941
break
940
942
}
941
943
}
0 commit comments