@sidhujag/sysweb3-keyring 1.0.628 → 2.0.0
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/CHANGELOG.md +22 -0
- package/README.md +66 -0
- package/cjs/hardware-wallet-manager.js +302 -128
- package/cjs/hardware-wallet-manager.js.map +1 -1
- package/cjs/keyring-core.js +93 -0
- package/cjs/keyring-core.js.map +1 -1
- package/cjs/keyring-manager.js +9 -3
- package/cjs/keyring-manager.js.map +1 -1
- package/cjs/ledger/bitcoin_client/lib/appClient.js.map +1 -1
- package/cjs/ledger/host-types.js +10 -0
- package/cjs/ledger/host-types.js.map +1 -0
- package/cjs/ledger/index.js +243 -447
- package/cjs/ledger/index.js.map +1 -1
- package/cjs/ledger/prepare-psbt.js +177 -0
- package/cjs/ledger/prepare-psbt.js.map +1 -0
- package/cjs/software-hd-account.js +23 -0
- package/cjs/software-hd-account.js.map +1 -0
- package/cjs/software.js +16 -0
- package/cjs/software.js.map +1 -1
- package/cjs/transactions/ethereum.js +55 -10
- package/cjs/transactions/ethereum.js.map +1 -1
- package/cjs/transactions/hardware-psbt.js +36 -44
- package/cjs/transactions/hardware-psbt.js.map +1 -1
- package/cjs/transactions/prepared-evm.js +196 -0
- package/cjs/transactions/prepared-evm.js.map +1 -0
- package/cjs/trezor/connect.js +243 -0
- package/cjs/trezor/connect.js.map +1 -0
- package/cjs/trezor/index.js +96 -58
- package/cjs/trezor/index.js.map +1 -1
- package/cjs/trezor/witness.js +25 -0
- package/cjs/trezor/witness.js.map +1 -0
- package/cjs/utils/psbt-account-scope.js +5 -3
- package/cjs/utils/psbt-account-scope.js.map +1 -1
- package/esm/errorUtils.js +72 -0
- package/esm/errorUtils.js.map +1 -0
- package/esm/ethers-v6.js +207 -0
- package/esm/ethers-v6.js.map +1 -0
- package/esm/hardware-wallet-manager.js +643 -0
- package/esm/hardware-wallet-manager.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/appClient.js +279 -0
- package/esm/ledger/bitcoin_client/lib/appClient.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/bip32.js +49 -0
- package/esm/ledger/bitcoin_client/lib/bip32.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/buffertools.js +119 -0
- package/esm/ledger/bitcoin_client/lib/buffertools.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/clientCommands.js +269 -0
- package/esm/ledger/bitcoin_client/lib/clientCommands.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/merkelizedPsbt.js +50 -0
- package/esm/ledger/bitcoin_client/lib/merkelizedPsbt.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/merkle.js +111 -0
- package/esm/ledger/bitcoin_client/lib/merkle.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/merkleMap.js +42 -0
- package/esm/ledger/bitcoin_client/lib/merkleMap.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/policy.js +68 -0
- package/esm/ledger/bitcoin_client/lib/policy.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/psbtv2.js +645 -0
- package/esm/ledger/bitcoin_client/lib/psbtv2.js.map +1 -0
- package/esm/ledger/bitcoin_client/lib/varint.js +108 -0
- package/esm/ledger/bitcoin_client/lib/varint.js.map +1 -0
- package/esm/ledger/consts.js +4 -0
- package/esm/ledger/consts.js.map +1 -0
- package/esm/ledger/dmk-evm.js +258 -0
- package/esm/ledger/dmk-evm.js.map +1 -0
- package/esm/ledger/dmk-session.js +264 -0
- package/esm/ledger/dmk-session.js.map +1 -0
- package/esm/ledger/dmk-utxo.js +279 -0
- package/esm/ledger/dmk-utxo.js.map +1 -0
- package/esm/ledger/host-types.js +5 -0
- package/esm/ledger/host-types.js.map +1 -0
- package/esm/ledger/index.js +268 -0
- package/esm/ledger/index.js.map +1 -0
- package/esm/ledger/prepare-psbt.js +141 -0
- package/esm/ledger/prepare-psbt.js.map +1 -0
- package/esm/ledger/types.js +2 -0
- package/esm/ledger/types.js.map +1 -0
- package/esm/ledger-host.js +36 -0
- package/esm/ledger-host.js.map +1 -0
- package/esm/private-records.js +153 -0
- package/esm/private-records.js.map +1 -0
- package/esm/providers.js +588 -0
- package/esm/providers.js.map +1 -0
- package/esm/signers.js +28 -0
- package/esm/signers.js.map +1 -0
- package/esm/trezor/connect.js +206 -0
- package/esm/trezor/connect.js.map +1 -0
- package/esm/trezor/index.js +876 -0
- package/esm/trezor/index.js.map +1 -0
- package/esm/trezor/witness.js +21 -0
- package/esm/trezor/witness.js.map +1 -0
- package/esm/types.js +17 -0
- package/esm/types.js.map +1 -0
- package/esm/utils/derivation-paths.js +109 -0
- package/esm/utils/derivation-paths.js.map +1 -0
- package/esm/utils/psbt-account-scope.js +310 -0
- package/esm/utils/psbt-account-scope.js.map +1 -0
- package/package.json +21 -8
- package/types/hardware-wallet-manager.d.ts +12 -19
- package/types/keyring-core.d.ts +6 -0
- package/types/keyring-manager.d.ts +2 -1
- package/types/ledger/bitcoin_client/lib/appClient.d.ts +6 -3
- package/types/ledger/dmk-evm.d.ts +8 -0
- package/types/ledger/dmk-session.d.ts +60 -0
- package/types/ledger/dmk-utxo.d.ts +26 -0
- package/types/ledger/host-types.d.ts +131 -0
- package/types/ledger/index.d.ts +21 -58
- package/types/ledger/prepare-psbt.d.ts +3 -0
- package/types/ledger/types.d.ts +3 -0
- package/types/ledger-host.d.ts +7 -0
- package/types/software-hd-account.d.ts +16 -0
- package/types/software.d.ts +16 -0
- package/types/transactions/ethereum.d.ts +1 -1
- package/types/transactions/prepared-evm.d.ts +53 -0
- package/types/trezor/connect.d.ts +42 -0
- package/types/trezor/index.d.ts +22 -4
- package/types/trezor/witness.d.ts +3 -0
- package/types/utils/psbt-account-scope.d.ts +1 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
import CryptoJS from 'crypto-js';
|
|
3
|
+
// Helper function for SHA256 hashing (browser-compatible)
|
|
4
|
+
function sha256(data) {
|
|
5
|
+
const wordArray = CryptoJS.lib.WordArray.create(data);
|
|
6
|
+
const hash = CryptoJS.SHA256(wordArray);
|
|
7
|
+
const hashBuffer = Buffer.from(hash.toString(CryptoJS.enc.Hex), 'hex');
|
|
8
|
+
return hashBuffer;
|
|
9
|
+
}
|
|
10
|
+
import { BufferReader } from './buffertools';
|
|
11
|
+
import { hashLeaf, Merkle } from './merkle';
|
|
12
|
+
import { createVarint, sanitizeBigintToNumber } from './varint';
|
|
13
|
+
var ClientCommandCode;
|
|
14
|
+
(function (ClientCommandCode) {
|
|
15
|
+
ClientCommandCode[ClientCommandCode["YIELD"] = 16] = "YIELD";
|
|
16
|
+
ClientCommandCode[ClientCommandCode["GET_PREIMAGE"] = 64] = "GET_PREIMAGE";
|
|
17
|
+
ClientCommandCode[ClientCommandCode["GET_MERKLE_LEAF_PROOF"] = 65] = "GET_MERKLE_LEAF_PROOF";
|
|
18
|
+
ClientCommandCode[ClientCommandCode["GET_MERKLE_LEAF_INDEX"] = 66] = "GET_MERKLE_LEAF_INDEX";
|
|
19
|
+
ClientCommandCode[ClientCommandCode["GET_MORE_ELEMENTS"] = 160] = "GET_MORE_ELEMENTS";
|
|
20
|
+
})(ClientCommandCode || (ClientCommandCode = {}));
|
|
21
|
+
class ClientCommand {
|
|
22
|
+
}
|
|
23
|
+
export class YieldCommand extends ClientCommand {
|
|
24
|
+
constructor(results, progressCallback) {
|
|
25
|
+
super();
|
|
26
|
+
this.progressCallback = progressCallback;
|
|
27
|
+
this.code = ClientCommandCode.YIELD;
|
|
28
|
+
this.results = results;
|
|
29
|
+
}
|
|
30
|
+
execute(request) {
|
|
31
|
+
this.results.push(Buffer.from(request.subarray(1)));
|
|
32
|
+
if (this.progressCallback) {
|
|
33
|
+
this.progressCallback();
|
|
34
|
+
}
|
|
35
|
+
return Buffer.from('');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class GetPreimageCommand extends ClientCommand {
|
|
39
|
+
constructor(known_preimages, queue) {
|
|
40
|
+
super();
|
|
41
|
+
this.code = ClientCommandCode.GET_PREIMAGE;
|
|
42
|
+
this.known_preimages = known_preimages;
|
|
43
|
+
this.queue = queue;
|
|
44
|
+
}
|
|
45
|
+
execute(request) {
|
|
46
|
+
const req = Buffer.from(request.subarray(1));
|
|
47
|
+
// we expect no more data to read
|
|
48
|
+
if (req.length != 1 + 32) {
|
|
49
|
+
throw new Error('Invalid request, unexpected trailing data');
|
|
50
|
+
}
|
|
51
|
+
if (req[0] != 0) {
|
|
52
|
+
throw new Error('Unsupported request, the first byte should be 0');
|
|
53
|
+
}
|
|
54
|
+
// read the hash
|
|
55
|
+
const hash = Buffer.alloc(32);
|
|
56
|
+
for (let i = 0; i < 32; i++) {
|
|
57
|
+
hash[i] = req[1 + i];
|
|
58
|
+
}
|
|
59
|
+
const req_hash_hex = hash.toString('hex');
|
|
60
|
+
const known_preimage = this.known_preimages.get(req_hash_hex);
|
|
61
|
+
if (known_preimage != undefined) {
|
|
62
|
+
const preimage_len_varint = createVarint(known_preimage.length);
|
|
63
|
+
// We can send at most 255 - len(preimage_len_out) - 1 bytes in a single message;
|
|
64
|
+
// the rest will be stored in the queue for GET_MORE_ELEMENTS
|
|
65
|
+
const max_payload_size = 255 - preimage_len_varint.length - 1;
|
|
66
|
+
const payload_size = Math.min(max_payload_size, known_preimage.length);
|
|
67
|
+
if (payload_size < known_preimage.length) {
|
|
68
|
+
for (let i = payload_size; i < known_preimage.length; i++) {
|
|
69
|
+
this.queue.push(Buffer.from([known_preimage[i]]));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return Buffer.concat([
|
|
73
|
+
preimage_len_varint,
|
|
74
|
+
Buffer.from([payload_size]),
|
|
75
|
+
Buffer.from(known_preimage.subarray(0, payload_size)),
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
throw Error(`Requested unknown preimage for: ${req_hash_hex}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export class GetMerkleLeafProofCommand extends ClientCommand {
|
|
82
|
+
constructor(known_trees, queue) {
|
|
83
|
+
super();
|
|
84
|
+
this.code = ClientCommandCode.GET_MERKLE_LEAF_PROOF;
|
|
85
|
+
this.known_trees = known_trees;
|
|
86
|
+
this.queue = queue;
|
|
87
|
+
}
|
|
88
|
+
execute(request) {
|
|
89
|
+
const req = Buffer.from(request.subarray(1));
|
|
90
|
+
if (req.length < 32 + 1 + 1) {
|
|
91
|
+
throw new Error('Invalid request, expected at least 34 bytes');
|
|
92
|
+
}
|
|
93
|
+
const reqBuf = new BufferReader(req);
|
|
94
|
+
const hash = reqBuf.readSlice(32);
|
|
95
|
+
const hash_hex = hash.toString('hex');
|
|
96
|
+
let tree_size;
|
|
97
|
+
let leaf_index;
|
|
98
|
+
try {
|
|
99
|
+
tree_size = sanitizeBigintToNumber(reqBuf.readVarInt());
|
|
100
|
+
leaf_index = sanitizeBigintToNumber(reqBuf.readVarInt());
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
throw new Error("Invalid request, couldn't parse tree_size or leaf_index");
|
|
104
|
+
}
|
|
105
|
+
const mt = this.known_trees.get(hash_hex);
|
|
106
|
+
if (!mt) {
|
|
107
|
+
throw Error(`Requested Merkle leaf proof for unknown tree: ${hash_hex}`);
|
|
108
|
+
}
|
|
109
|
+
if (leaf_index >= tree_size || mt.size() != tree_size) {
|
|
110
|
+
throw Error('Invalid index or tree size.');
|
|
111
|
+
}
|
|
112
|
+
if (this.queue.length != 0) {
|
|
113
|
+
throw Error('This command should not execute when the queue is not empty.');
|
|
114
|
+
}
|
|
115
|
+
const proof = mt.getProof(leaf_index);
|
|
116
|
+
const n_response_elements = Math.min(Math.floor((255 - 32 - 1 - 1) / 32), proof.length);
|
|
117
|
+
const n_leftover_elements = proof.length - n_response_elements;
|
|
118
|
+
// Add to the queue any proof elements that do not fit the response
|
|
119
|
+
if (n_leftover_elements > 0) {
|
|
120
|
+
this.queue.push(...proof.slice(-n_leftover_elements));
|
|
121
|
+
}
|
|
122
|
+
return Buffer.concat([
|
|
123
|
+
mt.getLeafHash(leaf_index),
|
|
124
|
+
Buffer.from([proof.length]),
|
|
125
|
+
Buffer.from([n_response_elements]),
|
|
126
|
+
...proof.slice(0, n_response_elements),
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export class GetMerkleLeafIndexCommand extends ClientCommand {
|
|
131
|
+
constructor(known_trees) {
|
|
132
|
+
super();
|
|
133
|
+
this.code = ClientCommandCode.GET_MERKLE_LEAF_INDEX;
|
|
134
|
+
this.known_trees = known_trees;
|
|
135
|
+
}
|
|
136
|
+
execute(request) {
|
|
137
|
+
const req = Buffer.from(request.subarray(1));
|
|
138
|
+
if (req.length != 32 + 32) {
|
|
139
|
+
throw new Error('Invalid request, unexpected trailing data');
|
|
140
|
+
}
|
|
141
|
+
// read the root hash
|
|
142
|
+
const root_hash = Buffer.alloc(32);
|
|
143
|
+
for (let i = 0; i < 32; i++) {
|
|
144
|
+
root_hash[i] = req.readUInt8(i);
|
|
145
|
+
}
|
|
146
|
+
const root_hash_hex = root_hash.toString('hex');
|
|
147
|
+
// read the leaf hash
|
|
148
|
+
const leef_hash = Buffer.alloc(32);
|
|
149
|
+
for (let i = 0; i < 32; i++) {
|
|
150
|
+
leef_hash[i] = req.readUInt8(32 + i);
|
|
151
|
+
}
|
|
152
|
+
const leef_hash_hex = leef_hash.toString('hex');
|
|
153
|
+
const mt = this.known_trees.get(root_hash_hex);
|
|
154
|
+
if (!mt) {
|
|
155
|
+
throw Error(`Requested Merkle leaf index for unknown root: ${root_hash_hex}`);
|
|
156
|
+
}
|
|
157
|
+
let leaf_index = 0;
|
|
158
|
+
let found = 0;
|
|
159
|
+
for (let i = 0; i < mt.size(); i++) {
|
|
160
|
+
if (mt.getLeafHash(i).toString('hex') == leef_hash_hex) {
|
|
161
|
+
found = 1;
|
|
162
|
+
leaf_index = i;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return Buffer.concat([Buffer.from([found]), createVarint(leaf_index)]);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export class GetMoreElementsCommand extends ClientCommand {
|
|
170
|
+
constructor(queue) {
|
|
171
|
+
super();
|
|
172
|
+
this.code = ClientCommandCode.GET_MORE_ELEMENTS;
|
|
173
|
+
this.queue = queue;
|
|
174
|
+
}
|
|
175
|
+
execute(request) {
|
|
176
|
+
if (request.length != 1) {
|
|
177
|
+
throw new Error('Invalid request, unexpected trailing data');
|
|
178
|
+
}
|
|
179
|
+
if (this.queue.length === 0) {
|
|
180
|
+
throw new Error('No elements to get');
|
|
181
|
+
}
|
|
182
|
+
// all elements should have the same length
|
|
183
|
+
const element_len = this.queue[0].length;
|
|
184
|
+
if (this.queue.some((el) => el.length != element_len)) {
|
|
185
|
+
throw new Error('The queue contains elements with different byte length, which is not expected');
|
|
186
|
+
}
|
|
187
|
+
const max_elements = Math.floor(253 / element_len);
|
|
188
|
+
const n_returned_elements = Math.min(max_elements, this.queue.length);
|
|
189
|
+
const returned_elements = this.queue.splice(0, n_returned_elements);
|
|
190
|
+
return Buffer.concat([
|
|
191
|
+
Buffer.from([n_returned_elements]),
|
|
192
|
+
Buffer.from([element_len]),
|
|
193
|
+
...returned_elements,
|
|
194
|
+
]);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* This class will dispatch a client command coming from the hardware device to
|
|
199
|
+
* the appropriate client command implementation. Those client commands
|
|
200
|
+
* typically requests data from a merkle tree or merkelized maps.
|
|
201
|
+
*
|
|
202
|
+
* A ClientCommandInterpreter is prepared by adding the merkle trees and
|
|
203
|
+
* merkelized maps it should be able to serve to the hardware device. This class
|
|
204
|
+
* doesn't know anything about the semantics of the data it holds, it just
|
|
205
|
+
* serves merkle data. It doesn't even know in what context it is being
|
|
206
|
+
* executed, ie SignPsbt, getWalletAddress, etc.
|
|
207
|
+
*
|
|
208
|
+
* If the command yelds results to the client, as signPsbt does, the yielded
|
|
209
|
+
* data will be accessible after the command completed by calling getYielded(),
|
|
210
|
+
* which will return the yields in the same order as they came in.
|
|
211
|
+
*/
|
|
212
|
+
export class ClientCommandInterpreter {
|
|
213
|
+
constructor(progressCallback) {
|
|
214
|
+
this.roots = new Map();
|
|
215
|
+
this.preimages = new Map();
|
|
216
|
+
this.yielded = [];
|
|
217
|
+
this.queue = [];
|
|
218
|
+
this.commands = new Map();
|
|
219
|
+
const commands = [
|
|
220
|
+
new YieldCommand(this.yielded, progressCallback),
|
|
221
|
+
new GetPreimageCommand(this.preimages, this.queue),
|
|
222
|
+
new GetMerkleLeafIndexCommand(this.roots),
|
|
223
|
+
new GetMerkleLeafProofCommand(this.roots, this.queue),
|
|
224
|
+
new GetMoreElementsCommand(this.queue),
|
|
225
|
+
];
|
|
226
|
+
for (const cmd of commands) {
|
|
227
|
+
if (this.commands.has(cmd.code)) {
|
|
228
|
+
throw new Error(`Multiple commands with code ${cmd.code}`);
|
|
229
|
+
}
|
|
230
|
+
this.commands.set(cmd.code, cmd);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
getYielded() {
|
|
234
|
+
return this.yielded;
|
|
235
|
+
}
|
|
236
|
+
addKnownPreimage(preimage) {
|
|
237
|
+
this.preimages.set(sha256(preimage).toString('hex'), preimage);
|
|
238
|
+
}
|
|
239
|
+
addKnownList(elements) {
|
|
240
|
+
for (const el of elements) {
|
|
241
|
+
const preimage = Buffer.concat([Buffer.from([0]), el]);
|
|
242
|
+
this.addKnownPreimage(preimage);
|
|
243
|
+
}
|
|
244
|
+
const mt = new Merkle(elements.map((el) => hashLeaf(el)));
|
|
245
|
+
this.roots.set(mt.getRoot().toString('hex'), mt);
|
|
246
|
+
}
|
|
247
|
+
addKnownMapping(mm) {
|
|
248
|
+
this.addKnownList(mm.keys);
|
|
249
|
+
this.addKnownList(mm.values);
|
|
250
|
+
}
|
|
251
|
+
addKnownWalletPolicy(wp) {
|
|
252
|
+
this.addKnownPreimage(wp.serialize());
|
|
253
|
+
this.addKnownList(wp.keys.map((k) => Buffer.from(k, 'ascii')));
|
|
254
|
+
// Use ASCII to match policy serialization hashing and device expectations
|
|
255
|
+
this.addKnownPreimage(Buffer.from(wp.descriptorTemplate, 'ascii'));
|
|
256
|
+
}
|
|
257
|
+
execute(request) {
|
|
258
|
+
if (request.length == 0) {
|
|
259
|
+
throw new Error('Unexpected empty command');
|
|
260
|
+
}
|
|
261
|
+
const cmdCode = request[0];
|
|
262
|
+
const cmd = this.commands.get(cmdCode);
|
|
263
|
+
if (!cmd) {
|
|
264
|
+
throw new Error(`Unexpected command code ${cmdCode}`);
|
|
265
|
+
}
|
|
266
|
+
return cmd.execute(request);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=clientCommands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientCommands.js","sourceRoot":"","sources":["../../../../../src/ledger/bitcoin_client/lib/clientCommands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { MerkleMap } from './merkleMap';
|
|
2
|
+
import { PsbtV2 } from './psbtv2';
|
|
3
|
+
/**
|
|
4
|
+
* This class merkelizes a PSBTv2, by merkelizing the different
|
|
5
|
+
* maps of the psbt. This is used during the transaction signing process,
|
|
6
|
+
* where the hardware app can request specific parts of the psbt from the
|
|
7
|
+
* client code and be sure that the response data actually belong to the psbt.
|
|
8
|
+
* The reason for this is the limited amount of memory available to the app,
|
|
9
|
+
* so it can't always store the full psbt in memory.
|
|
10
|
+
*
|
|
11
|
+
* The signing process is documented at
|
|
12
|
+
* https://github.com/LedgerHQ/app-bitcoin-new/blob/master/doc/bitcoin.md#sign_psbt
|
|
13
|
+
*/
|
|
14
|
+
export class MerkelizedPsbt extends PsbtV2 {
|
|
15
|
+
constructor(psbt) {
|
|
16
|
+
super();
|
|
17
|
+
this.inputMerkleMaps = [];
|
|
18
|
+
this.outputMerkleMaps = [];
|
|
19
|
+
psbt.copy(this);
|
|
20
|
+
this.globalMerkleMap = MerkelizedPsbt.createMerkleMap(this.globalMap);
|
|
21
|
+
for (let i = 0; i < this.getGlobalInputCount(); i++) {
|
|
22
|
+
this.inputMerkleMaps.push(MerkelizedPsbt.createMerkleMap(this.inputMaps[i]));
|
|
23
|
+
}
|
|
24
|
+
this.inputMapCommitments = [...this.inputMerkleMaps.values()].map((v) => v.commitment());
|
|
25
|
+
for (let i = 0; i < this.getGlobalOutputCount(); i++) {
|
|
26
|
+
this.outputMerkleMaps.push(MerkelizedPsbt.createMerkleMap(this.outputMaps[i]));
|
|
27
|
+
}
|
|
28
|
+
this.outputMapCommitments = [...this.outputMerkleMaps.values()].map((v) => v.commitment());
|
|
29
|
+
}
|
|
30
|
+
// These public functions are for MerkelizedPsbt.
|
|
31
|
+
getGlobalSize() {
|
|
32
|
+
return this.globalMap.size;
|
|
33
|
+
}
|
|
34
|
+
getGlobalKeysValuesRoot() {
|
|
35
|
+
return this.globalMerkleMap.commitment();
|
|
36
|
+
}
|
|
37
|
+
static createMerkleMap(map) {
|
|
38
|
+
const sortedKeysStrings = [...map.keys()].sort();
|
|
39
|
+
const values = sortedKeysStrings.map((k) => {
|
|
40
|
+
const v = map.get(k);
|
|
41
|
+
if (!v) {
|
|
42
|
+
throw new Error('No value for key ' + k);
|
|
43
|
+
}
|
|
44
|
+
return v;
|
|
45
|
+
});
|
|
46
|
+
const sortedKeys = sortedKeysStrings.map((k) => Buffer.from(k, 'hex'));
|
|
47
|
+
return new MerkleMap(sortedKeys, values);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=merkelizedPsbt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merkelizedPsbt.js","sourceRoot":"","sources":["../../../../../src/ledger/bitcoin_client/lib/merkelizedPsbt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC;;;;;;;;;;GAUG;AACH,MAAM,OAAO,cAAe,SAAQ,MAAM;IAMxC,YAAY,IAAY;QACtB,KAAK,EAAE,CAAC;QALH,oBAAe,GAAgB,EAAE,CAAC;QAClC,qBAAgB,GAAgB,EAAE,CAAC;QAKxC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YACpD,IAAI,CAAC,eAAe,CAAC,IAAI,CACvB,cAAc,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAClD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,mBAAmB,GAAG,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACtE,CAAC,CAAC,UAAU,EAAE,CACf,CAAC;QAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YACrD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CACxB,cAAc,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CACnD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,oBAAoB,GAAG,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACxE,CAAC,CAAC,UAAU,EAAE,CACf,CAAC;IACJ,CAAC;IACD,iDAAiD;IACjD,aAAa;QACX,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;IACD,uBAAuB;QACrB,OAAO,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC;IAC3C,CAAC;IAEO,MAAM,CAAC,eAAe,CAAC,GAAgC;QAC7D,MAAM,iBAAiB,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACzC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC,CAAC,EAAE,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAEvE,OAAO,IAAI,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import CryptoJS from 'crypto-js';
|
|
2
|
+
// Helper function for SHA256 hashing (browser-compatible)
|
|
3
|
+
function sha256(data) {
|
|
4
|
+
const wordArray = CryptoJS.lib.WordArray.create(data);
|
|
5
|
+
const hash = CryptoJS.SHA256(wordArray);
|
|
6
|
+
const hashBuffer = Buffer.from(hash.toString(CryptoJS.enc.Hex), 'hex');
|
|
7
|
+
return hashBuffer;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* This class implements the merkle tree used by Ledger Bitcoin app v2+,
|
|
11
|
+
* which is documented at
|
|
12
|
+
* https://github.com/LedgerHQ/app-bitcoin-new/blob/master/doc/merkle.md
|
|
13
|
+
*/
|
|
14
|
+
export class Merkle {
|
|
15
|
+
constructor(leaves, hasher = sha256) {
|
|
16
|
+
this.leaves = leaves;
|
|
17
|
+
this.h = hasher;
|
|
18
|
+
const nodes = this.calculateRoot(leaves);
|
|
19
|
+
this.rootNode = nodes.root;
|
|
20
|
+
this.leafNodes = nodes.leaves;
|
|
21
|
+
}
|
|
22
|
+
getRoot() {
|
|
23
|
+
return this.rootNode.hash;
|
|
24
|
+
}
|
|
25
|
+
size() {
|
|
26
|
+
return this.leaves.length;
|
|
27
|
+
}
|
|
28
|
+
getLeaves() {
|
|
29
|
+
return this.leaves;
|
|
30
|
+
}
|
|
31
|
+
getLeafHash(index) {
|
|
32
|
+
return this.leafNodes[index].hash;
|
|
33
|
+
}
|
|
34
|
+
getProof(index) {
|
|
35
|
+
if (index >= this.leaves.length)
|
|
36
|
+
throw Error('Index out of bounds');
|
|
37
|
+
return proveNode(this.leafNodes[index]);
|
|
38
|
+
}
|
|
39
|
+
calculateRoot(leaves) {
|
|
40
|
+
const n = leaves.length;
|
|
41
|
+
if (n == 0) {
|
|
42
|
+
return {
|
|
43
|
+
root: new Node(undefined, undefined, Buffer.alloc(32, 0)),
|
|
44
|
+
leaves: [],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (n == 1) {
|
|
48
|
+
const newNode = new Node(undefined, undefined, leaves[0]);
|
|
49
|
+
return { root: newNode, leaves: [newNode] };
|
|
50
|
+
}
|
|
51
|
+
const leftCount = highestPowerOf2LessThan(n);
|
|
52
|
+
const leftBranch = this.calculateRoot(leaves.slice(0, leftCount));
|
|
53
|
+
const rightBranch = this.calculateRoot(leaves.slice(leftCount));
|
|
54
|
+
const leftChild = leftBranch.root;
|
|
55
|
+
const rightChild = rightBranch.root;
|
|
56
|
+
const hash = this.hashNode(leftChild.hash, rightChild.hash);
|
|
57
|
+
const node = new Node(leftChild, rightChild, hash);
|
|
58
|
+
leftChild.parent = node;
|
|
59
|
+
rightChild.parent = node;
|
|
60
|
+
return { root: node, leaves: leftBranch.leaves.concat(rightBranch.leaves) };
|
|
61
|
+
}
|
|
62
|
+
hashNode(left, right) {
|
|
63
|
+
return this.h(Buffer.concat([Buffer.from([1]), left, right]));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function hashLeaf(buf, hashFunction = sha256) {
|
|
67
|
+
return hashConcat(Buffer.from([0]), buf, hashFunction);
|
|
68
|
+
}
|
|
69
|
+
function hashConcat(bufA, bufB, hashFunction) {
|
|
70
|
+
return hashFunction(Buffer.concat([bufA, bufB]));
|
|
71
|
+
}
|
|
72
|
+
class Node {
|
|
73
|
+
constructor(left, right, hash) {
|
|
74
|
+
this.leftChild = left;
|
|
75
|
+
this.rightChild = right;
|
|
76
|
+
this.hash = hash;
|
|
77
|
+
}
|
|
78
|
+
isLeaf() {
|
|
79
|
+
return this.leftChild == undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function proveNode(node) {
|
|
83
|
+
if (!node.parent) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
if (node.parent.leftChild == node) {
|
|
87
|
+
if (!node.parent.rightChild) {
|
|
88
|
+
throw new Error('Expected right child to exist');
|
|
89
|
+
}
|
|
90
|
+
return [node.parent.rightChild.hash, ...proveNode(node.parent)];
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
if (!node.parent.leftChild) {
|
|
94
|
+
throw new Error('Expected left child to exist');
|
|
95
|
+
}
|
|
96
|
+
return [node.parent.leftChild.hash, ...proveNode(node.parent)];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function highestPowerOf2LessThan(n) {
|
|
100
|
+
if (n < 2) {
|
|
101
|
+
throw Error('Expected n >= 2');
|
|
102
|
+
}
|
|
103
|
+
if (isPowerOf2(n)) {
|
|
104
|
+
return n / 2;
|
|
105
|
+
}
|
|
106
|
+
return 1 << Math.floor(Math.log2(n));
|
|
107
|
+
}
|
|
108
|
+
function isPowerOf2(n) {
|
|
109
|
+
return (n & (n - 1)) == 0;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=merkle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merkle.js","sourceRoot":"","sources":["../../../../../src/ledger/bitcoin_client/lib/merkle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { hashLeaf, Merkle } from './merkle';
|
|
2
|
+
import { createVarint } from './varint';
|
|
3
|
+
/**
|
|
4
|
+
* This implements "Merkelized Maps", documented at
|
|
5
|
+
* https://github.com/LedgerHQ/app-bitcoin-new/blob/master/doc/merkle.md#merkleized-maps
|
|
6
|
+
*
|
|
7
|
+
* A merkelized map consist of two merkle trees, one for the keys of
|
|
8
|
+
* a map and one for the values of the same map, thus the two merkle
|
|
9
|
+
* trees have the same shape. The commitment is the number elements
|
|
10
|
+
* in the map followed by the keys' merkle root followed by the
|
|
11
|
+
* values' merkle root.
|
|
12
|
+
*/
|
|
13
|
+
export class MerkleMap {
|
|
14
|
+
/**
|
|
15
|
+
* @param keys Sorted list of (unhashed) keys
|
|
16
|
+
* @param values values, in corresponding order as the keys, and of equal length
|
|
17
|
+
*/
|
|
18
|
+
constructor(keys, values) {
|
|
19
|
+
if (keys.length != values.length) {
|
|
20
|
+
throw new Error('keys and values should have the same length');
|
|
21
|
+
}
|
|
22
|
+
// Sanity check: verify that keys are actually sorted and with no duplicates
|
|
23
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
24
|
+
if (keys[i].toString('hex') >= keys[i + 1].toString('hex')) {
|
|
25
|
+
throw new Error('keys must be in strictly increasing order');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
this.keys = keys;
|
|
29
|
+
this.keysTree = new Merkle(keys.map((k) => hashLeaf(k)));
|
|
30
|
+
this.values = values;
|
|
31
|
+
this.valuesTree = new Merkle(values.map((v) => hashLeaf(v)));
|
|
32
|
+
}
|
|
33
|
+
commitment() {
|
|
34
|
+
// returns a buffer between 65 and 73 (included) bytes long
|
|
35
|
+
return Buffer.concat([
|
|
36
|
+
createVarint(this.keys.length),
|
|
37
|
+
this.keysTree.getRoot(),
|
|
38
|
+
this.valuesTree.getRoot(),
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=merkleMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merkleMap.js","sourceRoot":"","sources":["../../../../../src/ledger/bitcoin_client/lib/merkleMap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC;;;;;;;;;GASG;AACH,MAAM,OAAO,SAAS;IAKpB;;;OAGG;IACH,YAAY,IAAuB,EAAE,MAAyB;QAC5D,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,4EAA4E;QAC5E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3D,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,UAAU;QACR,2DAA2D;QAC3D,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE;YACvB,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;SAC1B,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import CryptoJS from 'crypto-js';
|
|
2
|
+
// Helper function for SHA256 hashing (browser-compatible)
|
|
3
|
+
function sha256(data) {
|
|
4
|
+
const wordArray = CryptoJS.lib.WordArray.create(data);
|
|
5
|
+
const hash = CryptoJS.SHA256(wordArray);
|
|
6
|
+
const hashBuffer = Buffer.from(hash.toString(CryptoJS.enc.Hex), 'hex');
|
|
7
|
+
return hashBuffer;
|
|
8
|
+
}
|
|
9
|
+
import { BufferWriter } from './buffertools';
|
|
10
|
+
import { hashLeaf, Merkle } from './merkle';
|
|
11
|
+
const WALLET_POLICY_V2 = 2;
|
|
12
|
+
/**
|
|
13
|
+
* The Bitcon hardware app uses a descriptors-like thing to describe
|
|
14
|
+
* how to construct output scripts from keys. A "Wallet Policy" consists
|
|
15
|
+
* of a "Descriptor Template" and a list of "keys". A key is basically
|
|
16
|
+
* a serialized BIP32 extended public key with some added derivation path
|
|
17
|
+
* information. This is documented at
|
|
18
|
+
* https://github.com/LedgerHQ/app-bitcoin-new/blob/master/doc/wallet.md
|
|
19
|
+
*/
|
|
20
|
+
export class WalletPolicy {
|
|
21
|
+
/**
|
|
22
|
+
* Creates and instance of a wallet policy.
|
|
23
|
+
* @param name an ascii string, up to 16 bytes long; it must be an empty string for default wallet policies
|
|
24
|
+
* @param descriptorTemplate the wallet policy template
|
|
25
|
+
* @param keys and array of the keys, with the key derivation information
|
|
26
|
+
*/
|
|
27
|
+
constructor(name, descriptorTemplate, keys) {
|
|
28
|
+
this.name = name;
|
|
29
|
+
this.descriptorTemplate = descriptorTemplate;
|
|
30
|
+
this.keys = keys;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Returns the unique 32-bytes id of this wallet policy.
|
|
34
|
+
*/
|
|
35
|
+
getId() {
|
|
36
|
+
return sha256(this.serialize());
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Serializes the wallet policy for transmission via the hardware wallet protocol.
|
|
40
|
+
* @returns the serialized wallet policy
|
|
41
|
+
*/
|
|
42
|
+
serialize() {
|
|
43
|
+
const keyBuffers = this.keys.map((k) => Buffer.from(k, 'ascii'));
|
|
44
|
+
const m = new Merkle(keyBuffers.map((k) => hashLeaf(k)));
|
|
45
|
+
const buf = new BufferWriter();
|
|
46
|
+
buf.writeUInt8(WALLET_POLICY_V2); // wallet version
|
|
47
|
+
// length of wallet name, and wallet name
|
|
48
|
+
buf.writeVarSlice(Buffer.from(this.name, 'ascii'));
|
|
49
|
+
// length of descriptor template
|
|
50
|
+
buf.writeVarInt(this.descriptorTemplate.length);
|
|
51
|
+
// sha256 hash of descriptor template (ASCII to match device expectations)
|
|
52
|
+
buf.writeSlice(sha256(Buffer.from(this.descriptorTemplate, 'ascii')));
|
|
53
|
+
// number of keys
|
|
54
|
+
buf.writeVarInt(this.keys.length);
|
|
55
|
+
// root of Merkle tree of keys
|
|
56
|
+
buf.writeSlice(m.getRoot());
|
|
57
|
+
return buf.buffer();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Simplified class to handle default wallet policies that can be used without policy registration.
|
|
62
|
+
*/
|
|
63
|
+
export class DefaultWalletPolicy extends WalletPolicy {
|
|
64
|
+
constructor(descriptorTemplate, key) {
|
|
65
|
+
super('', descriptorTemplate, [key]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../../../src/ledger/bitcoin_client/lib/policy.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,WAAW,CAAC;AAEjC,0DAA0D;AAC1D,SAAS,MAAM,CAAC,IAAY;IAC1B,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IACvE,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IAIvB;;;;;OAKG;IACH,YACE,IAAY,EACZ,kBAA0B,EAC1B,IAAuB;QAEvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAClC,CAAC;IAED;;;OAGG;IACH,SAAS;QACP,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,iBAAiB;QAEnD,yCAAyC;QACzC,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAEnD,gCAAgC;QAChC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAChD,0EAA0E;QAC1E,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAEtE,iBAAiB;QACjB,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,8BAA8B;QAC9B,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5B,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC;IACtB,CAAC;CACF;AAQD;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,YAAY;IACnD,YAAY,kBAA6C,EAAE,GAAW;QACpE,KAAK,CAAC,EAAE,EAAE,kBAAkB,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;CACF"}
|