@onekeyfe/hd-core 1.2.0-alpha.97 → 1.2.0-alpha.99
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__/check-all-firmware-release-protocol-v2.test.ts +411 -86
- package/__tests__/check-firmware-release-protocol-v2.test.ts +199 -0
- package/__tests__/firmware-memory-host.test.ts +126 -0
- package/__tests__/firmware-update/device-update-bootloader.test.ts +14 -2
- package/__tests__/firmware-update/firmware-host-binding.test.ts +9 -0
- package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +573 -0
- package/__tests__/firmware-update/firmware-prepared-resource-archive.test.ts +150 -0
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +65 -2
- package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +80 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +293 -71
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +53 -1
- package/__tests__/firmware-update/firmware-update-prepared-resource-executors.test.ts +326 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +2 -2
- package/__tests__/protocol-v2-firmware-targets.test.ts +16 -0
- package/__tests__/protocol-v2-resources.test.ts +148 -232
- package/__tests__/protocol-v2.test.ts +1326 -510
- package/dist/api/CheckAllFirmwareRelease.d.ts +2 -3
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBLEFirmwareRelease.d.ts +3 -2
- package/dist/api/CheckBLEFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts +2 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/CheckFirmwareRelease.d.ts +3 -2
- package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +1 -0
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +11 -9
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts +1 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareMemoryHost.d.ts +22 -0
- package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +1 -0
- package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts +11 -0
- package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +48 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +7 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +0 -1
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/protocolV2Release.d.ts +33 -0
- package/dist/api/firmware/protocolV2Release.d.ts.map +1 -0
- package/dist/data-manager/DataManager.d.ts +4 -3
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/index.d.ts +108 -114
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1825 -1006
- package/dist/protocols/protocol-v2/resources.d.ts +10 -28
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +20 -8
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkBLEFirmwareRelease.d.ts +2 -13
- package/dist/types/api/checkBLEFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkBootloaderRelease.d.ts +2 -6
- package/dist/types/api/checkBootloaderRelease.d.ts.map +1 -1
- package/dist/types/api/checkFirmwareRelease.d.ts +2 -13
- package/dist/types/api/checkFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkFirmwareTypeAvailable.d.ts +2 -2
- package/dist/types/api/checkFirmwareTypeAvailable.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -1
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +4 -12
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +2 -2
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -1
- package/dist/types/settings.d.ts +35 -36
- package/dist/types/settings.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +113 -80
- package/src/api/CheckBLEFirmwareRelease.ts +37 -5
- package/src/api/CheckBootloaderRelease.ts +35 -3
- package/src/api/CheckFirmwareRelease.ts +35 -7
- package/src/api/FirmwareUpdateV2.ts +231 -138
- package/src/api/FirmwareUpdateV3.ts +101 -56
- package/src/api/FirmwareUpdateV4.ts +936 -408
- package/src/api/UploadPortfolio.ts +18 -0
- package/src/api/device/DeviceUpdateBootloader.ts +37 -11
- package/src/api/firmware/FirmwareHostBinding.ts +26 -3
- package/src/api/firmware/FirmwareMemoryHost.ts +143 -0
- package/src/api/firmware/FirmwarePreparedResourceArchive.ts +207 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +122 -73
- package/src/api/firmware/FirmwareUpdatePlan.ts +295 -122
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +49 -12
- package/src/api/firmware/protocolV2Release.ts +168 -0
- package/src/data-manager/DataManager.ts +35 -19
- package/src/index.ts +10 -0
- package/src/protocols/protocol-v2/resources.ts +157 -341
- package/src/types/api/checkAllFirmwareRelease.ts +27 -12
- package/src/types/api/checkBLEFirmwareRelease.ts +4 -13
- package/src/types/api/checkBootloaderRelease.ts +2 -6
- package/src/types/api/checkFirmwareRelease.ts +2 -13
- package/src/types/api/checkFirmwareTypeAvailable.ts +2 -2
- package/src/types/api/deviceUpdateBootloader.ts +1 -0
- package/src/types/api/export.ts +6 -1
- package/src/types/api/firmwareUpdate.ts +12 -17
- package/src/types/api/firmwareUpdatePlan.ts +2 -2
- package/src/types/settings.ts +35 -61
- package/src/utils/deviceFeaturesUtils.ts +2 -2
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
buildFirmwareUpdatePlan,
|
|
5
|
+
validateProtocolV2FirmwareUpdateTargets,
|
|
6
|
+
} from '../../src/api/firmware/FirmwareUpdatePlan';
|
|
7
|
+
import {
|
|
8
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity,
|
|
9
|
+
prepareFirmwareUpdatePlan,
|
|
10
|
+
} from '../../src/api/firmware/FirmwareUpdatePreparedPlan';
|
|
4
11
|
|
|
5
12
|
import type { Features } from '../../src/types';
|
|
6
13
|
|
|
@@ -50,6 +57,8 @@ const createLegacyForceInput = (
|
|
|
50
57
|
release: Record<string, unknown> = {
|
|
51
58
|
url: 'https://firmware.onekey.so/pro/firmware.bin',
|
|
52
59
|
version: [4, 21, 0],
|
|
60
|
+
expectedSize: 1024,
|
|
61
|
+
fingerprint: '1'.repeat(64),
|
|
53
62
|
}
|
|
54
63
|
): BuildPlanInput => ({
|
|
55
64
|
features: createFeatures({
|
|
@@ -82,6 +91,18 @@ const createProtocolV2ForceInput = (
|
|
|
82
91
|
forceUpdateTargets: forceUpdateTargets as BuildPlanInput['forceUpdateTargets'],
|
|
83
92
|
});
|
|
84
93
|
|
|
94
|
+
describe('validateProtocolV2FirmwareUpdateTargets', () => {
|
|
95
|
+
test('normalizes the deprecated boot_resources alias to resource', () => {
|
|
96
|
+
expect(validateProtocolV2FirmwareUpdateTargets(['boot_resources'])).toEqual(['resource']);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('rejects duplicate semantic targets after alias normalization', () => {
|
|
100
|
+
expectFirmwarePlanInvalid(() =>
|
|
101
|
+
validateProtocolV2FirmwareUpdateTargets(['boot_resources', 'resource'])
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
85
106
|
describe('buildFirmwareUpdatePlan', () => {
|
|
86
107
|
test('selects all legacy artifacts before execution and chooses the desktop full resource', () => {
|
|
87
108
|
const plan = buildFirmwareUpdatePlan({
|
|
@@ -168,6 +189,8 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
168
189
|
release: {
|
|
169
190
|
url: 'https://firmware.onekey.so/pro/firmware.bin',
|
|
170
191
|
version: [4, 0, 0],
|
|
192
|
+
expectedSize: 1024,
|
|
193
|
+
fingerprint: '1'.repeat(64),
|
|
171
194
|
},
|
|
172
195
|
},
|
|
173
196
|
ble: noUpdate,
|
|
@@ -193,7 +216,11 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
193
216
|
release: {
|
|
194
217
|
url: 'https://firmware.onekey.so/pro/firmware.bin',
|
|
195
218
|
version: [4, 21, 0],
|
|
219
|
+
expectedSize: 1024,
|
|
220
|
+
fingerprint: '1'.repeat(64),
|
|
196
221
|
resource: 'https://firmware.onekey.so/pro/resource.zip',
|
|
222
|
+
resourceExpectedSize: 4096,
|
|
223
|
+
resourceFingerprint: '1'.repeat(64),
|
|
197
224
|
},
|
|
198
225
|
},
|
|
199
226
|
ble: {
|
|
@@ -201,6 +228,8 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
201
228
|
release: {
|
|
202
229
|
webUpdate: 'https://firmware.onekey.so/pro/ble.bin',
|
|
203
230
|
version: [2, 3, 7],
|
|
231
|
+
expectedSize: 512,
|
|
232
|
+
fingerprintWeb: '2'.repeat(64),
|
|
204
233
|
},
|
|
205
234
|
},
|
|
206
235
|
bootloader: {
|
|
@@ -208,6 +237,8 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
208
237
|
release: {
|
|
209
238
|
bootloaderResource: 'https://firmware.onekey.so/pro/bootloader.bin',
|
|
210
239
|
bootloaderVersion: [2, 8, 4],
|
|
240
|
+
bootloaderExpectedSize: 768,
|
|
241
|
+
bootloaderFingerprint: '3'.repeat(64),
|
|
211
242
|
},
|
|
212
243
|
},
|
|
213
244
|
forceUpdateTargets: ['firmware', 'resource', 'ble', 'bootloader'],
|
|
@@ -237,6 +268,8 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
237
268
|
release: {
|
|
238
269
|
url: 'https://firmware.onekey.so/pro/firmware.bin',
|
|
239
270
|
version: [4, 21, 0],
|
|
271
|
+
expectedSize: 1024,
|
|
272
|
+
fingerprint: '1'.repeat(64),
|
|
240
273
|
resource: 'https://firmware.onekey.so/pro/resource.zip',
|
|
241
274
|
},
|
|
242
275
|
},
|
|
@@ -249,6 +282,32 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
249
282
|
expect(plan.targetsToUpdate).toEqual(['firmware']);
|
|
250
283
|
});
|
|
251
284
|
|
|
285
|
+
test('does not approve an unexecutable V2 resource during bootloader recovery', () => {
|
|
286
|
+
const features = createFeatures({ deviceType: EDeviceType.Classic1s });
|
|
287
|
+
features.bootloaderMode = true;
|
|
288
|
+
const plan = buildFirmwareUpdatePlan({
|
|
289
|
+
features,
|
|
290
|
+
firmwareType: EFirmwareType.Universal,
|
|
291
|
+
platform: 'desktop',
|
|
292
|
+
firmware: {
|
|
293
|
+
status: 'none',
|
|
294
|
+
release: {
|
|
295
|
+
url: 'https://firmware.onekey.so/classic/firmware.bin',
|
|
296
|
+
expectedSize: 1024,
|
|
297
|
+
fingerprint: '1'.repeat(64),
|
|
298
|
+
resource: 'https://firmware.onekey.so/classic/resource.zip',
|
|
299
|
+
resourceExpectedSize: 4096,
|
|
300
|
+
resourceFingerprint: '2'.repeat(64),
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
ble: noUpdate,
|
|
304
|
+
bootloader: noUpdate,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
expect(plan.artifacts.map(artifact => artifact.artifactId)).toEqual(['firmware']);
|
|
308
|
+
expect(plan.targetsToUpdate).toEqual(['firmware']);
|
|
309
|
+
});
|
|
310
|
+
|
|
252
311
|
test.each([
|
|
253
312
|
{
|
|
254
313
|
label: 'a non-array value',
|
|
@@ -272,6 +331,110 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
272
331
|
expectFirmwarePlanInvalid(() => buildFirmwareUpdatePlan(createLegacyForceInput(['resource'])));
|
|
273
332
|
});
|
|
274
333
|
|
|
334
|
+
test.each([
|
|
335
|
+
{
|
|
336
|
+
executor: 'V2',
|
|
337
|
+
deviceType: EDeviceType.Classic1s,
|
|
338
|
+
bootloaderVersion: '2.1.2',
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
executor: 'V3',
|
|
342
|
+
deviceType: EDeviceType.Pro,
|
|
343
|
+
bootloaderVersion: '2.8.4',
|
|
344
|
+
},
|
|
345
|
+
])(
|
|
346
|
+
'rejects a resource-only prepared plan that the $executor executor cannot run',
|
|
347
|
+
({ deviceType, bootloaderVersion }) => {
|
|
348
|
+
expectFirmwarePlanInvalid(
|
|
349
|
+
() =>
|
|
350
|
+
buildFirmwareUpdatePlan({
|
|
351
|
+
features: createFeatures({
|
|
352
|
+
deviceType,
|
|
353
|
+
firmwareVersion: '4.21.0',
|
|
354
|
+
bootloaderVersion,
|
|
355
|
+
}),
|
|
356
|
+
firmwareType: EFirmwareType.Universal,
|
|
357
|
+
platform: 'desktop',
|
|
358
|
+
firmware: {
|
|
359
|
+
status: 'valid',
|
|
360
|
+
release: {
|
|
361
|
+
url: 'https://firmware.onekey.so/legacy/firmware.bin',
|
|
362
|
+
version: [4, 21, 0],
|
|
363
|
+
expectedSize: 1024,
|
|
364
|
+
fingerprint: '1'.repeat(64),
|
|
365
|
+
resource: 'https://firmware.onekey.so/legacy/resource.zip',
|
|
366
|
+
resourceExpectedSize: 4096,
|
|
367
|
+
resourceFingerprint: '2'.repeat(64),
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
ble: noUpdate,
|
|
371
|
+
bootloader: noUpdate,
|
|
372
|
+
forceUpdateTargets: ['resource'],
|
|
373
|
+
}),
|
|
374
|
+
'Legacy resource updates require a firmware target'
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
test('rejects a legacy resource archive without complete integrity metadata', () => {
|
|
380
|
+
expectFirmwarePlanInvalid(
|
|
381
|
+
() =>
|
|
382
|
+
buildFirmwareUpdatePlan(
|
|
383
|
+
createLegacyForceInput(['resource'], {
|
|
384
|
+
url: 'https://firmware.onekey.so/pro/firmware.bin',
|
|
385
|
+
resource: 'https://firmware.onekey.so/pro/resource.zip',
|
|
386
|
+
resourceExpectedSize: 4096,
|
|
387
|
+
})
|
|
388
|
+
),
|
|
389
|
+
'integrity metadata is invalid'
|
|
390
|
+
);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
test.each(['firmware', 'ble', 'bootloader'] as const)(
|
|
394
|
+
'rejects a remote legacy %s artifact without complete integrity metadata',
|
|
395
|
+
target => {
|
|
396
|
+
expectFirmwarePlanInvalid(
|
|
397
|
+
() =>
|
|
398
|
+
buildFirmwareUpdatePlan({
|
|
399
|
+
features: createFeatures({ deviceType: EDeviceType.Classic1s }),
|
|
400
|
+
firmwareType: EFirmwareType.Universal,
|
|
401
|
+
platform: 'desktop',
|
|
402
|
+
firmware:
|
|
403
|
+
target === 'firmware'
|
|
404
|
+
? {
|
|
405
|
+
status: 'outdated',
|
|
406
|
+
release: {
|
|
407
|
+
url: 'https://firmware.onekey.so/classic/firmware.bin',
|
|
408
|
+
expectedSize: 1024,
|
|
409
|
+
},
|
|
410
|
+
}
|
|
411
|
+
: noUpdate,
|
|
412
|
+
ble:
|
|
413
|
+
target === 'ble'
|
|
414
|
+
? {
|
|
415
|
+
status: 'outdated',
|
|
416
|
+
release: {
|
|
417
|
+
webUpdate: 'https://firmware.onekey.so/classic/ble.bin',
|
|
418
|
+
expectedSize: 512,
|
|
419
|
+
},
|
|
420
|
+
}
|
|
421
|
+
: noUpdate,
|
|
422
|
+
bootloader:
|
|
423
|
+
target === 'bootloader'
|
|
424
|
+
? {
|
|
425
|
+
status: 'outdated',
|
|
426
|
+
release: {
|
|
427
|
+
bootloaderResource: 'https://firmware.onekey.so/classic/bootloader.bin',
|
|
428
|
+
bootloaderExpectedSize: 768,
|
|
429
|
+
},
|
|
430
|
+
}
|
|
431
|
+
: noUpdate,
|
|
432
|
+
}),
|
|
433
|
+
'integrity metadata is invalid'
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
);
|
|
437
|
+
|
|
275
438
|
test.each(['ble', 'bootloader'] as const)(
|
|
276
439
|
'rejects the unsupported Pro2 %s force target',
|
|
277
440
|
forceTarget => {
|
|
@@ -297,12 +460,6 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
297
460
|
forceTarget: 'firmware' as const,
|
|
298
461
|
release: {
|
|
299
462
|
components: {},
|
|
300
|
-
resourceBundles: [
|
|
301
|
-
{
|
|
302
|
-
name: 'images',
|
|
303
|
-
url: 'https://firmware.onekey.so/pro2/images.okpkg',
|
|
304
|
-
},
|
|
305
|
-
],
|
|
306
463
|
},
|
|
307
464
|
},
|
|
308
465
|
{
|
|
@@ -312,6 +469,8 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
312
469
|
applicationP1: {
|
|
313
470
|
target: 'APPLICATION_P1',
|
|
314
471
|
url: 'https://firmware.onekey.so/pro2/application-p1.bin',
|
|
472
|
+
expectedSize: 1024,
|
|
473
|
+
fingerprint: '1111111111111111111111111111111111111111111111111111111111111111',
|
|
315
474
|
},
|
|
316
475
|
},
|
|
317
476
|
},
|
|
@@ -325,41 +484,23 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
325
484
|
}
|
|
326
485
|
);
|
|
327
486
|
|
|
328
|
-
test
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
expectedTargets: ['resource'],
|
|
338
|
-
},
|
|
339
|
-
])(
|
|
340
|
-
'limits a Pro2 $forceTarget force to the selected artifact role',
|
|
341
|
-
({ forceTarget, expectedArtifactIds, expectedTargets }) => {
|
|
342
|
-
const plan = buildFirmwareUpdatePlan(
|
|
343
|
-
createProtocolV2ForceInput([forceTarget], {
|
|
344
|
-
components: {
|
|
345
|
-
applicationP1: {
|
|
346
|
-
target: 'APPLICATION_P1',
|
|
347
|
-
url: 'https://firmware.onekey.so/pro2/application-p1.bin',
|
|
348
|
-
},
|
|
487
|
+
test('limits a Pro2 firmware force to component artifacts', () => {
|
|
488
|
+
const plan = buildFirmwareUpdatePlan(
|
|
489
|
+
createProtocolV2ForceInput(['firmware'], {
|
|
490
|
+
components: {
|
|
491
|
+
applicationP1: {
|
|
492
|
+
target: 'APPLICATION_P1',
|
|
493
|
+
url: 'https://firmware.onekey.so/pro2/application-p1.bin',
|
|
494
|
+
expectedSize: 1024,
|
|
495
|
+
fingerprint: '1111111111111111111111111111111111111111111111111111111111111111',
|
|
349
496
|
},
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
url: 'https://firmware.onekey.so/pro2/images.okpkg',
|
|
354
|
-
},
|
|
355
|
-
],
|
|
356
|
-
})
|
|
357
|
-
);
|
|
497
|
+
},
|
|
498
|
+
})
|
|
499
|
+
);
|
|
358
500
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
);
|
|
501
|
+
expect(plan.artifacts.map(artifact => artifact.artifactId)).toEqual(['component:app_v1']);
|
|
502
|
+
expect(plan.targetsToUpdate).toEqual(['app_v1']);
|
|
503
|
+
});
|
|
363
504
|
|
|
364
505
|
test('rejects a prepared native plan without a stable device identity', () => {
|
|
365
506
|
const features = createFeatures({
|
|
@@ -376,6 +517,8 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
376
517
|
status: 'outdated',
|
|
377
518
|
release: {
|
|
378
519
|
url: 'https://firmware.onekey.so/classic/firmware.bin',
|
|
520
|
+
expectedSize: 1024,
|
|
521
|
+
fingerprint: '1'.repeat(64),
|
|
379
522
|
},
|
|
380
523
|
},
|
|
381
524
|
ble: noUpdate,
|
|
@@ -384,7 +527,72 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
384
527
|
).toThrow('requires a stable device identity');
|
|
385
528
|
});
|
|
386
529
|
|
|
387
|
-
test('
|
|
530
|
+
test('allows an identity-less Protocol V2 device while retaining the model binding', () => {
|
|
531
|
+
const features = createFeatures({
|
|
532
|
+
deviceType: EDeviceType.Pro2,
|
|
533
|
+
});
|
|
534
|
+
delete (features as Partial<Features>).serialNo;
|
|
535
|
+
|
|
536
|
+
const plan = buildFirmwareUpdatePlan({
|
|
537
|
+
features,
|
|
538
|
+
firmwareType: EFirmwareType.Universal,
|
|
539
|
+
platform: 'desktop',
|
|
540
|
+
firmware: {
|
|
541
|
+
status: 'outdated',
|
|
542
|
+
release: {
|
|
543
|
+
components: {
|
|
544
|
+
applicationP1: {
|
|
545
|
+
target: 'APPLICATION_P1',
|
|
546
|
+
url: 'https://firmware.onekey.so/pro2/application-p1.bin',
|
|
547
|
+
expectedSize: 1024,
|
|
548
|
+
fingerprint: '1111111111111111111111111111111111111111111111111111111111111111',
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
ble: noUpdate,
|
|
554
|
+
bootloader: noUpdate,
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
expect(plan).toMatchObject({
|
|
558
|
+
executor: 'v4',
|
|
559
|
+
deviceIdentity: 'unavailable',
|
|
560
|
+
deviceModel: String(EDeviceType.Pro2),
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
const preparedPlan = prepareFirmwareUpdatePlan({
|
|
564
|
+
plan,
|
|
565
|
+
leaseRef: 'fwlease:00000000-0000-4000-8000-000000000004',
|
|
566
|
+
artifacts: [
|
|
567
|
+
{
|
|
568
|
+
artifactId: 'component:app_v1',
|
|
569
|
+
artifact: {
|
|
570
|
+
artifactRef: `fw:${'1'.repeat(64)}`,
|
|
571
|
+
size: 1024,
|
|
572
|
+
sha256: '1'.repeat(64),
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
],
|
|
576
|
+
});
|
|
577
|
+
expect(() =>
|
|
578
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
579
|
+
preparedPlan,
|
|
580
|
+
deviceIdentity: undefined,
|
|
581
|
+
bootloaderMode: false,
|
|
582
|
+
deviceModel: String(EDeviceType.Pro2),
|
|
583
|
+
})
|
|
584
|
+
).not.toThrow();
|
|
585
|
+
expect(() =>
|
|
586
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
587
|
+
preparedPlan,
|
|
588
|
+
deviceIdentity: undefined,
|
|
589
|
+
bootloaderMode: false,
|
|
590
|
+
deviceModel: String(EDeviceType.Neo),
|
|
591
|
+
})
|
|
592
|
+
).toThrow();
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
test('maps the Pro2 component order without downloading artifacts', () => {
|
|
388
596
|
const plan = buildFirmwareUpdatePlan({
|
|
389
597
|
features: createFeatures({ deviceType: EDeviceType.Pro2 }),
|
|
390
598
|
firmwareType: EFirmwareType.Universal,
|
|
@@ -403,18 +611,16 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
403
611
|
bootloader: {
|
|
404
612
|
target: 'BOOTLOADER',
|
|
405
613
|
url: 'https://firmware.onekey.so/pro2/bootloader.bin',
|
|
614
|
+
expectedSize: 2048,
|
|
615
|
+
fingerprint: '2222222222222222222222222222222222222222222222222222222222222222',
|
|
406
616
|
},
|
|
407
617
|
se01: {
|
|
408
618
|
target: 'SE01',
|
|
409
619
|
url: 'https://firmware.onekey.so/pro2/se01.bin',
|
|
620
|
+
expectedSize: 512,
|
|
621
|
+
fingerprint: '3333333333333333333333333333333333333333333333333333333333333333',
|
|
410
622
|
},
|
|
411
623
|
},
|
|
412
|
-
resourceBundles: [
|
|
413
|
-
{
|
|
414
|
-
name: 'images',
|
|
415
|
-
url: 'https://firmware.onekey.so/pro2/images.okpkg',
|
|
416
|
-
},
|
|
417
|
-
],
|
|
418
624
|
},
|
|
419
625
|
},
|
|
420
626
|
ble: noUpdate,
|
|
@@ -426,9 +632,8 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
426
632
|
'component:boot',
|
|
427
633
|
'component:app_v1',
|
|
428
634
|
'component:se01',
|
|
429
|
-
'resourceBundle:images',
|
|
430
635
|
]);
|
|
431
|
-
expect(plan.targetsToUpdate).toEqual(['boot', 'app_v1', 'se01'
|
|
636
|
+
expect(plan.targetsToUpdate).toEqual(['boot', 'app_v1', 'se01']);
|
|
432
637
|
expect(plan.artifacts[1]).toEqual(
|
|
433
638
|
expect.objectContaining({
|
|
434
639
|
expectedSize: 1024,
|
|
@@ -437,6 +642,41 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
437
642
|
);
|
|
438
643
|
});
|
|
439
644
|
|
|
645
|
+
test.each([
|
|
646
|
+
{
|
|
647
|
+
expectedSize: undefined,
|
|
648
|
+
fingerprint: '1'.repeat(64),
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
expectedSize: 1024,
|
|
652
|
+
fingerprint: undefined,
|
|
653
|
+
},
|
|
654
|
+
])('rejects a remote Pro2 component without complete integrity metadata', integrity => {
|
|
655
|
+
expectFirmwarePlanInvalid(
|
|
656
|
+
() =>
|
|
657
|
+
buildFirmwareUpdatePlan({
|
|
658
|
+
features: createFeatures({ deviceType: EDeviceType.Pro2 }),
|
|
659
|
+
firmwareType: EFirmwareType.Universal,
|
|
660
|
+
platform: 'desktop',
|
|
661
|
+
firmware: {
|
|
662
|
+
status: 'required',
|
|
663
|
+
release: {
|
|
664
|
+
components: {
|
|
665
|
+
applicationP1: {
|
|
666
|
+
target: 'APPLICATION_P1',
|
|
667
|
+
url: 'https://firmware.onekey.so/pro2/application-p1.bin',
|
|
668
|
+
...integrity,
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
},
|
|
673
|
+
ble: noUpdate,
|
|
674
|
+
bootloader: noUpdate,
|
|
675
|
+
}),
|
|
676
|
+
'integrity metadata is invalid'
|
|
677
|
+
);
|
|
678
|
+
});
|
|
679
|
+
|
|
440
680
|
test('rejects Pro2 ROMLOADER because it requires a separate loader flow', () => {
|
|
441
681
|
expect(() =>
|
|
442
682
|
buildFirmwareUpdatePlan({
|
|
@@ -468,37 +708,19 @@ describe('buildFirmwareUpdatePlan', () => {
|
|
|
468
708
|
application: {
|
|
469
709
|
target: 'APPLICATION_P1',
|
|
470
710
|
url: 'https://firmware.onekey.so/pro2/application.bin',
|
|
711
|
+
expectedSize: 1024,
|
|
712
|
+
fingerprint: '1111111111111111111111111111111111111111111111111111111111111111',
|
|
471
713
|
},
|
|
472
714
|
applicationDuplicate: {
|
|
473
715
|
target: 'APPLICATION_P1',
|
|
474
716
|
url: 'https://firmware.onekey.so/pro2/application-duplicate.bin',
|
|
717
|
+
expectedSize: 1024,
|
|
718
|
+
fingerprint: '2222222222222222222222222222222222222222222222222222222222222222',
|
|
475
719
|
},
|
|
476
720
|
},
|
|
477
721
|
},
|
|
478
722
|
expectedError: 'duplicates target app_v1',
|
|
479
723
|
},
|
|
480
|
-
{
|
|
481
|
-
label: 'resource bundle name',
|
|
482
|
-
release: {
|
|
483
|
-
components: {
|
|
484
|
-
application: {
|
|
485
|
-
target: 'APPLICATION_P1',
|
|
486
|
-
url: 'https://firmware.onekey.so/pro2/application.bin',
|
|
487
|
-
},
|
|
488
|
-
},
|
|
489
|
-
resourceBundles: [
|
|
490
|
-
{
|
|
491
|
-
name: 'images',
|
|
492
|
-
url: 'https://firmware.onekey.so/pro2/images.okpkg',
|
|
493
|
-
},
|
|
494
|
-
{
|
|
495
|
-
name: 'images',
|
|
496
|
-
url: 'https://firmware.onekey.so/pro2/images-duplicate.okpkg',
|
|
497
|
-
},
|
|
498
|
-
],
|
|
499
|
-
},
|
|
500
|
-
expectedError: 'duplicates name images',
|
|
501
|
-
},
|
|
502
724
|
])('rejects a duplicate Pro2 $label', ({ release, expectedError }) => {
|
|
503
725
|
expect(() =>
|
|
504
726
|
buildFirmwareUpdatePlan({
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
buildFirmwareUpdatePlan,
|
|
5
|
+
digestFirmwareUpdateContract,
|
|
6
|
+
} from '../../src/api/firmware/FirmwareUpdatePlan';
|
|
4
7
|
import {
|
|
5
8
|
assertFirmwareUpdatePreparedPlanBinding,
|
|
6
9
|
assertFirmwareUpdatePreparedPlanDeviceIdentity,
|
|
@@ -209,6 +212,55 @@ describe('FirmwareUpdatePreparedPlan', () => {
|
|
|
209
212
|
).toThrow('entry name is invalid');
|
|
210
213
|
});
|
|
211
214
|
|
|
215
|
+
test('rejects duplicate materialized entry names during standalone validation', () => {
|
|
216
|
+
const plan = buildPlan();
|
|
217
|
+
const prepared = prepareFirmwareUpdatePlan({
|
|
218
|
+
plan,
|
|
219
|
+
leaseRef: 'fwlease:00000000-0000-4000-8000-000000000001',
|
|
220
|
+
artifacts: [
|
|
221
|
+
{
|
|
222
|
+
artifactId: 'firmware',
|
|
223
|
+
artifact: artifact('a'.repeat(64), 4),
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
artifactId: 'resource',
|
|
227
|
+
artifact: artifact('b'.repeat(64), 8),
|
|
228
|
+
materializedEntries: [
|
|
229
|
+
{
|
|
230
|
+
entryName: 'resource/index.bin',
|
|
231
|
+
artifact: artifact('c'.repeat(64), 2),
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
});
|
|
237
|
+
const resourceArtifact = prepared.artifacts.find(item => item.target === 'resource')!;
|
|
238
|
+
const tamperedWithoutDigest = {
|
|
239
|
+
...prepared,
|
|
240
|
+
artifacts: prepared.artifacts.map(item =>
|
|
241
|
+
item === resourceArtifact
|
|
242
|
+
? {
|
|
243
|
+
...item,
|
|
244
|
+
materializedEntries: [
|
|
245
|
+
...resourceArtifact.materializedEntries!,
|
|
246
|
+
{
|
|
247
|
+
entryName: 'other/index.bin',
|
|
248
|
+
artifact: artifact('d'.repeat(64), 2),
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
}
|
|
252
|
+
: item
|
|
253
|
+
),
|
|
254
|
+
};
|
|
255
|
+
const { preparedPlanDigest: _preparedPlanDigest, ...digestInput } = tamperedWithoutDigest;
|
|
256
|
+
const tampered = {
|
|
257
|
+
...tamperedWithoutDigest,
|
|
258
|
+
preparedPlanDigest: digestFirmwareUpdateContract(digestInput),
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
expect(() => validateFirmwareUpdatePreparedPlan(tampered)).toThrow('duplicate entry names');
|
|
262
|
+
});
|
|
263
|
+
|
|
212
264
|
test('rejects unknown fields even when a caller presents a plan-shaped object', () => {
|
|
213
265
|
const plan = buildPlan();
|
|
214
266
|
expect(() =>
|