From 53372a1fe28898634e9cde468dbfc804e6815762 Mon Sep 17 00:00:00 2001 From: Thibaut Boustany Date: Fri, 27 Jul 2018 15:14:41 +0200 Subject: [PATCH 01/10] Using hw-transport-node-hid beta with usb devices detection --- package.json | 2 +- src/commands/listenDevices.js | 1 + yarn.lock | 25 ++++++++++++++++++++----- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a592f03e..25d7cffb 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@ledgerhq/hw-app-eth": "^4.14.0", "@ledgerhq/hw-app-xrp": "^4.13.0", "@ledgerhq/hw-transport": "^4.13.0", - "@ledgerhq/hw-transport-node-hid": "^4.13.0", + "@ledgerhq/hw-transport-node-hid": "^4.22.0-beta.ae6f5c51", "@ledgerhq/ledger-core": "2.0.0-rc.5", "@ledgerhq/live-common": "3.0.0-beta.2", "animated": "^0.2.2", diff --git a/src/commands/listenDevices.js b/src/commands/listenDevices.js index 011956e8..7a186b7d 100644 --- a/src/commands/listenDevices.js +++ b/src/commands/listenDevices.js @@ -7,6 +7,7 @@ import CommNodeHid from '@ledgerhq/hw-transport-node-hid' import { DEVICE_DISCONNECT_DEBOUNCE, LISTEN_DEVICES_POLLING_INTERVAL } from 'config/constants' CommNodeHid.setListenDevicesPollingInterval(LISTEN_DEVICES_POLLING_INTERVAL) +CommNodeHid.setListenDevicesDebug(true) const cmd = createCommand('listenDevices', () => Observable.create(o => { diff --git a/yarn.lock b/yarn.lock index 7dc25dc3..25ddc777 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1501,12 +1501,14 @@ "@ledgerhq/hw-transport" "^4.21.0" bip32-path "0.4.2" -"@ledgerhq/hw-transport-node-hid@^4.13.0": - version "4.21.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.21.0.tgz#fffdae5314bb969473a763e59fe1dfdde3fd7aed" +"@ledgerhq/hw-transport-node-hid@^4.22.0-beta.ae6f5c51": + version "4.22.0-beta.ae6f5c51" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.22.0-beta.ae6f5c51.tgz#36f5515c98af437d41653e854a613c462e65d9e1" dependencies: - "@ledgerhq/hw-transport" "^4.21.0" + "@ledgerhq/hw-transport" "^4.22.0-beta.ae6f5c51" + lodash "^4.17.10" node-hid "^0.7.2" + usb "^1.3.2" "@ledgerhq/hw-transport-node-hid@^4.7.6": version "4.16.0" @@ -1527,6 +1529,12 @@ dependencies: events "^2.0.0" +"@ledgerhq/hw-transport@^4.22.0-beta.ae6f5c51": + version "4.22.0-beta.ae6f5c51" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.22.0-beta.ae6f5c51.tgz#a9f17ff8fa792a19e01d82d72f14ff7f7a211209" + dependencies: + events "^2.0.0" + "@ledgerhq/ledger-core@2.0.0-rc.5": version "2.0.0-rc.5" resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.5.tgz#ec42f6c3cc265fc5ca82e01d27df38357642d3ed" @@ -9905,7 +9913,7 @@ mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nan@^2.10.0, nan@^2.2.1, nan@^2.6.2, nan@^2.9.2: +nan@^2.10.0, nan@^2.2.1, nan@^2.6.2, nan@^2.8.0, nan@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" @@ -14352,6 +14360,13 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +usb@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/usb/-/usb-1.3.2.tgz#4563a32323856e26c97dae374b34c66c3d83b5f4" + dependencies: + nan "^2.8.0" + node-pre-gyp "^0.10.0" + use@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" From 20297b6c2b2a0e8dc8843c700bbffb1b23549126 Mon Sep 17 00:00:00 2001 From: Thibaut Boustany Date: Mon, 30 Jul 2018 17:49:07 +0200 Subject: [PATCH 02/10] `retry` restored to fix comm error on app change --- src/helpers/deviceAccess.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helpers/deviceAccess.js b/src/helpers/deviceAccess.js index 05d9ced3..9104b769 100644 --- a/src/helpers/deviceAccess.js +++ b/src/helpers/deviceAccess.js @@ -4,6 +4,7 @@ import throttle from 'lodash/throttle' import type Transport from '@ledgerhq/hw-transport' import TransportNodeHid from '@ledgerhq/hw-transport-node-hid' import { DisconnectedDevice, CantOpenDevice } from 'config/errors' +import { retry } from './promise' // all open to device must use openDevice so we can prevent race conditions // and guarantee we do one device access at a time. It also will handle the .close() @@ -39,7 +40,7 @@ export const withDevice: WithDevice = devicePath => job => { busy = true refreshBusyUIState() try { - const t = await TransportNodeHid.open(devicePath).catch(mapError) + const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 1 }).catch(mapError).catch(mapError) t.setDebugMode(logger.apdu) try { const res = await job(t).catch(mapError) From 35c30e7ebde2206c8c5996a8ee912428a06c0f94 Mon Sep 17 00:00:00 2001 From: Thibaut Boustany Date: Mon, 30 Jul 2018 17:51:46 +0200 Subject: [PATCH 03/10] New `hw-transport-node-hid` version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 25d7cffb..bd69dd94 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@ledgerhq/hw-app-eth": "^4.14.0", "@ledgerhq/hw-app-xrp": "^4.13.0", "@ledgerhq/hw-transport": "^4.13.0", - "@ledgerhq/hw-transport-node-hid": "^4.22.0-beta.ae6f5c51", + "@ledgerhq/hw-transport-node-hid": "^4.22.0-beta.96c1e355", "@ledgerhq/ledger-core": "2.0.0-rc.5", "@ledgerhq/live-common": "3.0.0-beta.2", "animated": "^0.2.2", From caa193018088a6d7b7a3a15bf6aefad4abaf4cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Tue, 31 Jul 2018 11:09:23 +0200 Subject: [PATCH 04/10] Simplify listenDevices --- README.md | 1 - src/commands/listenDevices.js | 57 +++++------------------------------ src/config/constants.js | 3 +- 3 files changed, 9 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index fd4d0465..7ebf21be 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,6 @@ SYNC_ALL_INTERVAL=60000 CHECK_APP_INTERVAL_WHEN_INVALID=600 CHECK_APP_INTERVAL_WHEN_VALID=1200 CHECK_UPDATE_DELAY=5000 -DEVICE_DISCONNECT_DEBOUNCE=500 ``` ### Launch storybook diff --git a/src/commands/listenDevices.js b/src/commands/listenDevices.js index 7a186b7d..d0c9f48f 100644 --- a/src/commands/listenDevices.js +++ b/src/commands/listenDevices.js @@ -4,58 +4,17 @@ import logger from 'logger' import { createCommand } from 'helpers/ipc' import { Observable } from 'rxjs' import CommNodeHid from '@ledgerhq/hw-transport-node-hid' -import { DEVICE_DISCONNECT_DEBOUNCE, LISTEN_DEVICES_POLLING_INTERVAL } from 'config/constants' +import { LISTEN_DEVICES_DEBOUNCE } from 'config/constants' -CommNodeHid.setListenDevicesPollingInterval(LISTEN_DEVICES_POLLING_INTERVAL) -CommNodeHid.setListenDevicesDebug(true) +CommNodeHid.setListenDevicesPollingInterval(LISTEN_DEVICES_DEBOUNCE) -const cmd = createCommand('listenDevices', () => - Observable.create(o => { - const pendingRemovePerPath = {} - const sub = CommNodeHid.listen({ - next: e => { - // debounce the add/remove in case we see quick `remove,add` events on same path. - switch (e.type) { - case 'add': { - const pendingRemove = pendingRemovePerPath[e.descriptor] - if (pendingRemove) { - logger.warn(`Skipping remove/add usb event for ${e.descriptor}`) - // there where a recent "remove" event, we don't emit add because we didn't emit "remove" yet. - clearTimeout(pendingRemove) - delete pendingRemovePerPath[e.descriptor] - } else { - // if there were no recent "remove", we just emit the "add" - o.next(e) - } - break - } - case 'remove': { - // we we always debounce the "remove" event. emit it a bit later in case a "add" of same descriptor happen soon. - if (pendingRemovePerPath[e.descriptor]) { - clearTimeout(pendingRemovePerPath[e.descriptor]) - } - pendingRemovePerPath[e.descriptor] = setTimeout(() => { - delete pendingRemovePerPath[e.descriptor] - o.next(e) - }, DEVICE_DISCONNECT_DEBOUNCE) - break - } - default: - o.next(e) - } - }, - complete: () => { - o.complete() - }, - error: err => { - o.error(err) - }, - }) - return () => { - Object.keys(pendingRemovePerPath).map(k => clearTimeout(pendingRemovePerPath[k])) - sub.unsubscribe() - } +CommNodeHid.setListenDevicesDebug((msg, ...args) => + logger.debug(msg, { + type: 'listenDevices', + args, }), ) +const cmd = createCommand('listenDevices', () => Observable.create(CommNodeHid.listen)) + export default cmd diff --git a/src/config/constants.js b/src/config/constants.js index aefe35b3..3090cfe9 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -32,13 +32,12 @@ export const MIN_HEIGHT = intFromEnv('LEDGER_MIN_HEIGHT', 700) export const CHECK_APP_INTERVAL_WHEN_INVALID = 600 export const CHECK_APP_INTERVAL_WHEN_VALID = 1200 export const CHECK_UPDATE_DELAY = 5000 -export const DEVICE_DISCONNECT_DEBOUNCE = intFromEnv('LEDGER_DEVICE_DISCONNECT_DEBOUNCE', 1000) export const DEVICE_INFOS_TIMEOUT = intFromEnv('DEVICE_INFOS_TIMEOUT', 5 * 1000) export const GENUINE_CACHE_DELAY = intFromEnv('GENUINE_CACHE_DELAY', 1000) export const GENUINE_TIMEOUT = intFromEnv('GENUINE_TIMEOUT', 120 * 1000) export const GET_CALLS_RETRY = intFromEnv('GET_CALLS_RETRY', 2) export const GET_CALLS_TIMEOUT = intFromEnv('GET_CALLS_TIMEOUT', 30 * 1000) -export const LISTEN_DEVICES_POLLING_INTERVAL = intFromEnv('LISTEN_DEVICES_POLLING_INTERVAL', 1000) +export const LISTEN_DEVICES_DEBOUNCE = intFromEnv('LISTEN_DEVICES_DEBOUNCE', 200) // NB: technically speaking OUTDATED_CONSIDERED_DELAY should be set to ZERO. // but we'll only do that when we're sure the sync is performant and all is working smoothly export const OUTDATED_CONSIDERED_DELAY = intFromEnv('OUTDATED_CONSIDERED_DELAY', 2 * 60 * 1000) From 81e5ba3a4215dbff67c9d1909b99ba7c87479a40 Mon Sep 17 00:00:00 2001 From: Thibaut Boustany Date: Tue, 31 Jul 2018 11:44:16 +0200 Subject: [PATCH 05/10] Fix double catch --- src/helpers/deviceAccess.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/deviceAccess.js b/src/helpers/deviceAccess.js index 9104b769..f6903462 100644 --- a/src/helpers/deviceAccess.js +++ b/src/helpers/deviceAccess.js @@ -40,7 +40,9 @@ export const withDevice: WithDevice = devicePath => job => { busy = true refreshBusyUIState() try { - const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 1 }).catch(mapError).catch(mapError) + const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 1 }).catch( + mapError, + ) t.setDebugMode(logger.apdu) try { const res = await job(t).catch(mapError) From 9856c637415d879e7f116ea088e41f6a6839dd85 Mon Sep 17 00:00:00 2001 From: Thibaut Boustany Date: Tue, 31 Jul 2018 11:47:51 +0200 Subject: [PATCH 06/10] Renamed setListenDevicesPollingInterval to reflect new behavior --- package.json | 2 +- src/commands/listenDevices.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index bd69dd94..2653ac99 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@ledgerhq/hw-app-eth": "^4.14.0", "@ledgerhq/hw-app-xrp": "^4.13.0", "@ledgerhq/hw-transport": "^4.13.0", - "@ledgerhq/hw-transport-node-hid": "^4.22.0-beta.96c1e355", + "@ledgerhq/hw-transport-node-hid": "^4.22.0-beta.a1987cb3", "@ledgerhq/ledger-core": "2.0.0-rc.5", "@ledgerhq/live-common": "3.0.0-beta.2", "animated": "^0.2.2", diff --git a/src/commands/listenDevices.js b/src/commands/listenDevices.js index d0c9f48f..8deea524 100644 --- a/src/commands/listenDevices.js +++ b/src/commands/listenDevices.js @@ -6,7 +6,7 @@ import { Observable } from 'rxjs' import CommNodeHid from '@ledgerhq/hw-transport-node-hid' import { LISTEN_DEVICES_DEBOUNCE } from 'config/constants' -CommNodeHid.setListenDevicesPollingInterval(LISTEN_DEVICES_DEBOUNCE) +CommNodeHid.setListenDevicesDebounce(LISTEN_DEVICES_DEBOUNCE) CommNodeHid.setListenDevicesDebug((msg, ...args) => logger.debug(msg, { From acae959a3124cce4700302e776ec83f97a4c4b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Tue, 31 Jul 2018 11:58:03 +0200 Subject: [PATCH 07/10] CI --- .circleci/config.yml | 1 + package.json | 2 +- yarn.lock | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7ceba1c7..b0b6394a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,6 +9,7 @@ jobs: build: <<: *defaults steps: + - run: sudo apt-get install -y libudev-dev - checkout - restore_cache: keys: diff --git a/package.json b/package.json index 2653ac99..663fe82c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@ledgerhq/hw-app-eth": "^4.14.0", "@ledgerhq/hw-app-xrp": "^4.13.0", "@ledgerhq/hw-transport": "^4.13.0", - "@ledgerhq/hw-transport-node-hid": "^4.22.0-beta.a1987cb3", + "@ledgerhq/hw-transport-node-hid": "4.22.0-beta.a1987cb3", "@ledgerhq/ledger-core": "2.0.0-rc.5", "@ledgerhq/live-common": "3.0.0-beta.2", "animated": "^0.2.2", diff --git a/yarn.lock b/yarn.lock index 25ddc777..f310666d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1501,11 +1501,11 @@ "@ledgerhq/hw-transport" "^4.21.0" bip32-path "0.4.2" -"@ledgerhq/hw-transport-node-hid@^4.22.0-beta.ae6f5c51": - version "4.22.0-beta.ae6f5c51" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.22.0-beta.ae6f5c51.tgz#36f5515c98af437d41653e854a613c462e65d9e1" +"@ledgerhq/hw-transport-node-hid@4.22.0-beta.a1987cb3": + version "4.22.0-beta.a1987cb3" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.22.0-beta.a1987cb3.tgz#89dd5b30239ed81e41fd3a1a37a48d5e9cd8529b" dependencies: - "@ledgerhq/hw-transport" "^4.22.0-beta.ae6f5c51" + "@ledgerhq/hw-transport" "^4.22.0-beta.a1987cb3" lodash "^4.17.10" node-hid "^0.7.2" usb "^1.3.2" @@ -1529,7 +1529,7 @@ dependencies: events "^2.0.0" -"@ledgerhq/hw-transport@^4.22.0-beta.ae6f5c51": +"@ledgerhq/hw-transport@^4.22.0-beta.a1987cb3": version "4.22.0-beta.ae6f5c51" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.22.0-beta.ae6f5c51.tgz#a9f17ff8fa792a19e01d82d72f14ff7f7a211209" dependencies: From ad10c61ba2746782597313d659154de2ab10840e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Tue, 31 Jul 2018 12:03:06 +0200 Subject: [PATCH 08/10] silent one flow type --- src/helpers/deviceAccess.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/deviceAccess.js b/src/helpers/deviceAccess.js index f6903462..21e97c48 100644 --- a/src/helpers/deviceAccess.js +++ b/src/helpers/deviceAccess.js @@ -40,6 +40,7 @@ export const withDevice: WithDevice = devicePath => job => { busy = true refreshBusyUIState() try { + // $FlowFixMe not sure what's wrong const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 1 }).catch( mapError, ) From 842e9c2edaa2065990585f55c7e0e41b3900f566 Mon Sep 17 00:00:00 2001 From: Thibaut Boustany Date: Tue, 31 Jul 2018 15:41:15 +0200 Subject: [PATCH 09/10] Fix communication error on app change for Windows and Linux --- src/helpers/deviceAccess.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/deviceAccess.js b/src/helpers/deviceAccess.js index 21e97c48..4d457b78 100644 --- a/src/helpers/deviceAccess.js +++ b/src/helpers/deviceAccess.js @@ -41,7 +41,7 @@ export const withDevice: WithDevice = devicePath => job => { refreshBusyUIState() try { // $FlowFixMe not sure what's wrong - const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 1 }).catch( + const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 2 }).catch( mapError, ) t.setDebugMode(logger.apdu) From afe7f33b683d641f8d9737e857aea6c09e441cce Mon Sep 17 00:00:00 2001 From: Thibaut Boustany Date: Tue, 31 Jul 2018 15:42:54 +0200 Subject: [PATCH 10/10] hw-transport-node-hid out of beta --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 663fe82c..fa2ecf52 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@ledgerhq/hw-app-eth": "^4.14.0", "@ledgerhq/hw-app-xrp": "^4.13.0", "@ledgerhq/hw-transport": "^4.13.0", - "@ledgerhq/hw-transport-node-hid": "4.22.0-beta.a1987cb3", + "@ledgerhq/hw-transport-node-hid": "4.22.0", "@ledgerhq/ledger-core": "2.0.0-rc.5", "@ledgerhq/live-common": "3.0.0-beta.2", "animated": "^0.2.2",