@onekeyfe/hd-core 1.2.0-alpha.135 → 1.2.0-alpha.136
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/DeviceCommands.test.ts +1 -1
- package/__tests__/device-lifecycle-events.test.ts +17 -21
- package/__tests__/device-wallet-session-store.test.ts +79 -21
- package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +1 -37
- package/__tests__/protocol-v2-unlock-policy.test.ts +0 -59
- package/__tests__/protocol-v2.test.ts +20 -52
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
- package/dist/api/device/DeviceVerify.d.ts +0 -1
- package/dist/api/device/DeviceVerify.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/index.js +61 -41
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +68 -25
- package/src/api/device/DeviceChangePin.ts +1 -4
- package/src/api/device/DeviceVerify.ts +0 -9
- package/src/api/device/DeviceWipe.ts +1 -4
- package/src/device/Device.ts +42 -17
- package/src/device/DeviceCommands.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -43538,7 +43538,7 @@ const DEVICE_CONTROL_CALLS = new Set([
|
|
|
43538
43538
|
'DeviceCertificateSign',
|
|
43539
43539
|
'DeviceMiscUsbMscControl',
|
|
43540
43540
|
]);
|
|
43541
|
-
const isProtocolV2ActionCancelledMessage = (message) => /^(?:cancel(?:led|ed)(?: on device)?|confirm dismissed|
|
|
43541
|
+
const isProtocolV2ActionCancelledMessage = (message) => /^(?:cancel(?:led|ed)(?: on device)?|confirm dismissed|user cancel(?:led|ed)(?:\s+.*)?)$/i.test(message);
|
|
43542
43542
|
function shouldReduceDebugForCall(type) {
|
|
43543
43543
|
return HIGH_VOLUME_DEBUG_CALLS.has(type);
|
|
43544
43544
|
}
|
|
@@ -45617,15 +45617,6 @@ class Device extends events.exports {
|
|
|
45617
45617
|
yield TransportManager.reconfigure(this.features);
|
|
45618
45618
|
});
|
|
45619
45619
|
const expectedDeviceId = options === null || options === void 0 ? void 0 : options.deviceId;
|
|
45620
|
-
if (expectedDeviceId) {
|
|
45621
|
-
this.passphraseState = undefined;
|
|
45622
|
-
const { message } = yield this.commands.typedCall('GetFeatures', 'Features', {});
|
|
45623
|
-
this._updateFeatures(message);
|
|
45624
|
-
yield TransportManager.reconfigure(this.features);
|
|
45625
|
-
if (!this.checkDeviceId(expectedDeviceId)) {
|
|
45626
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
|
|
45627
|
-
}
|
|
45628
|
-
}
|
|
45629
45620
|
this.passphraseState = options === null || options === void 0 ? void 0 : options.passphraseState;
|
|
45630
45621
|
if (options === null || options === void 0 ? void 0 : options.initSession) {
|
|
45631
45622
|
this.clearInternalState(options === null || options === void 0 ? void 0 : options.deviceId);
|
|
@@ -45641,7 +45632,23 @@ class Device extends events.exports {
|
|
|
45641
45632
|
if (options === null || options === void 0 ? void 0 : options.deriveCardano) {
|
|
45642
45633
|
payload.derive_cardano = true;
|
|
45643
45634
|
}
|
|
45644
|
-
|
|
45635
|
+
if (this.features) {
|
|
45636
|
+
yield TransportManager.reconfigure(this.features);
|
|
45637
|
+
}
|
|
45638
|
+
const assertExpectedDeviceIdentity = () => {
|
|
45639
|
+
if (expectedDeviceId && !this.checkDeviceId(expectedDeviceId)) {
|
|
45640
|
+
this.clearInternalState();
|
|
45641
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
|
|
45642
|
+
}
|
|
45643
|
+
};
|
|
45644
|
+
try {
|
|
45645
|
+
yield callInitialize(payload, options === null || options === void 0 ? void 0 : options.initSession);
|
|
45646
|
+
}
|
|
45647
|
+
catch (error) {
|
|
45648
|
+
assertExpectedDeviceIdentity();
|
|
45649
|
+
throw error;
|
|
45650
|
+
}
|
|
45651
|
+
assertExpectedDeviceIdentity();
|
|
45645
45652
|
}
|
|
45646
45653
|
catch (error) {
|
|
45647
45654
|
Log$h.error('Initialization failed:', error);
|
|
@@ -46115,17 +46122,14 @@ class Device extends events.exports {
|
|
|
46115
46122
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
|
|
46116
46123
|
const cleanupPromise = this.runCleanupPromise;
|
|
46117
46124
|
const { cancelableAction } = this;
|
|
46118
|
-
const env = DataManager.getSettings('env');
|
|
46119
46125
|
if (cancelableAction) {
|
|
46120
46126
|
yield cancelableAction(error);
|
|
46121
46127
|
}
|
|
46122
46128
|
else if (this.isProtocolV2() &&
|
|
46123
|
-
|
|
46124
|
-
DataManager.isBrowserWebUsb(env) ||
|
|
46125
|
-
DataManager.isDesktopWebUsb(env)) &&
|
|
46129
|
+
DataManager.isBleConnect(DataManager.getSettings('env')) &&
|
|
46126
46130
|
this.hasDeviceAcquire()) {
|
|
46127
46131
|
yield ((_b = (_a = this.commands) === null || _a === void 0 ? void 0 : _a.cancelDevice) === null || _b === void 0 ? void 0 : _b.call(_a).catch(cancelError => {
|
|
46128
|
-
Log$h.debug('Protocol V2 fallback cancel error', cancelError);
|
|
46132
|
+
Log$h.debug('Protocol V2 BLE fallback cancel error', cancelError);
|
|
46129
46133
|
}));
|
|
46130
46134
|
}
|
|
46131
46135
|
yield ((_c = this.commands) === null || _c === void 0 ? void 0 : _c.cancel());
|
|
@@ -48180,7 +48184,6 @@ class DeviceChangePin extends BaseMethod {
|
|
|
48180
48184
|
}
|
|
48181
48185
|
init() {
|
|
48182
48186
|
this.unlockPolicy = 'unlock-before-run';
|
|
48183
|
-
this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
|
|
48184
48187
|
this.useDevicePassphraseState = false;
|
|
48185
48188
|
validateParams(this.payload, [{ name: 'remove', type: 'boolean' }]);
|
|
48186
48189
|
this.params = {
|
|
@@ -48790,12 +48793,7 @@ class DeviceSupportFeatures extends BaseMethod {
|
|
|
48790
48793
|
}
|
|
48791
48794
|
|
|
48792
48795
|
class DeviceVerify extends BaseMethod {
|
|
48793
|
-
getSupportedProtocols() {
|
|
48794
|
-
return ['V1', 'V2'];
|
|
48795
|
-
}
|
|
48796
48796
|
init() {
|
|
48797
|
-
this.unlockPolicy = 'unlock-before-run';
|
|
48798
|
-
this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
|
|
48799
48797
|
this.useDevicePassphraseState = false;
|
|
48800
48798
|
validateParams(this.payload, [{ name: 'dataHex', type: 'hexString' }]);
|
|
48801
48799
|
this.params = {
|
|
@@ -48834,7 +48832,6 @@ class DeviceWipe extends BaseMethod {
|
|
|
48834
48832
|
}
|
|
48835
48833
|
init() {
|
|
48836
48834
|
this.unlockPolicy = 'unlock-before-run';
|
|
48837
|
-
this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
|
|
48838
48835
|
this.useDevicePassphraseState = false;
|
|
48839
48836
|
this.protocolV2UiInteraction = {
|
|
48840
48837
|
request: 'button',
|
|
@@ -51722,8 +51719,9 @@ const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
|
|
|
51722
51719
|
const PROTOCOL_V2_FINAL_RECONNECT_TIMEOUT = 3 * 60 * 1000;
|
|
51723
51720
|
const PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT = 5 * 1000;
|
|
51724
51721
|
const PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT = 15 * 1000;
|
|
51725
|
-
const PROTOCOL_V2_INSTALL_TIMEOUT =
|
|
51722
|
+
const PROTOCOL_V2_INSTALL_TIMEOUT = 8 * 60 * 1000;
|
|
51726
51723
|
const PROTOCOL_V2_INSTALL_STATUS_INITIAL_DELAY = 1000;
|
|
51724
|
+
const PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT = 30 * 1000;
|
|
51727
51725
|
const PROTOCOL_V2_TARGET_STATUS_PENDING = 0;
|
|
51728
51726
|
const PROTOCOL_V2_TARGET_STATUS_IN_PROGRESS = 1;
|
|
51729
51727
|
const PROTOCOL_V2_TARGET_STATUS_FINISHED = 2;
|
|
@@ -51737,8 +51735,6 @@ const PROTOCOL_V2_CONNECT_SINGLE_TIMEOUT = 75 * 1000;
|
|
|
51737
51735
|
const PROTOCOL_V2_DEVICE_INFO_READY_TIMEOUT = 30 * 1000;
|
|
51738
51736
|
const PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT = 3;
|
|
51739
51737
|
const PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE = 'FirmwareInstallStatusConflict';
|
|
51740
|
-
const PROTOCOL_V2_INSTALL_FAILED_CODE = 'FirmwareInstallFailed';
|
|
51741
|
-
const PROTOCOL_V2_INSTALL_TIMEOUT_CODE = 'FirmwareInstallTimeout';
|
|
51742
51738
|
const PROTOCOL_V2_OKPP_HEADER_SIZE = 0x52a0;
|
|
51743
51739
|
const PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET = 0x200;
|
|
51744
51740
|
const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET = 0x240;
|
|
@@ -51894,8 +51890,7 @@ const isProtocolV2FirmwareStatusEndpointUnavailable = (error) => {
|
|
|
51894
51890
|
const isProtocolV2TerminalInstallStatusError = (error) => {
|
|
51895
51891
|
var _a;
|
|
51896
51892
|
return error instanceof hdShared.HardwareError &&
|
|
51897
|
-
(error.errorCode === hdShared.HardwareErrorCode.
|
|
51898
|
-
error.errorCode === hdShared.HardwareErrorCode.FirmwareError ||
|
|
51893
|
+
(error.errorCode === hdShared.HardwareErrorCode.FirmwareError ||
|
|
51899
51894
|
error.errorCode === hdShared.HardwareErrorCode.FirmwareVerificationFailed ||
|
|
51900
51895
|
((_a = error.params) === null || _a === void 0 ? void 0 : _a.firmwareUpdateCode) === PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE);
|
|
51901
51896
|
};
|
|
@@ -52037,7 +52032,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52037
52032
|
this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
|
|
52038
52033
|
this.requireDeviceMode = [];
|
|
52039
52034
|
this.unlockPolicy = 'unlock-before-run';
|
|
52040
|
-
this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
|
|
52041
52035
|
this.useDevicePassphraseState = false;
|
|
52042
52036
|
this.skipForceUpdateCheck = true;
|
|
52043
52037
|
const { payload } = this;
|
|
@@ -52771,9 +52765,8 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52771
52765
|
? visibleVersions[target]
|
|
52772
52766
|
: `${Math.floor(statusVersion / 0x10000) % 0x100}.${Math.floor(statusVersion / 0x100) % 0x100}.${statusVersion % 0x100}`;
|
|
52773
52767
|
if (!observedVersion) {
|
|
52774
|
-
|
|
52775
|
-
|
|
52776
|
-
Log$7.warn(`Protocol V2 target ${target} has no observable final version; install completion is authoritative`);
|
|
52768
|
+
if (this.protocolV2FinalStatusVerified) {
|
|
52769
|
+
Log$7.warn(`Protocol V2 target ${target} has no observable final version; completed target status is authoritative`);
|
|
52777
52770
|
}
|
|
52778
52771
|
else {
|
|
52779
52772
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareVerificationFailed, `Protocol V2 target ${target} has no observable final version after status fallback`);
|
|
@@ -53443,6 +53436,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53443
53436
|
});
|
|
53444
53437
|
}
|
|
53445
53438
|
assertProtocolV2TargetStatus(statusTargets, expectedTargetIds, expectedPaths = new Map()) {
|
|
53439
|
+
var _a, _b, _c;
|
|
53446
53440
|
Log$7.log(`[FirmwareUpdateV4] DeviceFirmwareUpdateStatus records=${JSON.stringify(statusTargets)}`);
|
|
53447
53441
|
const failedTarget = statusTargets.find(target => {
|
|
53448
53442
|
var _a;
|
|
@@ -53457,9 +53451,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53457
53451
|
path: failedTarget.path,
|
|
53458
53452
|
});
|
|
53459
53453
|
Log$7.error(`[FirmwareUpdateV4] firmware install failed target=${failedTargetDetails}`);
|
|
53460
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError,
|
|
53461
|
-
firmwareUpdateCode: PROTOCOL_V2_INSTALL_FAILED_CODE,
|
|
53462
|
-
});
|
|
53454
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, `Protocol V2 firmware target failed: target=${failedTarget.target_id} status=${(_a = failedTarget.status) !== null && _a !== void 0 ? _a : 'unknown'} payloadVersion=${(_b = failedTarget.payload_version) !== null && _b !== void 0 ? _b : 'unknown'} path=${(_c = failedTarget.path) !== null && _c !== void 0 ? _c : 'unknown'}`);
|
|
53463
53455
|
}
|
|
53464
53456
|
const matchingTargets = statusTargets.filter(target => { var _a; return expectedTargetIds.has((_a = normalizeProtocolV2TargetId(target.target_id)) !== null && _a !== void 0 ? _a : -1); });
|
|
53465
53457
|
const seenTargetIds = new Set();
|
|
@@ -53468,8 +53460,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53468
53460
|
if (targetId === undefined ||
|
|
53469
53461
|
seenTargetIds.has(targetId) ||
|
|
53470
53462
|
(target.path && expectedPaths.get(targetId) && target.path !== expectedPaths.get(targetId))) {
|
|
53471
|
-
|
|
53472
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, undefined, {
|
|
53463
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 install status conflicts with target ${target.target_id}`, {
|
|
53473
53464
|
firmwareUpdateCode: PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE,
|
|
53474
53465
|
});
|
|
53475
53466
|
}
|
|
@@ -53562,8 +53553,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53562
53553
|
let lastError;
|
|
53563
53554
|
let shouldReconnect = false;
|
|
53564
53555
|
let deviceInfo;
|
|
53556
|
+
let missingTargetStatusSince;
|
|
53557
|
+
let missingTargetStatusKey;
|
|
53558
|
+
let normalModeWithoutInstallEvidenceSince;
|
|
53565
53559
|
let installEvidenceObserved = false;
|
|
53566
53560
|
let currentInstallStatusObserved = false;
|
|
53561
|
+
const resetMissingTargetStatusGrace = () => {
|
|
53562
|
+
missingTargetStatusSince = undefined;
|
|
53563
|
+
missingTargetStatusKey = undefined;
|
|
53564
|
+
};
|
|
53567
53565
|
while (Date.now() - startTime < PROTOCOL_V2_INSTALL_TIMEOUT) {
|
|
53568
53566
|
this.throwIfAborted();
|
|
53569
53567
|
try {
|
|
@@ -53583,6 +53581,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53583
53581
|
}, { timeoutMs: PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT });
|
|
53584
53582
|
if (statusResponse.type === 'Success') {
|
|
53585
53583
|
installEvidenceObserved = true;
|
|
53584
|
+
resetMissingTargetStatusGrace();
|
|
53586
53585
|
lastError = new Error('Protocol V2 firmware install acknowledged; waiting for target status');
|
|
53587
53586
|
}
|
|
53588
53587
|
const statusTargets = statusResponse.type === 'DeviceFirmwareUpdateStatus'
|
|
@@ -53604,6 +53603,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53604
53603
|
if (hasMatchingTargetStatus &&
|
|
53605
53604
|
(!requireCurrentInstallStatus || currentInstallStatusObserved)) {
|
|
53606
53605
|
installEvidenceObserved = true;
|
|
53606
|
+
normalModeWithoutInstallEvidenceSince = undefined;
|
|
53607
53607
|
}
|
|
53608
53608
|
const matchingStatusTargets = statusTargets.filter(target => {
|
|
53609
53609
|
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
@@ -53631,6 +53631,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53631
53631
|
}
|
|
53632
53632
|
}
|
|
53633
53633
|
if (statusTargets.length === 0) {
|
|
53634
|
+
resetMissingTargetStatusGrace();
|
|
53634
53635
|
if (statusResponse.type !== 'Success') {
|
|
53635
53636
|
lastError = new Error('Protocol V2 firmware update is waiting for user confirmation or target status');
|
|
53636
53637
|
}
|
|
@@ -53638,10 +53639,23 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53638
53639
|
else {
|
|
53639
53640
|
const missingTargetIds = this.getProtocolV2MissingTargetIds(statusTargets, expectedTargetIds);
|
|
53640
53641
|
if (missingTargetIds.length > 0) {
|
|
53642
|
+
const now = Date.now();
|
|
53641
53643
|
const missingKey = missingTargetIds.join(',');
|
|
53644
|
+
if (missingTargetStatusSince === undefined || missingTargetStatusKey !== missingKey) {
|
|
53645
|
+
missingTargetStatusSince = now;
|
|
53646
|
+
missingTargetStatusKey = missingKey;
|
|
53647
|
+
}
|
|
53648
|
+
else if (now - missingTargetStatusSince >=
|
|
53649
|
+
PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT) {
|
|
53650
|
+
const reportedTargetIds = statusTargets
|
|
53651
|
+
.map(target => normalizeProtocolV2TargetId(target.target_id))
|
|
53652
|
+
.filter((targetId) => targetId !== undefined);
|
|
53653
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, `Protocol V2 firmware status is missing requested records: targetIds=${missingKey} reportedTargetIds=${reportedTargetIds.join(',')}`);
|
|
53654
|
+
}
|
|
53642
53655
|
lastError = new Error(`Protocol V2 firmware status is temporarily missing targetIds=${missingKey}`);
|
|
53643
53656
|
}
|
|
53644
53657
|
else {
|
|
53658
|
+
resetMissingTargetStatusGrace();
|
|
53645
53659
|
lastError = new Error('Protocol V2 firmware targets are still installing');
|
|
53646
53660
|
}
|
|
53647
53661
|
}
|
|
@@ -53650,6 +53664,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53650
53664
|
if (isProtocolV2TerminalInstallStatusError(error)) {
|
|
53651
53665
|
throw error;
|
|
53652
53666
|
}
|
|
53667
|
+
resetMissingTargetStatusGrace();
|
|
53653
53668
|
if (isProtocolV2FirmwareStatusEndpointUnavailable(error)) {
|
|
53654
53669
|
if (!currentDeviceInfo) {
|
|
53655
53670
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 device identity is unavailable during install polling');
|
|
@@ -53663,9 +53678,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53663
53678
|
return;
|
|
53664
53679
|
}
|
|
53665
53680
|
if (isNormalMode) {
|
|
53681
|
+
const now = Date.now();
|
|
53682
|
+
normalModeWithoutInstallEvidenceSince !== null && normalModeWithoutInstallEvidenceSince !== void 0 ? normalModeWithoutInstallEvidenceSince : (normalModeWithoutInstallEvidenceSince = now);
|
|
53683
|
+
if (now - normalModeWithoutInstallEvidenceSince >=
|
|
53684
|
+
PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT) {
|
|
53685
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, 'Protocol V2 device returned to normal mode without install ACK, target status, or version change');
|
|
53686
|
+
}
|
|
53666
53687
|
lastError = new Error('Protocol V2 device is in normal mode but installation is not yet confirmed');
|
|
53667
53688
|
}
|
|
53668
53689
|
else {
|
|
53690
|
+
normalModeWithoutInstallEvidenceSince = undefined;
|
|
53669
53691
|
lastError = new Error('Protocol V2 firmware status endpoint is unavailable while the device remains in loader mode');
|
|
53670
53692
|
}
|
|
53671
53693
|
}
|
|
@@ -53691,14 +53713,12 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53691
53713
|
}
|
|
53692
53714
|
shouldReconnect = true;
|
|
53693
53715
|
deviceInfo = undefined;
|
|
53716
|
+
resetMissingTargetStatusGrace();
|
|
53694
53717
|
Log$7.log('Protocol V2 firmware install device readiness probe failed: ', error);
|
|
53695
53718
|
}
|
|
53696
53719
|
yield hdShared.wait(1000);
|
|
53697
53720
|
}
|
|
53698
|
-
|
|
53699
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, undefined, {
|
|
53700
|
-
firmwareUpdateCode: PROTOCOL_V2_INSTALL_TIMEOUT_CODE,
|
|
53701
|
-
});
|
|
53721
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware update status not complete within ${PROTOCOL_V2_INSTALL_TIMEOUT / 1000}s: ${this.normalizeErrorMessage(lastError)}`);
|
|
53702
53722
|
});
|
|
53703
53723
|
}
|
|
53704
53724
|
exitProtocolV2BootloaderToNormal() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.136",
|
|
4
4
|
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-shared": "1.2.0-alpha.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.0-alpha.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.136",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.136",
|
|
30
30
|
"axios": "1.15.2",
|
|
31
31
|
"bignumber.js": "^9.0.2",
|
|
32
32
|
"buffer": "^6.0.3",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"@types/w3c-web-usb": "^1.0.10",
|
|
47
47
|
"@types/web-bluetooth": "^0.0.21"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "92945bc4aae3d6602dd44c2e028e902e6bce7b55"
|
|
50
50
|
}
|
|
@@ -2,7 +2,6 @@ import { EDeviceType, ERRORS, HardwareError, HardwareErrorCode, wait } from '@on
|
|
|
2
2
|
import JSZip from 'jszip';
|
|
3
3
|
import {
|
|
4
4
|
DeviceRebootType,
|
|
5
|
-
DeviceSessionPinType,
|
|
6
5
|
PROTOCOL_V2_BLE_FILE_CHUNK_SIZE,
|
|
7
6
|
PROTOCOL_V2_BLE_FILE_READ_CHUNK_SIZE,
|
|
8
7
|
PROTOCOL_V2_BLE_FIRMWARE_FILE_CHUNK_SIZE,
|
|
@@ -91,8 +90,9 @@ const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
|
|
|
91
90
|
const PROTOCOL_V2_FINAL_RECONNECT_TIMEOUT = 3 * 60 * 1000;
|
|
92
91
|
const PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT = 5 * 1000;
|
|
93
92
|
const PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT = 15 * 1000;
|
|
94
|
-
const PROTOCOL_V2_INSTALL_TIMEOUT =
|
|
93
|
+
const PROTOCOL_V2_INSTALL_TIMEOUT = 8 * 60 * 1000;
|
|
95
94
|
const PROTOCOL_V2_INSTALL_STATUS_INITIAL_DELAY = 1000;
|
|
95
|
+
const PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT = 30 * 1000;
|
|
96
96
|
const PROTOCOL_V2_TARGET_STATUS_PENDING = 0;
|
|
97
97
|
const PROTOCOL_V2_TARGET_STATUS_IN_PROGRESS = 1;
|
|
98
98
|
const PROTOCOL_V2_TARGET_STATUS_FINISHED = 2;
|
|
@@ -106,8 +106,6 @@ const PROTOCOL_V2_CONNECT_SINGLE_TIMEOUT = 75 * 1000;
|
|
|
106
106
|
const PROTOCOL_V2_DEVICE_INFO_READY_TIMEOUT = 30 * 1000;
|
|
107
107
|
const PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT = 3;
|
|
108
108
|
const PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE = 'FirmwareInstallStatusConflict';
|
|
109
|
-
const PROTOCOL_V2_INSTALL_FAILED_CODE = 'FirmwareInstallFailed';
|
|
110
|
-
const PROTOCOL_V2_INSTALL_TIMEOUT_CODE = 'FirmwareInstallTimeout';
|
|
111
109
|
const PROTOCOL_V2_OKPP_HEADER_SIZE = 0x52a0;
|
|
112
110
|
const PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET = 0x200;
|
|
113
111
|
const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET = 0x240;
|
|
@@ -393,8 +391,7 @@ const isProtocolV2FirmwareStatusEndpointUnavailable = (error: unknown) => {
|
|
|
393
391
|
|
|
394
392
|
const isProtocolV2TerminalInstallStatusError = (error: unknown) =>
|
|
395
393
|
error instanceof HardwareError &&
|
|
396
|
-
(error.errorCode === HardwareErrorCode.
|
|
397
|
-
error.errorCode === HardwareErrorCode.FirmwareError ||
|
|
394
|
+
(error.errorCode === HardwareErrorCode.FirmwareError ||
|
|
398
395
|
error.errorCode === HardwareErrorCode.FirmwareVerificationFailed ||
|
|
399
396
|
error.params?.firmwareUpdateCode === PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE);
|
|
400
397
|
|
|
@@ -602,9 +599,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
602
599
|
this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
|
|
603
600
|
this.requireDeviceMode = [];
|
|
604
601
|
this.unlockPolicy = 'unlock-before-run';
|
|
605
|
-
// Protocol V2 device-management actions are not wallet-scoped, so either
|
|
606
|
-
// the main PIN or an Attach PIN may authorize them.
|
|
607
|
-
this.protocolV2PreUnlockPinType = DeviceSessionPinType.Any;
|
|
608
602
|
this.useDevicePassphraseState = false;
|
|
609
603
|
this.skipForceUpdateCheck = true;
|
|
610
604
|
|
|
@@ -1629,11 +1623,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1629
1623
|
Math.floor(statusVersion / 0x100) % 0x100
|
|
1630
1624
|
}.${statusVersion % 0x100}`;
|
|
1631
1625
|
if (!observedVersion) {
|
|
1632
|
-
|
|
1633
|
-
applicationTargets.length > 1 && (target === 'app_v1' || target === 'app_v2');
|
|
1634
|
-
if (this.protocolV2FinalStatusVerified || isUnobservableApplicationSlot) {
|
|
1626
|
+
if (this.protocolV2FinalStatusVerified) {
|
|
1635
1627
|
Log.warn(
|
|
1636
|
-
`Protocol V2 target ${target} has no observable final version;
|
|
1628
|
+
`Protocol V2 target ${target} has no observable final version; completed target status is authoritative`
|
|
1637
1629
|
);
|
|
1638
1630
|
} else {
|
|
1639
1631
|
throw ERRORS.TypedError(
|
|
@@ -2507,9 +2499,14 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2507
2499
|
path: failedTarget.path,
|
|
2508
2500
|
});
|
|
2509
2501
|
Log.error(`[FirmwareUpdateV4] firmware install failed target=${failedTargetDetails}`);
|
|
2510
|
-
throw ERRORS.TypedError(
|
|
2511
|
-
|
|
2512
|
-
|
|
2502
|
+
throw ERRORS.TypedError(
|
|
2503
|
+
HardwareErrorCode.FirmwareError,
|
|
2504
|
+
`Protocol V2 firmware target failed: target=${failedTarget.target_id} status=${
|
|
2505
|
+
failedTarget.status ?? 'unknown'
|
|
2506
|
+
} payloadVersion=${failedTarget.payload_version ?? 'unknown'} path=${
|
|
2507
|
+
failedTarget.path ?? 'unknown'
|
|
2508
|
+
}`
|
|
2509
|
+
);
|
|
2513
2510
|
}
|
|
2514
2511
|
|
|
2515
2512
|
const matchingTargets = statusTargets.filter(target =>
|
|
@@ -2523,10 +2520,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2523
2520
|
seenTargetIds.has(targetId) ||
|
|
2524
2521
|
(target.path && expectedPaths.get(targetId) && target.path !== expectedPaths.get(targetId))
|
|
2525
2522
|
) {
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2523
|
+
throw ERRORS.TypedError(
|
|
2524
|
+
HardwareErrorCode.RuntimeError,
|
|
2525
|
+
`Protocol V2 install status conflicts with target ${target.target_id}`,
|
|
2526
|
+
{
|
|
2527
|
+
firmwareUpdateCode: PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE,
|
|
2528
|
+
}
|
|
2529
|
+
);
|
|
2530
2530
|
}
|
|
2531
2531
|
seenTargetIds.add(targetId);
|
|
2532
2532
|
}
|
|
@@ -2651,8 +2651,15 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2651
2651
|
// Reconnecting here probes DeviceInfo, which loaders reject while installation is active.
|
|
2652
2652
|
let shouldReconnect = false;
|
|
2653
2653
|
let deviceInfo: ProtocolV2DeviceInfo | undefined;
|
|
2654
|
+
let missingTargetStatusSince: number | undefined;
|
|
2655
|
+
let missingTargetStatusKey: string | undefined;
|
|
2656
|
+
let normalModeWithoutInstallEvidenceSince: number | undefined;
|
|
2654
2657
|
let installEvidenceObserved = false;
|
|
2655
2658
|
let currentInstallStatusObserved = false;
|
|
2659
|
+
const resetMissingTargetStatusGrace = () => {
|
|
2660
|
+
missingTargetStatusSince = undefined;
|
|
2661
|
+
missingTargetStatusKey = undefined;
|
|
2662
|
+
};
|
|
2656
2663
|
|
|
2657
2664
|
while (Date.now() - startTime < PROTOCOL_V2_INSTALL_TIMEOUT) {
|
|
2658
2665
|
// A transport release caused by an explicit workflow cancellation must not
|
|
@@ -2680,6 +2687,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2680
2687
|
);
|
|
2681
2688
|
if (statusResponse.type === 'Success') {
|
|
2682
2689
|
installEvidenceObserved = true;
|
|
2690
|
+
resetMissingTargetStatusGrace();
|
|
2683
2691
|
lastError = new Error(
|
|
2684
2692
|
'Protocol V2 firmware install acknowledged; waiting for target status'
|
|
2685
2693
|
);
|
|
@@ -2708,6 +2716,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2708
2716
|
(!requireCurrentInstallStatus || currentInstallStatusObserved)
|
|
2709
2717
|
) {
|
|
2710
2718
|
installEvidenceObserved = true;
|
|
2719
|
+
normalModeWithoutInstallEvidenceSince = undefined;
|
|
2711
2720
|
}
|
|
2712
2721
|
const matchingStatusTargets = statusTargets.filter(target => {
|
|
2713
2722
|
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
@@ -2749,6 +2758,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2749
2758
|
}
|
|
2750
2759
|
|
|
2751
2760
|
if (statusTargets.length === 0) {
|
|
2761
|
+
resetMissingTargetStatusGrace();
|
|
2752
2762
|
if (statusResponse.type !== 'Success') {
|
|
2753
2763
|
lastError = new Error(
|
|
2754
2764
|
'Protocol V2 firmware update is waiting for user confirmation or target status'
|
|
@@ -2760,11 +2770,30 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2760
2770
|
expectedTargetIds
|
|
2761
2771
|
);
|
|
2762
2772
|
if (missingTargetIds.length > 0) {
|
|
2773
|
+
const now = Date.now();
|
|
2763
2774
|
const missingKey = missingTargetIds.join(',');
|
|
2775
|
+
if (missingTargetStatusSince === undefined || missingTargetStatusKey !== missingKey) {
|
|
2776
|
+
missingTargetStatusSince = now;
|
|
2777
|
+
missingTargetStatusKey = missingKey;
|
|
2778
|
+
} else if (
|
|
2779
|
+
now - missingTargetStatusSince >=
|
|
2780
|
+
PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT
|
|
2781
|
+
) {
|
|
2782
|
+
const reportedTargetIds = statusTargets
|
|
2783
|
+
.map(target => normalizeProtocolV2TargetId(target.target_id))
|
|
2784
|
+
.filter((targetId): targetId is number => targetId !== undefined);
|
|
2785
|
+
throw ERRORS.TypedError(
|
|
2786
|
+
HardwareErrorCode.FirmwareError,
|
|
2787
|
+
`Protocol V2 firmware status is missing requested records: targetIds=${missingKey} reportedTargetIds=${reportedTargetIds.join(
|
|
2788
|
+
','
|
|
2789
|
+
)}`
|
|
2790
|
+
);
|
|
2791
|
+
}
|
|
2764
2792
|
lastError = new Error(
|
|
2765
2793
|
`Protocol V2 firmware status is temporarily missing targetIds=${missingKey}`
|
|
2766
2794
|
);
|
|
2767
2795
|
} else {
|
|
2796
|
+
resetMissingTargetStatusGrace();
|
|
2768
2797
|
lastError = new Error('Protocol V2 firmware targets are still installing');
|
|
2769
2798
|
}
|
|
2770
2799
|
}
|
|
@@ -2772,6 +2801,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2772
2801
|
if (isProtocolV2TerminalInstallStatusError(error)) {
|
|
2773
2802
|
throw error;
|
|
2774
2803
|
}
|
|
2804
|
+
// Only consecutive full status dumps can prove that a record is absent.
|
|
2805
|
+
// A reboot or transport interruption starts a fresh grace window.
|
|
2806
|
+
resetMissingTargetStatusGrace();
|
|
2775
2807
|
// App firmware does not register DeviceFirmwareUpdateStatusGet. Treat the
|
|
2776
2808
|
// missing endpoint as completion only after the runtime probe confirms App mode.
|
|
2777
2809
|
if (isProtocolV2FirmwareStatusEndpointUnavailable(error)) {
|
|
@@ -2794,10 +2826,22 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2794
2826
|
return;
|
|
2795
2827
|
}
|
|
2796
2828
|
if (isNormalMode) {
|
|
2829
|
+
const now = Date.now();
|
|
2830
|
+
normalModeWithoutInstallEvidenceSince ??= now;
|
|
2831
|
+
if (
|
|
2832
|
+
now - normalModeWithoutInstallEvidenceSince >=
|
|
2833
|
+
PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT
|
|
2834
|
+
) {
|
|
2835
|
+
throw ERRORS.TypedError(
|
|
2836
|
+
HardwareErrorCode.FirmwareError,
|
|
2837
|
+
'Protocol V2 device returned to normal mode without install ACK, target status, or version change'
|
|
2838
|
+
);
|
|
2839
|
+
}
|
|
2797
2840
|
lastError = new Error(
|
|
2798
2841
|
'Protocol V2 device is in normal mode but installation is not yet confirmed'
|
|
2799
2842
|
);
|
|
2800
2843
|
} else {
|
|
2844
|
+
normalModeWithoutInstallEvidenceSince = undefined;
|
|
2801
2845
|
lastError = new Error(
|
|
2802
2846
|
'Protocol V2 firmware status endpoint is unavailable while the device remains in loader mode'
|
|
2803
2847
|
);
|
|
@@ -2828,19 +2872,18 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2828
2872
|
}
|
|
2829
2873
|
shouldReconnect = true;
|
|
2830
2874
|
deviceInfo = undefined;
|
|
2875
|
+
resetMissingTargetStatusGrace();
|
|
2831
2876
|
Log.log('Protocol V2 firmware install device readiness probe failed: ', error);
|
|
2832
2877
|
}
|
|
2833
2878
|
await wait(1000);
|
|
2834
2879
|
}
|
|
2835
2880
|
|
|
2836
|
-
|
|
2837
|
-
|
|
2881
|
+
throw ERRORS.TypedError(
|
|
2882
|
+
HardwareErrorCode.RuntimeError,
|
|
2883
|
+
`Protocol V2 firmware update status not complete within ${
|
|
2838
2884
|
PROTOCOL_V2_INSTALL_TIMEOUT / 1000
|
|
2839
2885
|
}s: ${this.normalizeErrorMessage(lastError)}`
|
|
2840
2886
|
);
|
|
2841
|
-
throw ERRORS.TypedError(HardwareErrorCode.FirmwareError, undefined, {
|
|
2842
|
-
firmwareUpdateCode: PROTOCOL_V2_INSTALL_TIMEOUT_CODE,
|
|
2843
|
-
});
|
|
2844
2887
|
}
|
|
2845
2888
|
|
|
2846
2889
|
private async exitProtocolV2BootloaderToNormal() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DeviceSettingsPage } from '@onekeyfe/hd-transport';
|
|
2
2
|
|
|
3
3
|
import { BaseMethod } from '../BaseMethod';
|
|
4
4
|
import { validateParams } from '../helpers/paramsValidator';
|
|
@@ -13,9 +13,6 @@ export default class DeviceChangePin extends BaseMethod<ChangePin> {
|
|
|
13
13
|
|
|
14
14
|
init() {
|
|
15
15
|
this.unlockPolicy = 'unlock-before-run';
|
|
16
|
-
// Protocol V2 device-management actions are not wallet-scoped, so either
|
|
17
|
-
// the main PIN or an Attach PIN may authorize them.
|
|
18
|
-
this.protocolV2PreUnlockPinType = DeviceSessionPinType.Any;
|
|
19
16
|
this.useDevicePassphraseState = false;
|
|
20
17
|
|
|
21
18
|
// check payload
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { sha256 } from '@noble/hashes/sha256';
|
|
2
2
|
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
3
|
-
import { DeviceSessionPinType } from '@onekeyfe/hd-transport';
|
|
4
3
|
import { bytesToHex } from '@noble/hashes/utils';
|
|
5
4
|
|
|
6
5
|
import { formatAnyHex } from '../helpers/hexUtils';
|
|
@@ -12,15 +11,7 @@ import type { BixinVerifyDeviceRequest } from '@onekeyfe/hd-transport';
|
|
|
12
11
|
import type { DeviceVerifySignature } from '../../types';
|
|
13
12
|
|
|
14
13
|
export default class DeviceVerify extends BaseMethod<BixinVerifyDeviceRequest> {
|
|
15
|
-
getSupportedProtocols() {
|
|
16
|
-
return ['V1', 'V2'] as const;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
14
|
init() {
|
|
20
|
-
this.unlockPolicy = 'unlock-before-run';
|
|
21
|
-
// Protocol V2 device-management actions are not wallet-scoped, so either
|
|
22
|
-
// the main PIN or an Attach PIN may authorize them.
|
|
23
|
-
this.protocolV2PreUnlockPinType = DeviceSessionPinType.Any;
|
|
24
15
|
this.useDevicePassphraseState = false;
|
|
25
16
|
|
|
26
17
|
// check payload
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DeviceSettingsPage } from '@onekeyfe/hd-transport';
|
|
2
2
|
|
|
3
3
|
import { BaseMethod } from '../BaseMethod';
|
|
4
4
|
|
|
@@ -11,9 +11,6 @@ export default class DeviceWipe extends BaseMethod<WipeDevice> {
|
|
|
11
11
|
|
|
12
12
|
init() {
|
|
13
13
|
this.unlockPolicy = 'unlock-before-run';
|
|
14
|
-
// Protocol V2 device-management actions are not wallet-scoped, so either
|
|
15
|
-
// the main PIN or an Attach PIN may authorize them.
|
|
16
|
-
this.protocolV2PreUnlockPinType = DeviceSessionPinType.Any;
|
|
17
14
|
this.useDevicePassphraseState = false;
|
|
18
15
|
this.protocolV2UiInteraction = {
|
|
19
16
|
request: 'button',
|