@onekeyfe/hd-core 1.2.8-alpha.11 → 1.2.8-alpha.111
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__/core-dispose.test.ts +114 -1
- package/__tests__/core-error-output.test.ts +21 -0
- package/__tests__/device-connector-protocol.test.ts +5 -2
- package/__tests__/device-lifecycle-events.test.ts +22 -3
- package/__tests__/logBlockEvent.test.ts +43 -0
- package/__tests__/sol-sign-offchain-message.test.ts +8 -0
- package/__tests__/usb-identity-probe.test.ts +358 -0
- package/__tests__/zcash-protobuf.test.ts +141 -0
- package/__tests__/zcash-sign-pczt.test.ts +387 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts +21 -1
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/zcash/ZcashGetAddress.d.ts +12 -0
- package/dist/api/zcash/ZcashGetAddress.d.ts.map +1 -0
- package/dist/api/zcash/ZcashSignPczt.d.ts +16 -0
- package/dist/api/zcash/ZcashSignPczt.d.ts.map +1 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/index.d.ts +70 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3350 -2865
- package/dist/inject.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +2 -0
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +4 -0
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/zcashGetAddress.d.ts +22 -0
- package/dist/types/api/zcashGetAddress.d.ts.map +1 -0
- package/dist/types/api/zcashSignPczt.d.ts +9 -0
- package/dist/types/api/zcashSignPczt.d.ts.map +1 -0
- package/dist/types/device.d.ts +9 -0
- package/dist/types/device.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +4 -7
- package/src/api/SearchDevices.ts +172 -7
- package/src/api/index.ts +2 -0
- package/src/api/zcash/ZcashGetAddress.ts +121 -0
- package/src/api/zcash/ZcashSignPczt.ts +155 -0
- package/src/core/index.ts +45 -14
- package/src/data/messages/messages-protocol-v2.json +138 -1
- package/src/device/Device.ts +3 -1
- package/src/device/DeviceConnector.ts +4 -4
- package/src/events/logBlockEvent.ts +4 -2
- package/src/index.ts +1 -0
- package/src/inject.ts +4 -0
- package/src/types/api/export.ts +2 -0
- package/src/types/api/index.ts +8 -0
- package/src/types/api/zcashGetAddress.ts +36 -0
- package/src/types/api/zcashSignPczt.ts +18 -0
- package/src/types/device.ts +12 -0
package/src/api/index.ts
CHANGED
|
@@ -175,3 +175,5 @@ export { default as benfenSignTransaction } from './benfen/BenfenSignTransaction
|
|
|
175
175
|
|
|
176
176
|
export { default as neoGetAddress } from './neo/NeoGetAddress';
|
|
177
177
|
export { default as neoSignTransaction } from './neo/NeoSignTransaction';
|
|
178
|
+
export { default as zcashGetAddress } from './zcash/ZcashGetAddress';
|
|
179
|
+
export { default as zcashSignPczt } from './zcash/ZcashSignPczt';
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { ZcashAddressScope, ZcashAddressType } from '@onekeyfe/hd-transport';
|
|
2
|
+
|
|
3
|
+
import { BaseMethod } from '../BaseMethod';
|
|
4
|
+
import { serializedPath, toHardened, validatePath } from '../helpers/pathUtils';
|
|
5
|
+
import { invalidParameter, validateParams, validateResult } from '../helpers/paramsValidator';
|
|
6
|
+
import { UI_REQUEST } from '../../constants/ui-request';
|
|
7
|
+
|
|
8
|
+
import type { ZcashGetAddress as HardwareZcashGetAddress } from '@onekeyfe/hd-transport';
|
|
9
|
+
import type { ZcashGetAddressParams, ZcashAddress } from '../../types/api/zcashGetAddress';
|
|
10
|
+
import type { DeviceFirmwareRange } from '../../types';
|
|
11
|
+
|
|
12
|
+
export default class ZcashGetAddress extends BaseMethod<HardwareZcashGetAddress[]> {
|
|
13
|
+
hasBundle = false;
|
|
14
|
+
|
|
15
|
+
getSupportedProtocols() {
|
|
16
|
+
return ['V2'] as const;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
init() {
|
|
20
|
+
this.checkDeviceId = true;
|
|
21
|
+
this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
|
|
22
|
+
this.strictCheckDeviceSupport = true;
|
|
23
|
+
|
|
24
|
+
this.hasBundle = !!this.payload?.bundle;
|
|
25
|
+
const payload = this.hasBundle ? this.payload : { bundle: [this.payload] };
|
|
26
|
+
|
|
27
|
+
validateParams(payload, [{ name: 'bundle', type: 'array' }]);
|
|
28
|
+
|
|
29
|
+
this.params = [];
|
|
30
|
+
payload.bundle.forEach((batch: ZcashGetAddressParams) => {
|
|
31
|
+
// ZIP-32 account path: m/32'/133'/account'
|
|
32
|
+
const addressN = validatePath(batch.path, 3);
|
|
33
|
+
if (
|
|
34
|
+
addressN.length !== 3 ||
|
|
35
|
+
addressN[0] !== toHardened(32) ||
|
|
36
|
+
addressN[1] !== toHardened(133) ||
|
|
37
|
+
addressN[2] < toHardened(0) ||
|
|
38
|
+
addressN[2] > 0xffffffff
|
|
39
|
+
) {
|
|
40
|
+
throw invalidParameter("Zcash requires a ZIP-32 account path m/32'/133'/account'");
|
|
41
|
+
}
|
|
42
|
+
const addressType = batch.addressType ?? ZcashAddressType.UNIFIED_ORCHARD_P2PKH;
|
|
43
|
+
const scope = batch.scope ?? ZcashAddressScope.EXTERNAL;
|
|
44
|
+
const diversifierIndex = batch.diversifierIndex ?? 0;
|
|
45
|
+
if (
|
|
46
|
+
![
|
|
47
|
+
ZcashAddressType.UNIFIED_ORCHARD_P2PKH,
|
|
48
|
+
ZcashAddressType.TRANSPARENT_P2PKH,
|
|
49
|
+
ZcashAddressType.UNIFIED_ORCHARD,
|
|
50
|
+
].includes(addressType) ||
|
|
51
|
+
![ZcashAddressScope.EXTERNAL, ZcashAddressScope.INTERNAL].includes(scope)
|
|
52
|
+
) {
|
|
53
|
+
throw invalidParameter('Invalid Zcash address type or scope');
|
|
54
|
+
}
|
|
55
|
+
const maxIndex = addressType === ZcashAddressType.UNIFIED_ORCHARD ? 0xffffffff : 0x7fffffff;
|
|
56
|
+
if (
|
|
57
|
+
!Number.isSafeInteger(diversifierIndex) ||
|
|
58
|
+
diversifierIndex < 0 ||
|
|
59
|
+
diversifierIndex > maxIndex
|
|
60
|
+
) {
|
|
61
|
+
throw invalidParameter('Invalid Zcash diversifier index');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
validateParams(batch, [
|
|
65
|
+
{ name: 'path', required: true },
|
|
66
|
+
{ name: 'showOnOneKey', type: 'boolean' },
|
|
67
|
+
{ name: 'includeUfvk', type: 'boolean' },
|
|
68
|
+
{ name: 'includeSeedFingerprint', type: 'boolean' },
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
this.params.push({
|
|
72
|
+
address_n: addressN,
|
|
73
|
+
address_type: addressType,
|
|
74
|
+
scope,
|
|
75
|
+
diversifier_index: diversifierIndex,
|
|
76
|
+
show_display: batch.showOnOneKey ?? true,
|
|
77
|
+
include_ufvk: batch.includeUfvk ?? false,
|
|
78
|
+
include_seed_fingerprint: batch.includeSeedFingerprint ?? false,
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
getVersionRange(): DeviceFirmwareRange {
|
|
84
|
+
return {
|
|
85
|
+
model_pro2: {
|
|
86
|
+
min: '0.0.0',
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async run() {
|
|
92
|
+
const responses: ZcashAddress[] = [];
|
|
93
|
+
|
|
94
|
+
for (let i = 0; i < this.params.length; i++) {
|
|
95
|
+
const param = this.params[i];
|
|
96
|
+
|
|
97
|
+
const res = await this.device.commands.typedCall('ZcashGetAddress', 'ZcashAddress', {
|
|
98
|
+
...param,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const path = serializedPath(param.address_n);
|
|
102
|
+
responses.push({
|
|
103
|
+
path,
|
|
104
|
+
address: res.message.address,
|
|
105
|
+
ufvk: res.message.ufvk,
|
|
106
|
+
seedFingerprint: res.message.seed_fingerprint,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
this.postPreviousAddressMessage({
|
|
110
|
+
address: res.message.address,
|
|
111
|
+
path,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
validateResult(responses, ['address'], {
|
|
116
|
+
expectedLength: this.params.length,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return Promise.resolve(this.hasBundle ? responses : responses[0]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
2
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
3
|
+
|
|
4
|
+
import { BaseMethod } from '../BaseMethod';
|
|
5
|
+
import { invalidParameter, validateParams } from '../helpers/paramsValidator';
|
|
6
|
+
import { stripHexPrefix } from '../helpers/hexUtils';
|
|
7
|
+
import { UI_REQUEST } from '../../constants/ui-request';
|
|
8
|
+
|
|
9
|
+
import type { ZcashSignPczt as HardwareZcashSignPczt } from '@onekeyfe/hd-transport';
|
|
10
|
+
import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
|
|
11
|
+
import type { ZcashSignedPczt } from '../../types/api/zcashSignPczt';
|
|
12
|
+
import type { DeviceFirmwareRange } from '../../types';
|
|
13
|
+
|
|
14
|
+
const CHUNK_BYTE_SIZE = 1024;
|
|
15
|
+
// Host memory sanity bound on the device-announced length, not a device limit.
|
|
16
|
+
const SIGNED_PCZT_SANITY_MAX_BYTES = 16 * 1024 * 1024;
|
|
17
|
+
|
|
18
|
+
export default class ZcashSignPczt extends BaseMethod<HardwareZcashSignPczt> {
|
|
19
|
+
pczt: Buffer = Buffer.alloc(0);
|
|
20
|
+
|
|
21
|
+
getSupportedProtocols() {
|
|
22
|
+
return ['V2'] as const;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
init() {
|
|
26
|
+
this.checkDeviceId = true;
|
|
27
|
+
this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
|
|
28
|
+
this.strictCheckDeviceSupport = true;
|
|
29
|
+
|
|
30
|
+
validateParams(this.payload, [{ name: 'pczt', type: 'hexString', required: true }]);
|
|
31
|
+
|
|
32
|
+
// Reject odd-length hex instead of left-padding it, which would shift every nibble.
|
|
33
|
+
const pcztHex = stripHexPrefix(this.payload.pczt);
|
|
34
|
+
if (pcztHex.length % 2 !== 0) {
|
|
35
|
+
throw invalidParameter('pczt hex must have an even length');
|
|
36
|
+
}
|
|
37
|
+
this.pczt = Buffer.from(pcztHex, 'hex');
|
|
38
|
+
if (this.pczt.length === 0) {
|
|
39
|
+
throw invalidParameter('pczt is empty');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.params = {
|
|
43
|
+
pczt_length: this.pczt.length,
|
|
44
|
+
pczt_initial_chunk: bytesToHex(this.pczt.subarray(0, CHUNK_BYTE_SIZE)),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getVersionRange(): DeviceFirmwareRange {
|
|
49
|
+
return {
|
|
50
|
+
model_pro2: {
|
|
51
|
+
min: '0.0.0',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Upload: the device decides every chunk length via ZcashPcztChunkRequest and
|
|
57
|
+
// the host must answer with exactly that many bytes.
|
|
58
|
+
uploadPczt = async (
|
|
59
|
+
typedCall: TypedCall,
|
|
60
|
+
res: TypedResponseMessage<'ZcashSignedPczt'> | TypedResponseMessage<'ZcashPcztChunkRequest'>,
|
|
61
|
+
offset: number
|
|
62
|
+
): Promise<TypedResponseMessage<'ZcashSignedPczt'>> => {
|
|
63
|
+
if (res.type === 'ZcashSignedPczt') {
|
|
64
|
+
if (offset !== this.pczt.length) {
|
|
65
|
+
throw ERRORS.TypedError(
|
|
66
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
67
|
+
'device completed signing before receiving the whole pczt'
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
return res;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const { chunk_length: chunkLength } = res.message;
|
|
74
|
+
if (
|
|
75
|
+
!Number.isSafeInteger(chunkLength) ||
|
|
76
|
+
chunkLength <= 0 ||
|
|
77
|
+
offset + chunkLength > this.pczt.length
|
|
78
|
+
) {
|
|
79
|
+
throw ERRORS.TypedError(
|
|
80
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
81
|
+
`device requested ${chunkLength} bytes at offset ${offset} of ${this.pczt.length}`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const chunk = this.pczt.subarray(offset, offset + chunkLength);
|
|
86
|
+
const next = await typedCall(
|
|
87
|
+
'ZcashPcztChunkAck',
|
|
88
|
+
['ZcashSignedPczt', 'ZcashPcztChunkRequest'],
|
|
89
|
+
{
|
|
90
|
+
data_chunk: bytesToHex(chunk),
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return this.uploadPczt(typedCall, next, offset + chunkLength);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Download: the host decides chunk lengths via ZcashSignedPcztChunkRequest
|
|
98
|
+
// until the announced pczt_length has been received.
|
|
99
|
+
downloadSignedPczt = async (
|
|
100
|
+
typedCall: TypedCall,
|
|
101
|
+
res: TypedResponseMessage<'ZcashSignedPczt'>
|
|
102
|
+
): Promise<Buffer> => {
|
|
103
|
+
const { pczt_length: total, pczt_initial_chunk: initial } = res.message;
|
|
104
|
+
if (!Number.isSafeInteger(total) || total <= 0 || total > SIGNED_PCZT_SANITY_MAX_BYTES) {
|
|
105
|
+
throw ERRORS.TypedError(
|
|
106
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
107
|
+
`device announced invalid signed pczt length ${total}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const parts: Buffer[] = [Buffer.from(initial ?? '', 'hex')];
|
|
112
|
+
let received = parts[0].length;
|
|
113
|
+
if (received > total) {
|
|
114
|
+
throw ERRORS.TypedError(
|
|
115
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
116
|
+
'device returned more initial pczt bytes than announced'
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
while (received < total) {
|
|
121
|
+
const chunkLength = Math.min(CHUNK_BYTE_SIZE, total - received);
|
|
122
|
+
const ack = await typedCall('ZcashSignedPcztChunkRequest', 'ZcashPcztChunkAck', {
|
|
123
|
+
chunk_length: chunkLength,
|
|
124
|
+
});
|
|
125
|
+
const chunk = Buffer.from(ack.message.data_chunk ?? '', 'hex');
|
|
126
|
+
if (chunk.length !== chunkLength) {
|
|
127
|
+
throw ERRORS.TypedError(
|
|
128
|
+
HardwareErrorCode.ResponseUnexpectTypeError,
|
|
129
|
+
`device returned ${chunk.length} of ${chunkLength} requested bytes at offset ${received} of ${total}`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
parts.push(chunk);
|
|
133
|
+
received += chunk.length;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return Buffer.concat(parts);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
async run(): Promise<ZcashSignedPczt> {
|
|
140
|
+
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
141
|
+
|
|
142
|
+
const first = await typedCall('ZcashSignPczt', ['ZcashSignedPczt', 'ZcashPcztChunkRequest'], {
|
|
143
|
+
...this.params,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const signed = await this.uploadPczt(
|
|
147
|
+
typedCall,
|
|
148
|
+
first,
|
|
149
|
+
Math.min(CHUNK_BYTE_SIZE, this.pczt.length)
|
|
150
|
+
);
|
|
151
|
+
const pczt = await this.downloadSignedPczt(typedCall, signed);
|
|
152
|
+
|
|
153
|
+
return { pczt: bytesToHex(pczt) };
|
|
154
|
+
}
|
|
155
|
+
}
|
package/src/core/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import semver from 'semver';
|
|
2
|
+
import { getOwnedUsbDeviceIdentity } from '../api/SearchDevices';
|
|
2
3
|
import EventEmitter from 'events';
|
|
3
4
|
import {
|
|
4
5
|
DeviceSessionPinType,
|
|
@@ -125,6 +126,8 @@ const parseInitOptions = (method?: BaseMethod): InitOptions => ({
|
|
|
125
126
|
});
|
|
126
127
|
|
|
127
128
|
let _core: Core | undefined;
|
|
129
|
+
let transportSwitchGeneration = 0;
|
|
130
|
+
let pendingTransportSwitch: Promise<void> = Promise.resolve();
|
|
128
131
|
let _deviceList: DeviceList | undefined;
|
|
129
132
|
let _connector: DeviceConnector | undefined;
|
|
130
133
|
let _uiPromises: UiPromise<UiPromiseResponse['type']>[] = []; // Waiting for ui response
|
|
@@ -990,15 +993,11 @@ function canSkipInitialize(method: BaseMethod, device: Device): boolean {
|
|
|
990
993
|
}
|
|
991
994
|
|
|
992
995
|
export function isRetryableBleProtocolV2ProbeError(method: BaseMethod, error: unknown) {
|
|
993
|
-
const typedError = error as { errorCode?: unknown;
|
|
994
|
-
const message =
|
|
995
|
-
typeof typedError?.message === 'string' ? typedError.message : String(error ?? '');
|
|
996
|
+
const typedError = error as { errorCode?: unknown; params?: { expectedProtocol?: unknown } };
|
|
996
997
|
return (
|
|
997
998
|
method.payload.connectProtocol === 'V2' &&
|
|
998
|
-
typedError?.errorCode === HardwareErrorCode.
|
|
999
|
-
|
|
1000
|
-
message.includes('expected V2') &&
|
|
1001
|
-
message.includes('did not respond to expected protocol')
|
|
999
|
+
typedError?.errorCode === HardwareErrorCode.TransportProtocolProbeFailed &&
|
|
1000
|
+
typedError.params?.expectedProtocol === 'V2'
|
|
1002
1001
|
);
|
|
1003
1002
|
}
|
|
1004
1003
|
|
|
@@ -1008,7 +1007,7 @@ export function isRetryableBleConnectionError(method: BaseMethod, error: unknown
|
|
|
1008
1007
|
}
|
|
1009
1008
|
const typedError = error as {
|
|
1010
1009
|
errorCode?: unknown;
|
|
1011
|
-
params?: { acquireDeadlineExceeded?: unknown };
|
|
1010
|
+
params?: { acquireDeadlineExceeded?: unknown; expectedProtocol?: unknown };
|
|
1012
1011
|
};
|
|
1013
1012
|
if (
|
|
1014
1013
|
typedError?.errorCode === HardwareErrorCode.BleTimeoutError &&
|
|
@@ -1019,6 +1018,8 @@ export function isRetryableBleConnectionError(method: BaseMethod, error: unknown
|
|
|
1019
1018
|
return (
|
|
1020
1019
|
typedError?.errorCode === HardwareErrorCode.BleTimeoutError ||
|
|
1021
1020
|
typedError?.errorCode === HardwareErrorCode.BleConnectedError ||
|
|
1021
|
+
(typedError?.errorCode === HardwareErrorCode.TransportProtocolProbeFailed &&
|
|
1022
|
+
!typedError.params?.expectedProtocol) ||
|
|
1022
1023
|
isRetryableBleProtocolV2ProbeError(method, error) ||
|
|
1023
1024
|
isMissingDetectedProtocolV2Error(method, error)
|
|
1024
1025
|
);
|
|
@@ -1273,6 +1274,8 @@ const ensureConnected = async (
|
|
|
1273
1274
|
HardwareErrorCode.BridgeTimeoutError,
|
|
1274
1275
|
HardwareErrorCode.BridgeNeedsPermission,
|
|
1275
1276
|
HardwareErrorCode.WebUsbDeviceAccessError,
|
|
1277
|
+
HardwareErrorCode.TransportProtocolProbeFailed,
|
|
1278
|
+
HardwareErrorCode.TransportProtocolMismatch,
|
|
1276
1279
|
].includes(error.errorCode)
|
|
1277
1280
|
) {
|
|
1278
1281
|
_deviceList = undefined;
|
|
@@ -1360,6 +1363,8 @@ const ensureConnected = async (
|
|
|
1360
1363
|
HardwareErrorCode.BleCharacteristicNotifyChangeFailure,
|
|
1361
1364
|
HardwareErrorCode.BridgeNeedsPermission,
|
|
1362
1365
|
HardwareErrorCode.WebUsbDeviceAccessError,
|
|
1366
|
+
HardwareErrorCode.TransportProtocolProbeFailed,
|
|
1367
|
+
HardwareErrorCode.TransportProtocolMismatch,
|
|
1363
1368
|
HardwareErrorCode.DeviceInterruptedFromUser,
|
|
1364
1369
|
HardwareErrorCode.CallQueueActionCancelled,
|
|
1365
1370
|
].includes(error.errorCode) ||
|
|
@@ -1826,6 +1831,10 @@ export default class Core extends EventEmitter {
|
|
|
1826
1831
|
|
|
1827
1832
|
private requestQueue = new RequestQueue();
|
|
1828
1833
|
|
|
1834
|
+
getOwnedUsbDeviceIdentity(descriptor: Parameters<typeof getOwnedUsbDeviceIdentity>[0]) {
|
|
1835
|
+
return getOwnedUsbDeviceIdentity(descriptor, this.requestQueue);
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1829
1838
|
private disposePromise?: Promise<void>;
|
|
1830
1839
|
|
|
1831
1840
|
// background task
|
|
@@ -1959,6 +1968,8 @@ export default class Core extends EventEmitter {
|
|
|
1959
1968
|
|
|
1960
1969
|
private async disposeResources(): Promise<void> {
|
|
1961
1970
|
Log.debug(`[Core] Disposing SDK instance: ${this.sdkInstanceId}`);
|
|
1971
|
+
transportSwitchGeneration += 1;
|
|
1972
|
+
pendingTransportSwitch = Promise.resolve();
|
|
1962
1973
|
pollingManager.stopAll();
|
|
1963
1974
|
this.requestQueue.abortAllRequests();
|
|
1964
1975
|
cleanup();
|
|
@@ -1993,6 +2004,8 @@ export default class Core extends EventEmitter {
|
|
|
1993
2004
|
}
|
|
1994
2005
|
|
|
1995
2006
|
export const initCore = () => {
|
|
2007
|
+
transportSwitchGeneration += 1;
|
|
2008
|
+
pendingTransportSwitch = Promise.resolve();
|
|
1996
2009
|
const core = new Core();
|
|
1997
2010
|
_core = core;
|
|
1998
2011
|
return core;
|
|
@@ -2022,6 +2035,8 @@ export const init = async (
|
|
|
2022
2035
|
plugin?: LowlevelTransportSharedPlugin
|
|
2023
2036
|
) => {
|
|
2024
2037
|
try {
|
|
2038
|
+
transportSwitchGeneration += 1;
|
|
2039
|
+
pendingTransportSwitch = Promise.resolve();
|
|
2025
2040
|
await DataManager.load(settings);
|
|
2026
2041
|
initTransport(Transport, plugin);
|
|
2027
2042
|
enableLog(DataManager.getSettings('debug'));
|
|
@@ -2047,10 +2062,26 @@ export const switchTransport = ({
|
|
|
2047
2062
|
Transport: any;
|
|
2048
2063
|
plugin?: LowlevelTransportSharedPlugin;
|
|
2049
2064
|
}) => {
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2065
|
+
const generation = transportSwitchGeneration;
|
|
2066
|
+
// Preserve request order while native transport cleanup is pending.
|
|
2067
|
+
const switching = pendingTransportSwitch
|
|
2068
|
+
.catch(() => undefined)
|
|
2069
|
+
.then(async () => {
|
|
2070
|
+
if (generation !== transportSwitchGeneration) {
|
|
2071
|
+
throw ERRORS.TypedError(HardwareErrorCode.NotInitialized);
|
|
2072
|
+
}
|
|
2073
|
+
_connector?.stop();
|
|
2074
|
+
await TransportManager.getTransport()?.stop?.();
|
|
2075
|
+
if (generation !== transportSwitchGeneration) {
|
|
2076
|
+
throw ERRORS.TypedError(HardwareErrorCode.NotInitialized);
|
|
2077
|
+
}
|
|
2078
|
+
DataManager.updateEnv(env);
|
|
2079
|
+
TransportManager.setTransport(Transport, plugin);
|
|
2080
|
+
_deviceList = undefined;
|
|
2081
|
+
DevicePool.resetState();
|
|
2082
|
+
_connector = undefined;
|
|
2083
|
+
initConnector();
|
|
2084
|
+
});
|
|
2085
|
+
pendingTransportSwitch = switching;
|
|
2086
|
+
return switching;
|
|
2056
2087
|
};
|
|
@@ -11034,6 +11034,61 @@
|
|
|
11034
11034
|
}
|
|
11035
11035
|
}
|
|
11036
11036
|
},
|
|
11037
|
+
"ZcashSignPczt": {
|
|
11038
|
+
"fields": {
|
|
11039
|
+
"pczt_length": {
|
|
11040
|
+
"rule": "required",
|
|
11041
|
+
"type": "uint32",
|
|
11042
|
+
"id": 1
|
|
11043
|
+
},
|
|
11044
|
+
"pczt_initial_chunk": {
|
|
11045
|
+
"rule": "required",
|
|
11046
|
+
"type": "bytes",
|
|
11047
|
+
"id": 2
|
|
11048
|
+
}
|
|
11049
|
+
}
|
|
11050
|
+
},
|
|
11051
|
+
"ZcashPcztChunkRequest": {
|
|
11052
|
+
"fields": {
|
|
11053
|
+
"chunk_length": {
|
|
11054
|
+
"rule": "required",
|
|
11055
|
+
"type": "uint32",
|
|
11056
|
+
"id": 1
|
|
11057
|
+
}
|
|
11058
|
+
}
|
|
11059
|
+
},
|
|
11060
|
+
"ZcashPcztChunkAck": {
|
|
11061
|
+
"fields": {
|
|
11062
|
+
"data_chunk": {
|
|
11063
|
+
"rule": "required",
|
|
11064
|
+
"type": "bytes",
|
|
11065
|
+
"id": 1
|
|
11066
|
+
}
|
|
11067
|
+
}
|
|
11068
|
+
},
|
|
11069
|
+
"ZcashSignedPczt": {
|
|
11070
|
+
"fields": {
|
|
11071
|
+
"pczt_length": {
|
|
11072
|
+
"rule": "required",
|
|
11073
|
+
"type": "uint32",
|
|
11074
|
+
"id": 1
|
|
11075
|
+
},
|
|
11076
|
+
"pczt_initial_chunk": {
|
|
11077
|
+
"rule": "required",
|
|
11078
|
+
"type": "bytes",
|
|
11079
|
+
"id": 2
|
|
11080
|
+
}
|
|
11081
|
+
}
|
|
11082
|
+
},
|
|
11083
|
+
"ZcashSignedPcztChunkRequest": {
|
|
11084
|
+
"fields": {
|
|
11085
|
+
"chunk_length": {
|
|
11086
|
+
"rule": "required",
|
|
11087
|
+
"type": "uint32",
|
|
11088
|
+
"id": 1
|
|
11089
|
+
}
|
|
11090
|
+
}
|
|
11091
|
+
},
|
|
11037
11092
|
"wire_in": {
|
|
11038
11093
|
"type": "bool",
|
|
11039
11094
|
"id": 50002,
|
|
@@ -11459,6 +11514,11 @@
|
|
|
11459
11514
|
"MessageType_NeoAddress": 12302,
|
|
11460
11515
|
"MessageType_NeoSignTx": 12303,
|
|
11461
11516
|
"MessageType_NeoSignedTx": 12304,
|
|
11517
|
+
"MessageType_ZcashSignPczt": 12402,
|
|
11518
|
+
"MessageType_ZcashSignedPczt": 12403,
|
|
11519
|
+
"MessageType_ZcashPcztChunkRequest": 12404,
|
|
11520
|
+
"MessageType_ZcashPcztChunkAck": 12405,
|
|
11521
|
+
"MessageType_ZcashSignedPcztChunkRequest": 12406,
|
|
11462
11522
|
"MessageType_DeviceFactoryInfoSet": 60000,
|
|
11463
11523
|
"MessageType_DeviceFactoryInfoGet": 60001,
|
|
11464
11524
|
"MessageType_DeviceFactoryInfo": 60002,
|
|
@@ -11511,7 +11571,9 @@
|
|
|
11511
11571
|
"MessageType_PortfolioUpdate": 61400,
|
|
11512
11572
|
"MessageType_NftUpdate": 61500,
|
|
11513
11573
|
"MessageType_OnboardingStatusGet": 61600,
|
|
11514
|
-
"MessageType_OnboardingStatus": 61601
|
|
11574
|
+
"MessageType_OnboardingStatus": 61601,
|
|
11575
|
+
"MessageType_ZcashGetAddress": 12400,
|
|
11576
|
+
"MessageType_ZcashAddress": 12401
|
|
11515
11577
|
},
|
|
11516
11578
|
"reserved": [
|
|
11517
11579
|
[90, 92],
|
|
@@ -13730,6 +13792,81 @@
|
|
|
13730
13792
|
}
|
|
13731
13793
|
}
|
|
13732
13794
|
}
|
|
13795
|
+
},
|
|
13796
|
+
"ZcashAddressType": {
|
|
13797
|
+
"values": {
|
|
13798
|
+
"UNIFIED_ORCHARD_P2PKH": 0,
|
|
13799
|
+
"TRANSPARENT_P2PKH": 1,
|
|
13800
|
+
"UNIFIED_ORCHARD": 2
|
|
13801
|
+
}
|
|
13802
|
+
},
|
|
13803
|
+
"ZcashAddressScope": {
|
|
13804
|
+
"values": {
|
|
13805
|
+
"EXTERNAL": 0,
|
|
13806
|
+
"INTERNAL": 1
|
|
13807
|
+
}
|
|
13808
|
+
},
|
|
13809
|
+
"ZcashGetAddress": {
|
|
13810
|
+
"fields": {
|
|
13811
|
+
"address_n": {
|
|
13812
|
+
"rule": "repeated",
|
|
13813
|
+
"type": "uint32",
|
|
13814
|
+
"id": 1,
|
|
13815
|
+
"options": {
|
|
13816
|
+
"packed": false
|
|
13817
|
+
}
|
|
13818
|
+
},
|
|
13819
|
+
"show_display": {
|
|
13820
|
+
"type": "bool",
|
|
13821
|
+
"id": 2
|
|
13822
|
+
},
|
|
13823
|
+
"include_seed_fingerprint": {
|
|
13824
|
+
"type": "bool",
|
|
13825
|
+
"id": 3
|
|
13826
|
+
},
|
|
13827
|
+
"include_ufvk": {
|
|
13828
|
+
"type": "bool",
|
|
13829
|
+
"id": 4
|
|
13830
|
+
},
|
|
13831
|
+
"diversifier_index": {
|
|
13832
|
+
"type": "uint32",
|
|
13833
|
+
"id": 5,
|
|
13834
|
+
"options": {
|
|
13835
|
+
"default": 0
|
|
13836
|
+
}
|
|
13837
|
+
},
|
|
13838
|
+
"address_type": {
|
|
13839
|
+
"type": "ZcashAddressType",
|
|
13840
|
+
"id": 6,
|
|
13841
|
+
"options": {
|
|
13842
|
+
"default": "UNIFIED_ORCHARD_P2PKH"
|
|
13843
|
+
}
|
|
13844
|
+
},
|
|
13845
|
+
"scope": {
|
|
13846
|
+
"type": "ZcashAddressScope",
|
|
13847
|
+
"id": 7,
|
|
13848
|
+
"options": {
|
|
13849
|
+
"default": "EXTERNAL"
|
|
13850
|
+
}
|
|
13851
|
+
}
|
|
13852
|
+
}
|
|
13853
|
+
},
|
|
13854
|
+
"ZcashAddress": {
|
|
13855
|
+
"fields": {
|
|
13856
|
+
"address": {
|
|
13857
|
+
"rule": "required",
|
|
13858
|
+
"type": "string",
|
|
13859
|
+
"id": 1
|
|
13860
|
+
},
|
|
13861
|
+
"ufvk": {
|
|
13862
|
+
"type": "string",
|
|
13863
|
+
"id": 2
|
|
13864
|
+
},
|
|
13865
|
+
"seed_fingerprint": {
|
|
13866
|
+
"type": "bytes",
|
|
13867
|
+
"id": 3
|
|
13868
|
+
}
|
|
13869
|
+
}
|
|
13733
13870
|
}
|
|
13734
13871
|
}
|
|
13735
13872
|
}
|
package/src/device/Device.ts
CHANGED
|
@@ -587,10 +587,12 @@ export class Device extends EventEmitter {
|
|
|
587
587
|
try {
|
|
588
588
|
// BLE releases even when keepSession is set, so forward the intent.
|
|
589
589
|
await this.deviceConnector?.release(this.mainId, false, this.keepSession);
|
|
590
|
-
this.updateDescriptor({ session: null } as DeviceDescriptor);
|
|
591
590
|
} catch (err) {
|
|
592
591
|
Log.error('[Device] release error: ', err);
|
|
593
592
|
} finally {
|
|
593
|
+
// Core no longer owns a logical transport session after release starts,
|
|
594
|
+
// even if native cleanup must be retried by the transport.
|
|
595
|
+
this.updateDescriptor({ session: null } as DeviceDescriptor);
|
|
594
596
|
this.needReloadDevice = true;
|
|
595
597
|
}
|
|
596
598
|
}
|
|
@@ -133,10 +133,10 @@ export default class DeviceConnector {
|
|
|
133
133
|
: undefined;
|
|
134
134
|
const detectedProtocol = acquiredProtocol ?? transport.getProtocolType(path);
|
|
135
135
|
if (detectedProtocol !== expectedProtocol) {
|
|
136
|
-
throw ERRORS.TypedError(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
);
|
|
136
|
+
throw ERRORS.TypedError(HardwareErrorCode.TransportProtocolMismatch, undefined, {
|
|
137
|
+
expectedProtocol,
|
|
138
|
+
detectedProtocol,
|
|
139
|
+
});
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
return res;
|
|
@@ -8,8 +8,8 @@ export const LogBlockEvent: Set<string> = new Set([
|
|
|
8
8
|
UI_RESPONSE.RECEIVE_PASSPHRASE,
|
|
9
9
|
]);
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
//
|
|
11
|
+
// Drop sensitive wallet payloads and large resource data before logger caches
|
|
12
|
+
// or log events can retain them, regardless of whether debug output is enabled.
|
|
13
13
|
const LogPayloadBlockMethod: Set<string> = new Set([
|
|
14
14
|
'btcDeriveContextHash',
|
|
15
15
|
'deviceUploadNft',
|
|
@@ -17,6 +17,8 @@ const LogPayloadBlockMethod: Set<string> = new Set([
|
|
|
17
17
|
'uploadPortfolio',
|
|
18
18
|
'fileWrite',
|
|
19
19
|
'fileRead',
|
|
20
|
+
'zcashGetAddress',
|
|
21
|
+
'zcashSignPczt',
|
|
20
22
|
]);
|
|
21
23
|
|
|
22
24
|
export function getLogBlockLabel(message: unknown): string | undefined {
|
package/src/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { executeCallback, cleanupCallback };
|
|
|
21
21
|
export { preloadSessionCache } from './device/Device';
|
|
22
22
|
export { projectFeatures as projectDeviceStateFeatures } from './device/DeviceStateProjector';
|
|
23
23
|
export { getMethodSupportedProtocols } from './api/utils';
|
|
24
|
+
export { probeUsbDeviceIdentitiesWithTransport } from './api/SearchDevices';
|
|
24
25
|
export {
|
|
25
26
|
getFirmwareUpdateHostBindingGeneration,
|
|
26
27
|
registerFirmwareUpdateHostBinding,
|
package/src/inject.ts
CHANGED
|
@@ -504,4 +504,8 @@ export const createCoreApi = (
|
|
|
504
504
|
call({ ...params, connectId, deviceId, method: 'neoGetAddress' }),
|
|
505
505
|
neoSignTransaction: (connectId, deviceId, params) =>
|
|
506
506
|
call({ ...params, connectId, deviceId, method: 'neoSignTransaction' }),
|
|
507
|
+
zcashGetAddress: (connectId, deviceId, params) =>
|
|
508
|
+
call({ ...params, connectId, deviceId, method: 'zcashGetAddress' }),
|
|
509
|
+
zcashSignPczt: (connectId, deviceId, params) =>
|
|
510
|
+
call({ ...params, connectId, deviceId, method: 'zcashSignPczt' }),
|
|
507
511
|
});
|
package/src/types/api/export.ts
CHANGED
|
@@ -227,3 +227,5 @@ export type { BenfenAddress, BenfenGetAddressParams } from './benfenGetAddress';
|
|
|
227
227
|
export type { BenfenPublicKey, BenfenGetPublicKeyParams } from './benfenGetPublicKey';
|
|
228
228
|
export type { BenfenSignMessageParams } from './benfenSignMessage';
|
|
229
229
|
export type { BenfenSignedTx, BenfenSignTransactionParams } from './benfenSignTransaction';
|
|
230
|
+
export type { ZcashAddress, ZcashGetAddressParams } from './zcashGetAddress';
|
|
231
|
+
export type { ZcashSignedPczt, ZcashSignPcztParams } from './zcashSignPczt';
|
package/src/types/api/index.ts
CHANGED
|
@@ -154,6 +154,8 @@ import type { benfenSignTransaction } from './benfenSignTransaction';
|
|
|
154
154
|
import type { benfenSignMessage } from './benfenSignMessage';
|
|
155
155
|
import type { neoGetAddress } from './neoGetAddress';
|
|
156
156
|
import type { neoSignTransaction } from './neoSignTransaction';
|
|
157
|
+
import type { zcashGetAddress } from './zcashGetAddress';
|
|
158
|
+
import type { zcashSignPczt } from './zcashSignPczt';
|
|
157
159
|
import type { ConnectSettings } from '../settings';
|
|
158
160
|
import type { HardwareConnectProtocol } from '@onekeyfe/hd-shared';
|
|
159
161
|
|
|
@@ -472,4 +474,10 @@ export type CoreApi = {
|
|
|
472
474
|
*/
|
|
473
475
|
neoGetAddress: typeof neoGetAddress;
|
|
474
476
|
neoSignTransaction: typeof neoSignTransaction;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Zcash
|
|
480
|
+
*/
|
|
481
|
+
zcashGetAddress: typeof zcashGetAddress;
|
|
482
|
+
zcashSignPczt: typeof zcashSignPczt;
|
|
475
483
|
};
|