@bsv/templates 1.0.0 → 1.1.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/dist/cjs/mod.js +22 -7
- package/dist/cjs/mod.js.map +1 -1
- package/dist/cjs/package.json +2 -2
- package/dist/cjs/src/Metanet.js +14 -14
- package/dist/cjs/src/Metanet.js.map +1 -1
- package/dist/cjs/src/MultiPushDrop.js +278 -0
- package/dist/cjs/src/MultiPushDrop.js.map +1 -0
- package/dist/cjs/src/OpReturn.js +13 -13
- package/dist/cjs/src/OpReturn.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/mod.js +1 -0
- package/dist/esm/mod.js.map +1 -1
- package/dist/esm/src/Metanet.js +14 -14
- package/dist/esm/src/Metanet.js.map +1 -1
- package/dist/esm/src/MultiPushDrop.js +275 -0
- package/dist/esm/src/MultiPushDrop.js.map +1 -0
- package/dist/esm/src/OpReturn.js +13 -13
- package/dist/esm/src/OpReturn.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/mod.d.ts +1 -0
- package/dist/types/mod.d.ts.map +1 -1
- package/dist/types/src/Metanet.d.ts +13 -13
- package/dist/types/src/Metanet.d.ts.map +1 -1
- package/dist/types/src/MultiPushDrop.d.ts +66 -0
- package/dist/types/src/MultiPushDrop.d.ts.map +1 -0
- package/dist/types/src/OpReturn.d.ts +12 -12
- package/dist/types/src/OpReturn.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/mod.ts +1 -0
- package/package.json +4 -4
- package/src/Metanet.ts +37 -37
- package/src/MultiPushDrop.ts +317 -0
- package/src/OpReturn.ts +32 -32
- package/src/__tests/Metanet.test.ts +15 -15
- package/src/__tests/MultiPushDrop.test.ts +256 -0
- package/src/__tests/OpReturn.test.ts +7 -7
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { LockingScript, UnlockingScript, OP, Utils, Hash, TransactionSignature, Signature } from '@bsv/sdk';
|
|
2
|
+
// Helper to ensure a value is not null or undefined
|
|
3
|
+
function verifyTruthy(v, err) {
|
|
4
|
+
if (v === null || v === undefined)
|
|
5
|
+
throw new Error(err || 'Value must not be null or undefined');
|
|
6
|
+
return v;
|
|
7
|
+
}
|
|
8
|
+
// Helper to create minimally encoded script chunks (same as in PushDrop)
|
|
9
|
+
const createMinimallyEncodedScriptChunk = (data) => {
|
|
10
|
+
if (data.length === 0)
|
|
11
|
+
return { op: 0 }; // OP_0
|
|
12
|
+
if (data.length === 1 && data[0] === 0)
|
|
13
|
+
return { op: 0 }; // OP_0
|
|
14
|
+
if (data.length === 1 && data[0] > 0 && data[0] <= 16)
|
|
15
|
+
return { op: 0x50 + data[0] }; // OP_1 to OP_16
|
|
16
|
+
if (data.length === 1 && data[0] === 0x81)
|
|
17
|
+
return { op: 0x4f }; // OP_1NEGATE
|
|
18
|
+
if (data.length <= 75)
|
|
19
|
+
return { op: data.length, data };
|
|
20
|
+
if (data.length <= 255)
|
|
21
|
+
return { op: 0x4c, data }; // OP_PUSHDATA1
|
|
22
|
+
if (data.length <= 65535)
|
|
23
|
+
return { op: 0x4d, data }; // OP_PUSHDATA2
|
|
24
|
+
return { op: 0x4e, data }; // OP_PUSHDATA4
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* MultiPushDrop Script Template
|
|
28
|
+
*
|
|
29
|
+
* This template creates locking scripts that allow spending by any one of multiple
|
|
30
|
+
* specified public keys (1-of-N). It also pushes arbitrary data fields onto the stack,
|
|
31
|
+
* which are dropped after the signature check.
|
|
32
|
+
*
|
|
33
|
+
* When using this among adversarial or non-trusted groups, the MASSIVE caveat is that
|
|
34
|
+
* there is no constraint enforcing that any group members are kept in the loop. Any group
|
|
35
|
+
* member can trivially destroy the token. For more practical non-trusted arrangements,
|
|
36
|
+
* techniques like OP_PUSH_TX should be used instead.
|
|
37
|
+
*
|
|
38
|
+
* There's also a known bug in this implementation where it won't work with over around 120
|
|
39
|
+
* keys but involving more than a few people than just a few into a FULLY TRUST BASED exchange
|
|
40
|
+
* is never a good idea. Use a more robust, application-specific mechanism.
|
|
41
|
+
*/
|
|
42
|
+
export default class MultiPushDrop {
|
|
43
|
+
wallet;
|
|
44
|
+
originator;
|
|
45
|
+
/**
|
|
46
|
+
* Decodes a MultiPushDrop locking script back into its data fields and the list of locking public keys.
|
|
47
|
+
* @param script The MultiPushDrop locking script to decode.
|
|
48
|
+
* @returns {MultiPushDropDecoded} An object containing the locking public keys and data fields.
|
|
49
|
+
* @throws {Error} If the script structure is not a valid MultiPushDrop script.
|
|
50
|
+
*/
|
|
51
|
+
static decode(script) {
|
|
52
|
+
const chunks = script.chunks;
|
|
53
|
+
let cursor = 0;
|
|
54
|
+
// Decode keys until they stop being 33 bytes long
|
|
55
|
+
const lockingPublicKeys = [];
|
|
56
|
+
while (chunks[cursor].data?.length === 33) {
|
|
57
|
+
const keyChunk = verifyTruthy(chunks[cursor], `Missing public key chunk ${cursor}`);
|
|
58
|
+
const keyData = verifyTruthy(keyChunk.data, `Public key chunk ${cursor} has no data`);
|
|
59
|
+
lockingPublicKeys.push(Utils.toHex(keyData));
|
|
60
|
+
cursor++;
|
|
61
|
+
}
|
|
62
|
+
// Skip the nPublicKeys chunk and opcodes.
|
|
63
|
+
// This amounts to 8 items to skip.
|
|
64
|
+
cursor += 8;
|
|
65
|
+
// Decode Data Fields
|
|
66
|
+
const fields = [];
|
|
67
|
+
for (let i = cursor; i < chunks.length; i++) {
|
|
68
|
+
const nextOpcode = chunks[i + 1]?.op;
|
|
69
|
+
const chunkData = chunks[i].data ?? []; // Use OP code for OP_0-OP_16 etc. if data is null
|
|
70
|
+
let currentField = [];
|
|
71
|
+
if (chunkData.length > 0) {
|
|
72
|
+
currentField = chunkData;
|
|
73
|
+
}
|
|
74
|
+
else if (chunks[i].op >= OP.OP_1 && chunks[i].op <= OP.OP_16) {
|
|
75
|
+
currentField = [chunks[i].op - OP.OP_1 + 1];
|
|
76
|
+
}
|
|
77
|
+
else if (chunks[i].op === OP.OP_0) {
|
|
78
|
+
currentField = []; // Represent OP_0 as empty array
|
|
79
|
+
}
|
|
80
|
+
else if (chunks[i].op === OP.OP_1NEGATE) {
|
|
81
|
+
currentField = [0x81];
|
|
82
|
+
}
|
|
83
|
+
else if (chunks[i].op === OP.OP_DROP || chunks[i].op === OP.OP_2DROP) {
|
|
84
|
+
// Stop before the drops
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Assume it's a data push even if data is empty for some reason
|
|
89
|
+
currentField = chunkData;
|
|
90
|
+
}
|
|
91
|
+
fields.push(currentField);
|
|
92
|
+
// If the next opcode is a DROP, we've found the last field
|
|
93
|
+
if (nextOpcode === OP.OP_DROP || nextOpcode === OP.OP_2DROP) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
lockingPublicKeys,
|
|
99
|
+
fields
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Constructs a new instance of the MultiPushDrop class.
|
|
104
|
+
*
|
|
105
|
+
* @param {WalletInterface} wallet - The wallet interface used for deriving keys and signing.
|
|
106
|
+
* @param {string} [originator] - The originator domain for wallet requests.
|
|
107
|
+
*/
|
|
108
|
+
constructor(wallet, originator) {
|
|
109
|
+
this.wallet = wallet;
|
|
110
|
+
this.originator = originator;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Creates a MultiPushDrop locking script.
|
|
114
|
+
*
|
|
115
|
+
* @param {number[][]} fields - The arbitrary data fields to include in the script.
|
|
116
|
+
* @param {[SecurityLevel, string]} protocolID - The protocol ID used for key derivation.
|
|
117
|
+
* @param {string} keyID - The key ID used for key derivation.
|
|
118
|
+
* @param {WalletCounterparty[]} counterparties - An array of counterparties ('self' or PubKeyHex) whose derived keys can unlock the script. Must contain at least one.
|
|
119
|
+
* @returns {Promise<LockingScript>} The generated MultiPushDrop locking script.
|
|
120
|
+
* @throws {Error} If counterparties array is empty.
|
|
121
|
+
*/
|
|
122
|
+
async lock(fields, protocolID, keyID, counterparties) {
|
|
123
|
+
if (!Array.isArray(counterparties) || counterparties.length === 0) {
|
|
124
|
+
throw new Error('MultiPushDrop requires at least one counterparty.');
|
|
125
|
+
}
|
|
126
|
+
const publicKeys = [];
|
|
127
|
+
for (const counterparty of counterparties) {
|
|
128
|
+
const { publicKey } = await this.wallet.getPublicKey({
|
|
129
|
+
protocolID,
|
|
130
|
+
keyID,
|
|
131
|
+
counterparty
|
|
132
|
+
}, this.originator);
|
|
133
|
+
publicKeys.push(publicKey);
|
|
134
|
+
}
|
|
135
|
+
const nPublicKeys = publicKeys.length;
|
|
136
|
+
const lockPart = [];
|
|
137
|
+
// Push Public Keys
|
|
138
|
+
for (const publicKeyHex of publicKeys) {
|
|
139
|
+
lockPart.push({
|
|
140
|
+
op: publicKeyHex.length / 2, // Length of compressed pubkey is 33 bytes (66 hex)
|
|
141
|
+
data: Utils.toArray(publicKeyHex, 'hex')
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Pick the value on the stack that's right before the locking script.
|
|
145
|
+
// This should be the index of the key to use in the unlock.
|
|
146
|
+
lockPart.push(createMinimallyEncodedScriptChunk([nPublicKeys]));
|
|
147
|
+
lockPart.push({ op: OP.OP_PICK });
|
|
148
|
+
// Now we use the index to get the actual key.
|
|
149
|
+
lockPart.push({ op: OP.OP_PICK });
|
|
150
|
+
// We pull the signature from the bottom of the stack, no matter the number of keys.
|
|
151
|
+
lockPart.push({ op: OP.OP_DEPTH });
|
|
152
|
+
lockPart.push({ op: OP.OP_1SUB });
|
|
153
|
+
lockPart.push({ op: OP.OP_PICK });
|
|
154
|
+
// We swap the signature and public key so they're in the correct order, then CHECKSIGVERIFY
|
|
155
|
+
lockPart.push({ op: OP.OP_SWAP });
|
|
156
|
+
lockPart.push({ op: OP.OP_CHECKSIGVERIFY });
|
|
157
|
+
// Construct PushDrop Part for fields
|
|
158
|
+
const pushDropPart = [];
|
|
159
|
+
for (const field of fields) {
|
|
160
|
+
pushDropPart.push(createMinimallyEncodedScriptChunk(field));
|
|
161
|
+
}
|
|
162
|
+
// Add Drop Opcodes
|
|
163
|
+
// We need to drop N keys, the number N itself, and M fields after verification succeeds.
|
|
164
|
+
// We also copied the signature itself so we need to drop that.
|
|
165
|
+
// Then we push a single true.
|
|
166
|
+
let itemsToDrop = fields.length + nPublicKeys + 2;
|
|
167
|
+
while (itemsToDrop > 1) {
|
|
168
|
+
pushDropPart.push({ op: OP.OP_2DROP });
|
|
169
|
+
itemsToDrop -= 2;
|
|
170
|
+
}
|
|
171
|
+
if (itemsToDrop === 1) {
|
|
172
|
+
pushDropPart.push({ op: OP.OP_DROP });
|
|
173
|
+
}
|
|
174
|
+
// Combine parts and return
|
|
175
|
+
return new LockingScript([
|
|
176
|
+
...lockPart,
|
|
177
|
+
...pushDropPart,
|
|
178
|
+
{ op: OP.OP_TRUE }
|
|
179
|
+
]);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Creates an unlocking script template for spending a MultiPushDrop output.
|
|
183
|
+
*
|
|
184
|
+
* @param {[SecurityLevel, string]} protocolID - The protocol ID used for key derivation.
|
|
185
|
+
* @param {string} keyID - The key ID used for key derivation.
|
|
186
|
+
* @param {WalletCounterparty} creator - The identity key of the person who made the locking script. Could come from one of the fields or be passed off chain.
|
|
187
|
+
* @param {'all' | 'none' | 'single'} [signOutputs='all'] - Specifies which transaction outputs to sign.
|
|
188
|
+
* @param {boolean} [anyoneCanPay=false] - Specifies if the SIGHASH_ANYONECANPAY flag should be used.
|
|
189
|
+
* @returns {ScriptTemplateUnlock} An object containing `sign` and `estimateLength` functions.
|
|
190
|
+
* @throws {Error} If we are not found in the list of keys, or if required signing info (sourceTXID, satoshis, lockingScript) is missing.
|
|
191
|
+
*/
|
|
192
|
+
unlock(protocolID, keyID, creator, signOutputs = 'all', anyoneCanPay = false) {
|
|
193
|
+
return {
|
|
194
|
+
sign: async (tx, inputIndex) => {
|
|
195
|
+
// Prepare for signing
|
|
196
|
+
let signatureScope = TransactionSignature.SIGHASH_FORKID;
|
|
197
|
+
if (signOutputs === 'all')
|
|
198
|
+
signatureScope |= TransactionSignature.SIGHASH_ALL;
|
|
199
|
+
else if (signOutputs === 'none')
|
|
200
|
+
signatureScope |= TransactionSignature.SIGHASH_NONE;
|
|
201
|
+
else if (signOutputs === 'single')
|
|
202
|
+
signatureScope |= TransactionSignature.SIGHASH_SINGLE;
|
|
203
|
+
if (anyoneCanPay)
|
|
204
|
+
signatureScope |= TransactionSignature.SIGHASH_ANYONECANPAY;
|
|
205
|
+
const input = tx.inputs[inputIndex];
|
|
206
|
+
const currentSourceTXID = input.sourceTXID ?? input.sourceTransaction?.id('hex');
|
|
207
|
+
const currentSourceSatoshis = input.sourceTransaction?.outputs[input.sourceOutputIndex].satoshis;
|
|
208
|
+
const currentLockingScript = input.sourceTransaction?.outputs[input.sourceOutputIndex]?.lockingScript;
|
|
209
|
+
if (typeof currentSourceTXID !== 'string')
|
|
210
|
+
throw new Error('Input sourceTXID or sourceTransaction required for signing.');
|
|
211
|
+
if (currentSourceSatoshis === undefined)
|
|
212
|
+
throw new Error('Input sourceSatoshis or sourceTransaction required for signing.');
|
|
213
|
+
if (currentLockingScript == null)
|
|
214
|
+
throw new Error('Input lockingScript or sourceTransaction required for signing.');
|
|
215
|
+
const otherInputs = tx.inputs.filter((_, index) => index !== inputIndex);
|
|
216
|
+
const decoded = MultiPushDrop.decode(currentLockingScript);
|
|
217
|
+
// Find the index of the unlocker's public key
|
|
218
|
+
let unlockerIndex = -1;
|
|
219
|
+
const { publicKey: unlockerPubKeyHex } = await this.wallet.getPublicKey({
|
|
220
|
+
protocolID,
|
|
221
|
+
keyID,
|
|
222
|
+
counterparty: creator,
|
|
223
|
+
forSelf: true
|
|
224
|
+
}, this.originator);
|
|
225
|
+
for (let i = 0; i < decoded.lockingPublicKeys.length; i++) {
|
|
226
|
+
if (decoded.lockingPublicKeys[i] === unlockerPubKeyHex) {
|
|
227
|
+
unlockerIndex = i;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (unlockerIndex === -1) {
|
|
232
|
+
throw new Error(`Unlocker key derived for counterparty (creator) "${creator}" not found in the list of locking keys.`);
|
|
233
|
+
}
|
|
234
|
+
unlockerIndex = decoded.lockingPublicKeys.length - 1 - unlockerIndex;
|
|
235
|
+
// Calculate Preimage
|
|
236
|
+
const preimage = TransactionSignature.format({
|
|
237
|
+
sourceTXID: currentSourceTXID,
|
|
238
|
+
sourceOutputIndex: verifyTruthy(input.sourceOutputIndex),
|
|
239
|
+
sourceSatoshis: currentSourceSatoshis,
|
|
240
|
+
transactionVersion: tx.version,
|
|
241
|
+
otherInputs,
|
|
242
|
+
inputIndex,
|
|
243
|
+
outputs: tx.outputs,
|
|
244
|
+
inputSequence: input.sequence ?? 0xffffffff,
|
|
245
|
+
subscript: currentLockingScript,
|
|
246
|
+
lockTime: tx.lockTime,
|
|
247
|
+
scope: signatureScope
|
|
248
|
+
});
|
|
249
|
+
// Create Signature
|
|
250
|
+
const preimageHash = Hash.hash256(preimage);
|
|
251
|
+
const { signature: bareSignature } = await this.wallet.createSignature({
|
|
252
|
+
hashToDirectlySign: preimageHash,
|
|
253
|
+
protocolID,
|
|
254
|
+
keyID,
|
|
255
|
+
counterparty: creator
|
|
256
|
+
}, this.originator);
|
|
257
|
+
const signature = Signature.fromDER([...bareSignature]);
|
|
258
|
+
const txSignature = new TransactionSignature(signature.r, signature.s, signatureScope);
|
|
259
|
+
const sigForScript = txSignature.toChecksigFormat();
|
|
260
|
+
// Create Unlocking Script Chunks: <Signature> <Index>
|
|
261
|
+
const unlockingChunks = [];
|
|
262
|
+
unlockingChunks.push({ op: sigForScript.length, data: sigForScript });
|
|
263
|
+
unlockingChunks.push(createMinimallyEncodedScriptChunk([unlockerIndex]));
|
|
264
|
+
return new UnlockingScript(unlockingChunks);
|
|
265
|
+
},
|
|
266
|
+
// Estimate length: Signature (~71-73 bytes) + Index push (1 byte for 0-15, potentially more)
|
|
267
|
+
estimateLength: async () => {
|
|
268
|
+
// A conservative estimate, usually 73 + 1 = 74
|
|
269
|
+
// Could potentially be larger if index > 15, but that's rare.
|
|
270
|
+
return 74;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=MultiPushDrop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultiPushDrop.js","sourceRoot":"","sources":["../../../src/MultiPushDrop.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/src/OpReturn.js
CHANGED
|
@@ -6,12 +6,12 @@ import { OP, LockingScript, Utils } from '@bsv/sdk';
|
|
|
6
6
|
*/
|
|
7
7
|
export default class OpReturn {
|
|
8
8
|
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
* Creates an OpReturn script
|
|
10
|
+
*
|
|
11
|
+
* @param {string | string[] | number[]} data The data or array of data to push after OP_RETURN.
|
|
12
|
+
* @param {('hex' | 'utf8' | 'base64')} enc The data encoding type, defaults to utf8.
|
|
13
|
+
* @returns {LockingScript} - An OpReturn locking script.
|
|
14
|
+
*/
|
|
15
15
|
lock(data, enc) {
|
|
16
16
|
const script = [
|
|
17
17
|
{ op: OP.OP_FALSE },
|
|
@@ -20,7 +20,7 @@ export default class OpReturn {
|
|
|
20
20
|
if (typeof data === 'string') {
|
|
21
21
|
data = [data];
|
|
22
22
|
}
|
|
23
|
-
if (data.length && typeof data[0] === 'number') {
|
|
23
|
+
if ((data.length > 0) && typeof data[0] === 'number') {
|
|
24
24
|
script.push({ op: data.length, data: data });
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
@@ -32,16 +32,16 @@ export default class OpReturn {
|
|
|
32
32
|
return new LockingScript(script);
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
* Unlock method is not available for OpReturn scripts, throws exception.
|
|
36
|
+
*/
|
|
37
37
|
unlock() {
|
|
38
38
|
throw new Error('Unlock is not supported for OpReturn scripts');
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
* Decodes an OpReturn script data to utf8
|
|
42
|
+
* @param script The opreturn script
|
|
43
|
+
* @returns An array of UTF8 encoded strings
|
|
44
|
+
*/
|
|
45
45
|
static decode(script) {
|
|
46
46
|
const tokens = script.toASM().split(' ').slice(2);
|
|
47
47
|
return tokens.map(token => Utils.toUTF8(Utils.toArray(token, 'hex')));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpReturn.js","sourceRoot":"","sources":["../../../src/OpReturn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAA0B,aAAa,EAAgC,KAAK,EAAE,MAAM,UAAU,CAAA;AAEzG;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;
|
|
1
|
+
{"version":3,"file":"OpReturn.js","sourceRoot":"","sources":["../../../src/OpReturn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAA0B,aAAa,EAAgC,KAAK,EAAE,MAAM,UAAU,CAAA;AAEzG;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B;;;;;;SAMK;IACL,IAAI,CAAE,IAAkC,EAAE,GAA+B;QACvE,MAAM,MAAM,GAA2C;YACrD,EAAE,EAAE,EAAE,EAAE,CAAC,QAAQ,EAAE;YACnB,EAAE,EAAE,EAAE,EAAE,CAAC,SAAS,EAAE;SACrB,CAAA;QAED,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;QACf,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAgB,EAAE,CAAC,CAAA;QAC1D,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;gBACrC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAA;YAC5C,CAAC;QACH,CAAC;QAED,OAAO,IAAI,aAAa,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IAED;;SAEK;IACL,MAAM;QAIJ,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;IACjE,CAAC;IAED;;;;KAIC;IACD,MAAM,CAAC,MAAM,CAAE,MAAc;QAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACjD,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IACvE,CAAC;CACF"}
|