@onekeyfe/hd-core 1.2.0-alpha.142 → 1.2.0-alpha.143
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__/device-lifecycle-events.test.ts +23 -1
- package/__tests__/protocol-v2-resources.test.ts +35 -89
- package/__tests__/protocol-v2.test.ts +47 -187
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/index.d.ts +1 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +117 -240
- package/dist/protocols/protocol-v2/resources.d.ts +11 -7
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/settings.d.ts +0 -13
- package/dist/types/settings.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +61 -238
- package/src/core/index.ts +5 -2
- package/src/index.ts +0 -4
- package/src/protocols/protocol-v2/resources.ts +92 -102
- package/src/types/settings.ts +0 -15
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { EDeviceType, ERRORS, HardwareErrorCode, createDeferred } from '@onekeyfe/hd-shared';
|
|
2
2
|
import { DeviceType, TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
initConnector,
|
|
6
|
+
initCore,
|
|
7
|
+
isMissingDetectedProtocolV2Error,
|
|
8
|
+
isRetryableBleProtocolV2ProbeError,
|
|
9
|
+
} from '../src/core';
|
|
5
10
|
import { DataManager } from '../src/data-manager';
|
|
6
11
|
import TransportManager from '../src/data-manager/TransportManager';
|
|
7
12
|
import { Device } from '../src/device/Device';
|
|
@@ -269,6 +274,23 @@ describe('public device lifecycle events', () => {
|
|
|
269
274
|
}
|
|
270
275
|
);
|
|
271
276
|
|
|
277
|
+
test.each([
|
|
278
|
+
[HardwareErrorCode.RuntimeError, true],
|
|
279
|
+
[HardwareErrorCode.BleDeviceBondError, false],
|
|
280
|
+
] as const)(
|
|
281
|
+
'retries a Protocol V2 probe mismatch with error code %s: %s',
|
|
282
|
+
(errorCode, expected) => {
|
|
283
|
+
const method = { payload: { connectProtocol: 'V2' } } as never;
|
|
284
|
+
const error = {
|
|
285
|
+
errorCode,
|
|
286
|
+
message:
|
|
287
|
+
'Device protocol mismatch: expected V2, but device did not respond to expected protocol',
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
expect(isRetryableBleProtocolV2ProbeError(method, error)).toBe(expected);
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
|
|
272
294
|
test('converts an internal transport disconnect into a public KnownDevice snapshot', () => {
|
|
273
295
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
274
296
|
core = initCore();
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
3
2
|
import { EDeviceType, EFirmwareType, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
4
3
|
|
|
5
4
|
import { DataManager } from '../src/data-manager';
|
|
6
5
|
import {
|
|
7
|
-
|
|
6
|
+
parseProtocolV2ResourcePackage,
|
|
8
7
|
parseProtocolV2Resources,
|
|
9
8
|
} from '../src/protocols/protocol-v2/resources';
|
|
10
9
|
|
|
@@ -16,9 +15,6 @@ jest.mock('../src/data/config', () => ({
|
|
|
16
15
|
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0-test/',
|
|
17
16
|
}));
|
|
18
17
|
|
|
19
|
-
const bytesToHex = (bytes: Uint8Array) =>
|
|
20
|
-
Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
|
|
21
|
-
|
|
22
18
|
const resourceSource = {
|
|
23
19
|
archiveUrl: 'https://example.com/resource/pro2-resource.zip',
|
|
24
20
|
archiveSha256: 'a'.repeat(64),
|
|
@@ -31,65 +27,21 @@ const neoResourceSource = {
|
|
|
31
27
|
archiveSize: 12_345_678,
|
|
32
28
|
};
|
|
33
29
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
[
|
|
50
|
-
'bundles/translations/translations-build.okpkg',
|
|
51
|
-
'translations.okpkg',
|
|
52
|
-
'vol0:/bundles/translations/translations.okpkg',
|
|
53
|
-
],
|
|
54
|
-
[
|
|
55
|
-
'loaders/bootloader/boot_resource-build.okpkg',
|
|
56
|
-
'boot_resource.okpkg',
|
|
57
|
-
'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
58
|
-
],
|
|
59
|
-
['loaders/rom/params-build.okpkg', 'params.okpkg', 'vol0:/loaders/rom/params.okpkg'],
|
|
60
|
-
].map(([archive_path, original_name, device_path], index) => {
|
|
61
|
-
const binary = new Uint8Array([index + 1]).buffer;
|
|
62
|
-
return {
|
|
63
|
-
archive_path,
|
|
64
|
-
original_name,
|
|
65
|
-
device_path,
|
|
66
|
-
size: 1,
|
|
67
|
-
sha256: bytesToHex(sha256(new Uint8Array(binary))),
|
|
68
|
-
signed: true,
|
|
69
|
-
sig_algo: device_path.startsWith('vol0:/bundles/') ? 'ed25519' : 'mldsa65',
|
|
70
|
-
payload_version: '1.0.0',
|
|
71
|
-
binary,
|
|
72
|
-
};
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const resourceManifest = {
|
|
76
|
-
schema: 1,
|
|
77
|
-
artifact_name: 'pro2-resource-build',
|
|
78
|
-
release_name: 'resource-build',
|
|
79
|
-
variant: 'resource',
|
|
80
|
-
commit: 'a'.repeat(40),
|
|
81
|
-
short_sha: 'aaaaaaa',
|
|
82
|
-
timestamp_utc: '20260807_091424',
|
|
83
|
-
core_version: '1.0.0',
|
|
84
|
-
key_set: 'dev',
|
|
85
|
-
device_root: 'vol0:',
|
|
86
|
-
restore_mode: 'bootloader_update',
|
|
87
|
-
trees: [
|
|
88
|
-
{ path: 'bundles', device: 'vol0:/bundles' },
|
|
89
|
-
{ path: 'loaders/bootloader', device: 'vol0:/loaders/bootloader' },
|
|
90
|
-
{ path: 'loaders/rom', device: 'vol0:/loaders/rom' },
|
|
91
|
-
],
|
|
92
|
-
files: manifestFiles.map(({ binary: _binary, ...file }) => file),
|
|
30
|
+
const createResourcePackage = (devicePath: string) => {
|
|
31
|
+
const headerSize = 0x5f90;
|
|
32
|
+
const bytes = new Uint8Array(headerSize + 1);
|
|
33
|
+
bytes.set(new TextEncoder().encode('OKPP'), 0);
|
|
34
|
+
bytes.set(new TextEncoder().encode('RESC'), 0x08);
|
|
35
|
+
bytes.set(new TextEncoder().encode(devicePath), 0x6c);
|
|
36
|
+
const view = new DataView(bytes.buffer);
|
|
37
|
+
view.setUint32(0x04, 1, true);
|
|
38
|
+
view.setUint32(0x0c, headerSize, true);
|
|
39
|
+
view.setUint32(0x10, 0x010203, true);
|
|
40
|
+
view.setUint32(0x14, 1, true);
|
|
41
|
+
bytes.fill(0x11, 0x200, 0x240);
|
|
42
|
+
bytes.fill(0x22, 0x240, 0x280);
|
|
43
|
+
bytes[headerSize] = 0xaa;
|
|
44
|
+
return bytes;
|
|
93
45
|
};
|
|
94
46
|
|
|
95
47
|
const createSettings = (configFetcher: ConnectSettings['configFetcher']): ConnectSettings =>
|
|
@@ -146,34 +98,36 @@ describe('Pro2 resource configuration', () => {
|
|
|
146
98
|
DataManager.lastCheckTimestamp = 0;
|
|
147
99
|
});
|
|
148
100
|
|
|
149
|
-
test('accepts the
|
|
101
|
+
test('accepts the release archive source', () => {
|
|
150
102
|
expect(parseProtocolV2Resources({ source: resourceSource })).toEqual({
|
|
151
103
|
source: resourceSource,
|
|
152
104
|
});
|
|
153
|
-
expect(parseProtocolV2ResourceManifest(resourceManifest).files).toHaveLength(9);
|
|
154
105
|
});
|
|
155
106
|
|
|
156
|
-
test('
|
|
107
|
+
test('reads the version, hashes, and direct device path from a RESC package', () => {
|
|
157
108
|
expect(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
109
|
+
parseProtocolV2ResourcePackage(createResourcePackage('vol0:/bundles/images.okpkg'))
|
|
110
|
+
).toEqual({
|
|
111
|
+
version: [1, 2, 3],
|
|
112
|
+
payloadLength: 1,
|
|
113
|
+
devicePath: 'vol0:/bundles/images.okpkg',
|
|
114
|
+
payloadHash: '11'.repeat(64),
|
|
115
|
+
headerHash: '22'.repeat(64),
|
|
116
|
+
});
|
|
162
117
|
});
|
|
163
118
|
|
|
164
|
-
test('
|
|
119
|
+
test('accepts the boot resource staging path and rejects paths outside resource roots', () => {
|
|
165
120
|
expect(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
).toEqual({ files: [resourceManifest.files[0]] });
|
|
121
|
+
parseProtocolV2ResourcePackage(
|
|
122
|
+
createResourcePackage('vol0:/loaders/bootloader/boot_resource.okpkg.staging')
|
|
123
|
+
).devicePath
|
|
124
|
+
).toBe('vol0:/loaders/bootloader/boot_resource.okpkg.staging');
|
|
125
|
+
expect(() =>
|
|
126
|
+
parseProtocolV2ResourcePackage(createResourcePackage('vol0:/unexpected/images.okpkg'))
|
|
127
|
+
).toThrow('device path');
|
|
174
128
|
});
|
|
175
129
|
|
|
176
|
-
test('rejects missing
|
|
130
|
+
test('rejects missing or malformed release sources', () => {
|
|
177
131
|
expect(() => parseProtocolV2Resources({})).toThrow('source is required');
|
|
178
132
|
expect(() =>
|
|
179
133
|
parseProtocolV2Resources({
|
|
@@ -193,14 +147,6 @@ describe('Pro2 resource configuration', () => {
|
|
|
193
147
|
source: { ...resourceSource, archiveSize: 0 },
|
|
194
148
|
})
|
|
195
149
|
).toThrow('positive integer');
|
|
196
|
-
expect(() =>
|
|
197
|
-
parseProtocolV2ResourceManifest({
|
|
198
|
-
...resourceManifest,
|
|
199
|
-
files: resourceManifest.files.map((file, index) =>
|
|
200
|
-
index === 0 ? { ...file, archive_path: '../outside.okpkg' } : file
|
|
201
|
-
),
|
|
202
|
-
})
|
|
203
|
-
).toThrow('archive_path');
|
|
204
150
|
});
|
|
205
151
|
|
|
206
152
|
test('applies a validated pre-release config and exposes its archive source', async () => {
|
|
@@ -139,21 +139,29 @@ const createJpegBase64 = (width: number, height: number) => {
|
|
|
139
139
|
|
|
140
140
|
const createProtocolV2OkppBinary = ({
|
|
141
141
|
version = [1, 2, 3],
|
|
142
|
+
devicePath = 'vol0:/bundles/images/images.okpkg',
|
|
142
143
|
payloadHashByte = 0x11,
|
|
143
144
|
headerHashByte = 0x22,
|
|
144
145
|
}: {
|
|
145
146
|
version?: [number, number, number];
|
|
147
|
+
devicePath?: string;
|
|
146
148
|
payloadHashByte?: number;
|
|
147
149
|
headerHashByte?: number;
|
|
148
150
|
} = {}) => {
|
|
149
|
-
const
|
|
151
|
+
const headerSize = 0x5f90;
|
|
152
|
+
const payloadSize = 1;
|
|
153
|
+
const bytes = new Uint8Array(headerSize + payloadSize);
|
|
150
154
|
bytes.set([0x4f, 0x4b, 0x50, 0x50], 0);
|
|
151
155
|
bytes.set([0x52, 0x45, 0x53, 0x43], 0x08);
|
|
152
156
|
const view = new DataView(bytes.buffer);
|
|
153
|
-
view.setUint32(
|
|
157
|
+
view.setUint32(0x04, 1, true);
|
|
158
|
+
view.setUint32(0x0c, headerSize, true);
|
|
154
159
|
view.setUint32(0x10, version[0] * 0x10000 + version[1] * 0x100 + version[2], true);
|
|
160
|
+
view.setUint32(0x14, payloadSize, true);
|
|
161
|
+
bytes.set(new TextEncoder().encode(devicePath), 0x6c);
|
|
155
162
|
bytes.fill(payloadHashByte, 0x200, 0x240);
|
|
156
163
|
bytes.fill(headerHashByte, 0x240, 0x280);
|
|
164
|
+
bytes[headerSize] = 0xaa;
|
|
157
165
|
return bytes.buffer;
|
|
158
166
|
};
|
|
159
167
|
|
|
@@ -7228,7 +7236,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7228
7236
|
});
|
|
7229
7237
|
});
|
|
7230
7238
|
|
|
7231
|
-
test('maps a prepared resource archive
|
|
7239
|
+
test('maps self-describing packages from a prepared resource archive', async () => {
|
|
7232
7240
|
const method = new FirmwareUpdateV4({
|
|
7233
7241
|
id: 1,
|
|
7234
7242
|
payload: {
|
|
@@ -7236,60 +7244,18 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7236
7244
|
},
|
|
7237
7245
|
});
|
|
7238
7246
|
const imagesBinary = createProtocolV2OkppBinary();
|
|
7239
|
-
const bootBinary = createProtocolV2OkppBinary({
|
|
7247
|
+
const bootBinary = createProtocolV2OkppBinary({
|
|
7248
|
+
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg.staging',
|
|
7249
|
+
payloadHashByte: 0x33,
|
|
7250
|
+
});
|
|
7240
7251
|
const imagesSha256 = bytesToHex(sha256(new Uint8Array(imagesBinary)));
|
|
7241
7252
|
const bootSha256 = bytesToHex(sha256(new Uint8Array(bootBinary)));
|
|
7242
|
-
const manifest = {
|
|
7243
|
-
schema: 1,
|
|
7244
|
-
artifact_name: 'pro2-resource',
|
|
7245
|
-
release_name: 'test-release',
|
|
7246
|
-
variant: 'resource',
|
|
7247
|
-
commit: 'abc123',
|
|
7248
|
-
short_sha: 'abc123',
|
|
7249
|
-
timestamp_utc: '2026-08-09T00:00:00Z',
|
|
7250
|
-
core_version: '1.0.0',
|
|
7251
|
-
key_set: 'production',
|
|
7252
|
-
device_root: 'vol0:',
|
|
7253
|
-
restore_mode: 'bootloader_update',
|
|
7254
|
-
trees: [{ path: 'bundles', device: 'pro2' }],
|
|
7255
|
-
files: [
|
|
7256
|
-
{
|
|
7257
|
-
archive_path: 'bundles/images/images.okpkg',
|
|
7258
|
-
original_name: 'images.okpkg',
|
|
7259
|
-
device_path: 'vol0:/bundles/images/images.okpkg',
|
|
7260
|
-
size: imagesBinary.byteLength,
|
|
7261
|
-
sha256: imagesSha256,
|
|
7262
|
-
signed: true,
|
|
7263
|
-
sig_algo: 'ed25519',
|
|
7264
|
-
payload_version: '1.2.3',
|
|
7265
|
-
},
|
|
7266
|
-
{
|
|
7267
|
-
archive_path: 'loaders/bootloader/boot_resource.okpkg',
|
|
7268
|
-
original_name: 'boot_resource.okpkg',
|
|
7269
|
-
device_path: 'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
7270
|
-
size: bootBinary.byteLength,
|
|
7271
|
-
sha256: bootSha256,
|
|
7272
|
-
signed: true,
|
|
7273
|
-
sig_algo: 'ed25519',
|
|
7274
|
-
payload_version: '1.2.3',
|
|
7275
|
-
},
|
|
7276
|
-
],
|
|
7277
|
-
};
|
|
7278
|
-
const manifestBinary = new TextEncoder().encode(JSON.stringify(manifest)).buffer;
|
|
7279
7253
|
const zip = new JSZip();
|
|
7280
|
-
zip.file('manifest.json', manifestBinary);
|
|
7281
7254
|
zip.file('bundles/images/images.okpkg', imagesBinary);
|
|
7282
7255
|
zip.file('loaders/bootloader/boot_resource.okpkg', bootBinary);
|
|
7256
|
+
zip.file('manifest.json', '{"ignored":true}');
|
|
7283
7257
|
const archiveBinary = await zip.generateAsync({ type: 'arraybuffer' });
|
|
7284
7258
|
const preparedEntries = [
|
|
7285
|
-
{
|
|
7286
|
-
entryName: 'pro2-resource/manifest.json',
|
|
7287
|
-
artifact: {
|
|
7288
|
-
artifactRef: 'manifest',
|
|
7289
|
-
size: manifestBinary.byteLength,
|
|
7290
|
-
sha256: bytesToHex(sha256(new Uint8Array(manifestBinary))),
|
|
7291
|
-
},
|
|
7292
|
-
},
|
|
7293
7259
|
{
|
|
7294
7260
|
entryName: 'pro2-resource/bundles/images/images.okpkg',
|
|
7295
7261
|
artifact: {
|
|
@@ -7352,7 +7318,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7352
7318
|
}),
|
|
7353
7319
|
expect.objectContaining({
|
|
7354
7320
|
name: 'boot_resource.okpkg',
|
|
7355
|
-
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
7321
|
+
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg.staging',
|
|
7356
7322
|
version: [1, 2, 3],
|
|
7357
7323
|
}),
|
|
7358
7324
|
]);
|
|
@@ -7398,9 +7364,9 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7398
7364
|
},
|
|
7399
7365
|
materializedEntries: [
|
|
7400
7366
|
{
|
|
7401
|
-
entryName: '
|
|
7367
|
+
entryName: 'bundles/images/images.okpkg',
|
|
7402
7368
|
artifact: {
|
|
7403
|
-
artifactRef: 'resource-
|
|
7369
|
+
artifactRef: 'resource-package',
|
|
7404
7370
|
size: 2,
|
|
7405
7371
|
sha256: 'b'.repeat(64),
|
|
7406
7372
|
},
|
|
@@ -7600,9 +7566,9 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7600
7566
|
},
|
|
7601
7567
|
materializedEntries: [
|
|
7602
7568
|
{
|
|
7603
|
-
entryName: '
|
|
7569
|
+
entryName: 'bundles/images/images.okpkg',
|
|
7604
7570
|
artifact: {
|
|
7605
|
-
artifactRef: 'prepared-resource-
|
|
7571
|
+
artifactRef: 'prepared-resource-package',
|
|
7606
7572
|
size: 2,
|
|
7607
7573
|
sha256: 'b'.repeat(64),
|
|
7608
7574
|
},
|
|
@@ -7659,48 +7625,15 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7659
7625
|
});
|
|
7660
7626
|
|
|
7661
7627
|
test('converts a local resource ZIP into a local PreparedPlan without matching a remote release', async () => {
|
|
7662
|
-
const imagesBinary =
|
|
7663
|
-
const bootResourceBinary =
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
release_name: 'local-development',
|
|
7668
|
-
variant: 'resource',
|
|
7669
|
-
commit: 'local',
|
|
7670
|
-
short_sha: 'local',
|
|
7671
|
-
timestamp_utc: '2026-08-09T00:00:00Z',
|
|
7672
|
-
core_version: '1.0.0',
|
|
7673
|
-
key_set: 'development',
|
|
7674
|
-
device_root: 'vol0:',
|
|
7675
|
-
restore_mode: 'bootloader_update',
|
|
7676
|
-
trees: [{ path: 'bundles', device: 'pro2' }],
|
|
7677
|
-
files: [
|
|
7678
|
-
{
|
|
7679
|
-
archive_path: 'bundles/images/images.okpkg',
|
|
7680
|
-
original_name: 'images.okpkg',
|
|
7681
|
-
device_path: 'vol0:/bundles/images/images.okpkg',
|
|
7682
|
-
size: imagesBinary.byteLength,
|
|
7683
|
-
sha256: bytesToHex(sha256(new Uint8Array(imagesBinary))),
|
|
7684
|
-
signed: true,
|
|
7685
|
-
sig_algo: 'ed25519',
|
|
7686
|
-
payload_version: '1.0.0',
|
|
7687
|
-
},
|
|
7688
|
-
{
|
|
7689
|
-
archive_path: 'loaders/bootloader/boot_resource.okpkg',
|
|
7690
|
-
original_name: 'boot_resource.okpkg',
|
|
7691
|
-
device_path: 'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
7692
|
-
size: bootResourceBinary.byteLength,
|
|
7693
|
-
sha256: bytesToHex(sha256(new Uint8Array(bootResourceBinary))),
|
|
7694
|
-
signed: true,
|
|
7695
|
-
sig_algo: 'ed25519',
|
|
7696
|
-
payload_version: '1.0.0',
|
|
7697
|
-
},
|
|
7698
|
-
],
|
|
7699
|
-
};
|
|
7628
|
+
const imagesBinary = createProtocolV2OkppBinary({ version: [1, 0, 0] });
|
|
7629
|
+
const bootResourceBinary = createProtocolV2OkppBinary({
|
|
7630
|
+
version: [1, 0, 0],
|
|
7631
|
+
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg.staging',
|
|
7632
|
+
});
|
|
7700
7633
|
const zip = new JSZip();
|
|
7701
|
-
zip.file('pro2-resource/manifest.json', JSON.stringify(manifest));
|
|
7702
7634
|
zip.file('pro2-resource/bundles/images/images.okpkg', imagesBinary);
|
|
7703
7635
|
zip.file('pro2-resource/loaders/bootloader/boot_resource.okpkg', bootResourceBinary);
|
|
7636
|
+
zip.file('pro2-resource/manifest.json', '{"ignored":true}');
|
|
7704
7637
|
zip.file('pro2-resource/build-info.txt', 'ignored');
|
|
7705
7638
|
const resourceArchiveBinary = await zip.generateAsync({ type: 'arraybuffer' });
|
|
7706
7639
|
const applicationP1Binary = new Uint8Array([7, 8, 9]).buffer;
|
|
@@ -7766,7 +7699,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7766
7699
|
}),
|
|
7767
7700
|
expect.objectContaining({
|
|
7768
7701
|
name: 'boot_resource.okpkg',
|
|
7769
|
-
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
7702
|
+
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg.staging',
|
|
7770
7703
|
}),
|
|
7771
7704
|
],
|
|
7772
7705
|
})
|
|
@@ -7777,9 +7710,11 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7777
7710
|
}
|
|
7778
7711
|
});
|
|
7779
7712
|
|
|
7780
|
-
test('accepts a local resource ZIP
|
|
7781
|
-
const imagesBinary =
|
|
7782
|
-
const bootResourceBinary =
|
|
7713
|
+
test('accepts every okpkg in a local resource ZIP and ignores other files', async () => {
|
|
7714
|
+
const imagesBinary = createProtocolV2OkppBinary();
|
|
7715
|
+
const bootResourceBinary = createProtocolV2OkppBinary({
|
|
7716
|
+
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg.staging',
|
|
7717
|
+
});
|
|
7783
7718
|
const zip = new JSZip();
|
|
7784
7719
|
zip.file('pro2-resource/bundles/images/images.okpkg', imagesBinary);
|
|
7785
7720
|
zip.file('pro2-resource/loaders/bootloader/boot_resource.okpkg', bootResourceBinary);
|
|
@@ -7800,61 +7735,21 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7800
7735
|
)
|
|
7801
7736
|
).resolves.toMatchObject({
|
|
7802
7737
|
materializedEntries: [
|
|
7803
|
-
{ entryName: '
|
|
7804
|
-
{ entryName: 'bundles/images/images.okpkg', binary: imagesBinary },
|
|
7738
|
+
{ entryName: 'pro2-resource/bundles/images/images.okpkg', binary: imagesBinary },
|
|
7805
7739
|
{
|
|
7806
|
-
entryName: 'loaders/bootloader/boot_resource.okpkg',
|
|
7740
|
+
entryName: 'pro2-resource/loaders/bootloader/boot_resource.okpkg',
|
|
7807
7741
|
binary: bootResourceBinary,
|
|
7808
7742
|
},
|
|
7809
7743
|
],
|
|
7810
7744
|
});
|
|
7811
7745
|
});
|
|
7812
7746
|
|
|
7813
|
-
test('rejects a local resource ZIP
|
|
7814
|
-
const resourceBinary =
|
|
7815
|
-
const
|
|
7747
|
+
test('rejects a local resource ZIP with duplicate package device paths', async () => {
|
|
7748
|
+
const resourceBinary = createProtocolV2OkppBinary();
|
|
7749
|
+
const duplicateResourceBinary = createProtocolV2OkppBinary({ payloadHashByte: 0x44 });
|
|
7816
7750
|
const zip = new JSZip();
|
|
7817
|
-
zip.file(
|
|
7818
|
-
'manifest.json',
|
|
7819
|
-
JSON.stringify({
|
|
7820
|
-
schema: 1,
|
|
7821
|
-
artifact_name: 'pro2-resource',
|
|
7822
|
-
release_name: 'local-development',
|
|
7823
|
-
variant: 'resource',
|
|
7824
|
-
commit: 'local',
|
|
7825
|
-
short_sha: 'local',
|
|
7826
|
-
timestamp_utc: '2026-08-09T00:00:00Z',
|
|
7827
|
-
core_version: '1.0.0',
|
|
7828
|
-
key_set: 'development',
|
|
7829
|
-
device_root: 'vol0:',
|
|
7830
|
-
restore_mode: 'bootloader_update',
|
|
7831
|
-
trees: [{ path: 'bundles', device: 'pro2' }],
|
|
7832
|
-
files: [
|
|
7833
|
-
{
|
|
7834
|
-
archive_path: 'bundles/images/images.okpkg',
|
|
7835
|
-
original_name: 'images.okpkg',
|
|
7836
|
-
device_path: 'vol0:/bundles/images/images.okpkg',
|
|
7837
|
-
size: resourceBinary.byteLength,
|
|
7838
|
-
sha256: '0'.repeat(64),
|
|
7839
|
-
signed: true,
|
|
7840
|
-
sig_algo: 'ed25519',
|
|
7841
|
-
payload_version: '1.0.0',
|
|
7842
|
-
},
|
|
7843
|
-
{
|
|
7844
|
-
archive_path: 'loaders/bootloader/boot_resource.okpkg',
|
|
7845
|
-
original_name: 'boot_resource.okpkg',
|
|
7846
|
-
device_path: 'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
7847
|
-
size: bootResourceBinary.byteLength,
|
|
7848
|
-
sha256: bytesToHex(sha256(new Uint8Array(bootResourceBinary))),
|
|
7849
|
-
signed: true,
|
|
7850
|
-
sig_algo: 'ed25519',
|
|
7851
|
-
payload_version: '1.0.0',
|
|
7852
|
-
},
|
|
7853
|
-
],
|
|
7854
|
-
})
|
|
7855
|
-
);
|
|
7856
7751
|
zip.file('bundles/images/images.okpkg', resourceBinary);
|
|
7857
|
-
zip.file('
|
|
7752
|
+
zip.file('copies/images.okpkg', duplicateResourceBinary);
|
|
7858
7753
|
const method = new FirmwareUpdateV4({
|
|
7859
7754
|
id: 1,
|
|
7860
7755
|
payload: {
|
|
@@ -7869,9 +7764,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7869
7764
|
(method as any).prepareProtocolV2LocalResourceArchive(
|
|
7870
7765
|
await zip.generateAsync({ type: 'arraybuffer' })
|
|
7871
7766
|
)
|
|
7872
|
-
).rejects.toThrow(
|
|
7873
|
-
'Protocol V2 local resource file does not match manifest: bundles/images/images.okpkg'
|
|
7874
|
-
);
|
|
7767
|
+
).rejects.toThrow('duplicate device path: vol0:/bundles/images/images.okpkg');
|
|
7875
7768
|
});
|
|
7876
7769
|
|
|
7877
7770
|
test('maps malformed resource ZIPs to a typed firmware preparation error', async () => {
|
|
@@ -7901,40 +7794,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7901
7794
|
test('rejects an oversized ZIP entry before allocating its decompressed bytes', async () => {
|
|
7902
7795
|
const extractEntry = jest.fn();
|
|
7903
7796
|
const oversizedFileSize = 257 * 1024 * 1024;
|
|
7904
|
-
const manifestBinary = new TextEncoder().encode(
|
|
7905
|
-
JSON.stringify({
|
|
7906
|
-
files: [
|
|
7907
|
-
{
|
|
7908
|
-
archive_path: 'loaders/bootloader/boot_resource.okpkg',
|
|
7909
|
-
original_name: 'boot_resource.okpkg',
|
|
7910
|
-
device_path: 'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
7911
|
-
size: oversizedFileSize,
|
|
7912
|
-
sha256: '0'.repeat(64),
|
|
7913
|
-
signed: true,
|
|
7914
|
-
sig_algo: 'ed25519',
|
|
7915
|
-
},
|
|
7916
|
-
{
|
|
7917
|
-
archive_path: 'bundles/images/images.okpkg',
|
|
7918
|
-
original_name: 'images.okpkg',
|
|
7919
|
-
device_path: 'vol0:/bundles/images/images.okpkg',
|
|
7920
|
-
size: oversizedFileSize,
|
|
7921
|
-
sha256: '0'.repeat(64),
|
|
7922
|
-
signed: true,
|
|
7923
|
-
sig_algo: 'ed25519',
|
|
7924
|
-
},
|
|
7925
|
-
],
|
|
7926
|
-
})
|
|
7927
|
-
);
|
|
7928
7797
|
const zipFiles = {
|
|
7929
|
-
'manifest.json': {
|
|
7930
|
-
name: 'manifest.json',
|
|
7931
|
-
dir: false,
|
|
7932
|
-
_data: {
|
|
7933
|
-
compressedSize: manifestBinary.byteLength,
|
|
7934
|
-
uncompressedSize: manifestBinary.byteLength,
|
|
7935
|
-
},
|
|
7936
|
-
async: jest.fn().mockResolvedValue(manifestBinary.buffer),
|
|
7937
|
-
},
|
|
7938
7798
|
'loaders/bootloader/boot_resource.okpkg': {
|
|
7939
7799
|
name: 'loaders/bootloader/boot_resource.okpkg',
|
|
7940
7800
|
dir: false,
|
|
@@ -7965,7 +7825,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7965
7825
|
try {
|
|
7966
7826
|
await expect(
|
|
7967
7827
|
(method as any).prepareProtocolV2LocalResourceArchive(new Uint8Array([1]).buffer)
|
|
7968
|
-
).rejects.toThrow('
|
|
7828
|
+
).rejects.toThrow('resource package size is invalid');
|
|
7969
7829
|
expect(extractEntry).not.toHaveBeenCalled();
|
|
7970
7830
|
} finally {
|
|
7971
7831
|
loadSpy.mockRestore();
|
|
@@ -8117,17 +7977,17 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8117
7977
|
readAt: jest.fn(),
|
|
8118
7978
|
close: jest.fn(),
|
|
8119
7979
|
},
|
|
8120
|
-
devicePath: 'vol0:/
|
|
7980
|
+
devicePath: 'vol0:/bundles/images/images.okpkg',
|
|
8121
7981
|
},
|
|
8122
7982
|
],
|
|
8123
7983
|
});
|
|
8124
7984
|
|
|
8125
7985
|
expect((method as any).protocolV2SourceUpdateProcess).toHaveBeenCalledTimes(1);
|
|
8126
7986
|
expect((method as any).protocolV2SourceUpdateProcess).toHaveBeenCalledWith(
|
|
8127
|
-
expect.objectContaining({ filePath: 'vol0:/
|
|
7987
|
+
expect.objectContaining({ filePath: 'vol0:/bundles/images/images.okpkg' })
|
|
8128
7988
|
);
|
|
8129
7989
|
expect((method as any).verifyProtocolV2StagedFile).toHaveBeenCalledWith(
|
|
8130
|
-
'vol0:/
|
|
7990
|
+
'vol0:/bundles/images/images.okpkg',
|
|
8131
7991
|
3
|
|
8132
7992
|
);
|
|
8133
7993
|
expect((method as any).protocolV2StartFirmwareUpdate).not.toHaveBeenCalled();
|
|
@@ -8162,7 +8022,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8162
8022
|
readAt: jest.fn(),
|
|
8163
8023
|
close: jest.fn(),
|
|
8164
8024
|
},
|
|
8165
|
-
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
8025
|
+
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg.staging',
|
|
8166
8026
|
},
|
|
8167
8027
|
],
|
|
8168
8028
|
});
|
|
@@ -8195,7 +8055,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8195
8055
|
readAt: jest.fn(),
|
|
8196
8056
|
close: jest.fn(),
|
|
8197
8057
|
},
|
|
8198
|
-
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
8058
|
+
devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg.staging',
|
|
8199
8059
|
version: [1, 0, 0],
|
|
8200
8060
|
payloadHash: '11'.repeat(64),
|
|
8201
8061
|
headerHash: '22'.repeat(64),
|
|
@@ -9267,7 +9127,7 @@ describe('Protocol V2 firmware reconnect identity', () => {
|
|
|
9267
9127
|
const readChunkLengths: number[] = [];
|
|
9268
9128
|
const typedCall = jest.fn((requestType: string, _responseType: string, request: any) => {
|
|
9269
9129
|
if (requestType === 'FilesystemPathInfoQuery') {
|
|
9270
|
-
return Promise.resolve({ message: { exist: true, directory: false, size:
|
|
9130
|
+
return Promise.resolve({ message: { exist: true, directory: false, size: 0x5f91 } });
|
|
9271
9131
|
}
|
|
9272
9132
|
if (requestType === 'FilesystemFileRead') {
|
|
9273
9133
|
readChunkLengths.push(request.chunk_len);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AA0BlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { LowlevelTransportSharedPlugin } from '@onekeyfe/hd-transport';
|
|
|
8
8
|
import type { BaseMethod } from '../api/BaseMethod';
|
|
9
9
|
export type CoreContext = ReturnType<Core['getCoreContext']>;
|
|
10
10
|
export declare const callAPI: (context: CoreContext, message: CoreMessage) => Promise<any>;
|
|
11
|
+
export declare function isRetryableBleProtocolV2ProbeError(method: BaseMethod, error: unknown): boolean;
|
|
11
12
|
export declare function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unknown): boolean;
|
|
12
13
|
export declare const cancel: (context: CoreContext, connectId?: string) => void;
|
|
13
14
|
export declare const onDeviceButtonHandler: (__0_0: Device, __0_1: import("../events").DeviceButtonRequestPayload) => void;
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAoClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EACV,6BAA6B,EAG9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAmE7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBAoFvE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAoClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EACV,6BAA6B,EAG9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAmE7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBAoFvE,CAAC;AAiqBF,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAWpF;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAQlF;AAsPD,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SAqF9D,CAAC;AAmGF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AAiLF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAE1C,OAAO,CAAC,cAAc,CAAC,CAAgB;IAGvC,OAAO,CAAC,sBAAsB,CAAoC;IAElE,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,OAAO,CAAC,cAAc;IA6BhB,aAAa,CAAC,OAAO,EAAE,WAAW;IAuExC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOV,gBAAgB;CAiC/B;AAED,eAAO,MAAM,QAAQ,YAIpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAYzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAiBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
|