@@ -192,6 +192,9 @@ func (w *ledgerWallet) Open(passphrase string) error {
192192 if err != nil {
193193 return err
194194 }
195+ if len (devices ) == 0 {
196+ return accounts .ErrUnknownWallet
197+ }
195198 // Device opened, attach to the input and output endpoints
196199 device := devices [0 ]
197200
@@ -767,7 +770,7 @@ func (w *ledgerWallet) ledgerDerive(derivationPath []uint32) (common.Address, er
767770func (w * ledgerWallet ) ledgerSign (derivationPath []uint32 , address common.Address , tx * types.Transaction , chainID * big.Int ) (* types.Transaction , error ) {
768771 // We need to modify the timeouts to account for user feedback
769772 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
771774
772775 // Flatten the derivation path into the Ledger request
773776 path := make ([]byte , 1 + 4 * len (derivationPath ))
@@ -823,7 +826,7 @@ func (w *ledgerWallet) ledgerSign(derivationPath []uint32, address common.Addres
823826 signer = new (types.HomesteadSigner )
824827 } else {
825828 signer = types .NewEIP155Signer (chainID )
826- signature [64 ] = ( signature [64 ]- 34 ) / 2 - byte (chainID .Uint64 ())
829+ signature [64 ] = signature [64 ] - byte (chainID .Uint64 ()* 2 + 35 )
827830 }
828831 // Inject the final signature into the transaction and sanity check the sender
829832 signed , err := tx .WithSignature (signer , signature )
@@ -875,45 +878,42 @@ func (w *ledgerWallet) ledgerSign(derivationPath []uint32, address common.Addres
875878// Optional APDU data | arbitrary
876879func (w * ledgerWallet ) ledgerExchange (opcode ledgerOpcode , p1 ledgerParam1 , p2 ledgerParam2 , data []byte ) ([]byte , error ) {
877880 // 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+
896887 // 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 )
901891
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 ))
903896
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+ }
904904 // Send over to the device
905905 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 )
907907 }
908- if _ , err := w .input .Write (msg ); err != nil {
908+ if _ , err := w .input .Write (chunk ); err != nil {
909909 return nil , err
910910 }
911911 }
912912 // Stream the reply back from the wallet in 64 byte chunks
913913 var reply []byte
914+ chunk = chunk [:64 ] // Yeah, we surely have enough space
914915 for {
915916 // Read the next chunk from the Ledger wallet
916- chunk := make ([]byte , 64 )
917917 if _ , err := io .ReadFull (w .output , chunk ); err != nil {
918918 return nil , err
919919 }
@@ -925,17 +925,19 @@ func (w *ledgerWallet) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 l
925925 return nil , errReplyInvalidHeader
926926 }
927927 // If it's the first chunk, retrieve the total message length
928+ var payload []byte
929+
928930 if chunk [3 ] == 0x00 && chunk [4 ] == 0x00 {
929931 reply = make ([]byte , 0 , int (binary .BigEndian .Uint16 (chunk [5 :7 ])))
930- chunk = chunk [7 :]
932+ payload = chunk [7 :]
931933 } else {
932- chunk = chunk [5 :]
934+ payload = chunk [5 :]
933935 }
934936 // 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 ... )
937939 } else {
938- reply = append (reply , chunk [:left ]... )
940+ reply = append (reply , payload [:left ]... )
939941 break
940942 }
941943 }
0 commit comments