@bitgo-beta/utxo-descriptors 0.0.1-beta.4 → 0.0.1-beta.40
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/src/sbtc/index.d.ts +1 -0
- package/dist/cjs/src/sbtc/index.d.ts.map +1 -1
- package/dist/cjs/src/sbtc/index.js +2 -1
- package/dist/cjs/src/sbtc/parseDescriptor.d.ts +47 -0
- package/dist/cjs/src/sbtc/parseDescriptor.d.ts.map +1 -0
- package/dist/cjs/src/sbtc/parseDescriptor.js +179 -0
- package/dist/cjs/test/unit/sbtc/parseDescriptor.d.ts +2 -0
- package/dist/cjs/test/unit/sbtc/parseDescriptor.d.ts.map +1 -0
- package/dist/cjs/test/unit/sbtc/parseDescriptor.js +189 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/sbtc/index.d.ts +1 -0
- package/dist/esm/sbtc/index.d.ts.map +1 -1
- package/dist/esm/sbtc/index.js +2 -1
- package/dist/esm/sbtc/parseDescriptor.d.ts +47 -0
- package/dist/esm/sbtc/parseDescriptor.d.ts.map +1 -0
- package/dist/esm/sbtc/parseDescriptor.js +176 -0
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/sbtc/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/sbtc/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
|
|
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./constants"), exports);
|
|
18
18
|
__exportStar(require("./descriptor"), exports);
|
|
19
19
|
__exportStar(require("./depositAddress"), exports);
|
|
20
|
-
|
|
20
|
+
__exportStar(require("./parseDescriptor"), exports);
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2J0Yy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsOENBQTRCO0FBQzVCLCtDQUE2QjtBQUM3QixtREFBaUM7QUFDakMsb0RBQWtDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9jb25zdGFudHMnO1xuZXhwb3J0ICogZnJvbSAnLi9kZXNjcmlwdG9yJztcbmV4cG9ydCAqIGZyb20gJy4vZGVwb3NpdEFkZHJlc3MnO1xuZXhwb3J0ICogZnJvbSAnLi9wYXJzZURlc2NyaXB0b3InO1xuIl19
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Descriptor, ast } from '@bitgo/wasm-utxo';
|
|
2
|
+
/**
|
|
3
|
+
* Parsed components of an sBTC peg-in deposit descriptor.
|
|
4
|
+
*
|
|
5
|
+
* The parser returns both the high-level
|
|
6
|
+
* fields callers usually need (keys, lockTime, fee, recipient) and the raw
|
|
7
|
+
* miniscript AST nodes so the leaves can be re-compiled into a
|
|
8
|
+
* `Miniscript` via `ast.formatNode` + `Miniscript.fromString`.
|
|
9
|
+
*/
|
|
10
|
+
export type ParsedSbtcDepositDescriptor = {
|
|
11
|
+
/** 32-byte x-only signers aggregate key from the deposit leaf. */
|
|
12
|
+
signersAggregateKey: Buffer;
|
|
13
|
+
/** Max signer fee parsed from the first 8 bytes of the payload_drop value. */
|
|
14
|
+
maxFee: bigint;
|
|
15
|
+
/** 22-byte Stacks recipient parsed from the trailing bytes of the payload. */
|
|
16
|
+
stacksRecipient: Buffer;
|
|
17
|
+
/** Reclaim-leaf relative timelock (number of Bitcoin blocks, OP_CSV argument). */
|
|
18
|
+
lockTime: number;
|
|
19
|
+
/**
|
|
20
|
+
* The three concrete x-only reclaim keys from the reclaim-leaf `multi_a`,
|
|
21
|
+
* in the order they appear inside the leaf (descriptor library sorts by hex).
|
|
22
|
+
* Only present when the descriptor is in its derived/definite form — for
|
|
23
|
+
* derivable descriptors the multi_a entries are xpub strings (e.g.
|
|
24
|
+
* `xpub.../*`), which can't be turned into 32-byte buffers without picking
|
|
25
|
+
* a derivation index. Callers that need raw key bytes MUST pass the
|
|
26
|
+
* derived descriptor (see `deriveReclaimKeys` for derivable inputs).
|
|
27
|
+
*/
|
|
28
|
+
reclaimKeys: [Buffer, Buffer, Buffer] | undefined;
|
|
29
|
+
/** Raw miniscript AST for the deposit leaf (first tap-tree leaf). */
|
|
30
|
+
depositMiniscriptNode: ast.MiniscriptNode;
|
|
31
|
+
/** Raw miniscript AST for the reclaim leaf (second tap-tree leaf). */
|
|
32
|
+
reclaimMiniscriptNode: ast.MiniscriptNode;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Parse an sBTC peg-in deposit descriptor and return its components.
|
|
36
|
+
*
|
|
37
|
+
* Returns `null` if the descriptor does not match the expected
|
|
38
|
+
* `tr(<UNSPENDABLE>, {<depositLeaf>, <reclaimLeaf>})` shape — same convention
|
|
39
|
+
* as babylon's `parseStakingDescriptor`. Throws if the shape matches but a
|
|
40
|
+
* sub-field is malformed (e.g. signers key isn't 32 bytes, payload isn't 30
|
|
41
|
+
* bytes, threshold isn't 2).
|
|
42
|
+
*
|
|
43
|
+
* Accepts both the `Descriptor` WASM object (definite or derivable) and a
|
|
44
|
+
* pre-extracted `ast.DescriptorNode`
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseSbtcDepositDescriptor(descriptor: Descriptor | ast.DescriptorNode): ParsedSbtcDepositDescriptor | null;
|
|
47
|
+
//# sourceMappingURL=parseDescriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseDescriptor.d.ts","sourceRoot":"","sources":["../../../../src/sbtc/parseDescriptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,UAAU,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAK1D;;;;;;;GAOG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,kEAAkE;IAClE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,eAAe,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAClD,qEAAqE;IACrE,qBAAqB,EAAE,GAAG,CAAC,cAAc,CAAC;IAC1C,sEAAsE;IACtE,qBAAqB,EAAE,GAAG,CAAC,cAAc,CAAC;CAC3C,CAAC;AAwJF;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,GAAG,GAAG,CAAC,cAAc,GAC1C,2BAA2B,GAAG,IAAI,CAwCpC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseSbtcDepositDescriptor = parseSbtcDepositDescriptor;
|
|
4
|
+
const wasm_utxo_1 = require("@bitgo/wasm-utxo");
|
|
5
|
+
const descriptor_1 = require("@bitgo-beta/utxo-core/descriptor");
|
|
6
|
+
const constants_1 = require("./constants");
|
|
7
|
+
function asString(v, field) {
|
|
8
|
+
if (typeof v !== 'string') {
|
|
9
|
+
throw new Error(`${field} must be a string`);
|
|
10
|
+
}
|
|
11
|
+
return v;
|
|
12
|
+
}
|
|
13
|
+
function asNumber(v, field) {
|
|
14
|
+
if (typeof v !== 'number') {
|
|
15
|
+
throw new Error(`${field} must be a number`);
|
|
16
|
+
}
|
|
17
|
+
return v;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Pull `[threshold, ...keys]` out of a `multi_a` AST node value, validating
|
|
21
|
+
* each element. The descriptor's `multi_a` is rendered with keys either as
|
|
22
|
+
* concrete hex (definite descriptor) or as xpub strings ending in `/*`
|
|
23
|
+
* (derivable descriptor) — both are strings here, so we don't try to convert
|
|
24
|
+
* to Buffer at this level.
|
|
25
|
+
*/
|
|
26
|
+
function parseMulti(multi) {
|
|
27
|
+
if (!Array.isArray(multi) || multi.length < 1) {
|
|
28
|
+
throw new Error('Invalid multi_a structure: not an array or empty');
|
|
29
|
+
}
|
|
30
|
+
const [threshold, ...keys] = multi;
|
|
31
|
+
if (typeof threshold !== 'number') {
|
|
32
|
+
throw new Error('Invalid multi_a structure: threshold is not a number');
|
|
33
|
+
}
|
|
34
|
+
if (!keys.every((k) => typeof k === 'string')) {
|
|
35
|
+
throw new Error('Invalid multi_a structure: not all keys are strings');
|
|
36
|
+
}
|
|
37
|
+
return [threshold, keys];
|
|
38
|
+
}
|
|
39
|
+
function parseDepositLeaf(depositNode, matcher) {
|
|
40
|
+
const depositPattern = {
|
|
41
|
+
and_v: [{ payload_drop: { $var: 'payloadHex' } }, { pk: { $var: 'signersKey' } }],
|
|
42
|
+
};
|
|
43
|
+
const match = matcher.match(depositNode, depositPattern);
|
|
44
|
+
if (!match) {
|
|
45
|
+
throw new Error('Deposit leaf does not match expected pattern');
|
|
46
|
+
}
|
|
47
|
+
const payloadHex = asString(match.payloadHex, 'payload_drop value');
|
|
48
|
+
const signersKeyHex = asString(match.signersKey, 'pk_k key');
|
|
49
|
+
const expectedPayloadLength = constants_1.MAX_FEE_BYTE_LENGTH + constants_1.STACKS_RECIPIENT_BYTE_LENGTH;
|
|
50
|
+
const payload = Buffer.from(payloadHex, 'hex');
|
|
51
|
+
if (payload.length !== expectedPayloadLength) {
|
|
52
|
+
throw new Error(`payload_drop value must be ${expectedPayloadLength} bytes (${expectedPayloadLength * 2} hex chars), got ${payload.length} bytes`);
|
|
53
|
+
}
|
|
54
|
+
const maxFee = payload.readBigUInt64BE(0);
|
|
55
|
+
const stacksRecipient = payload.subarray(constants_1.MAX_FEE_BYTE_LENGTH);
|
|
56
|
+
const signersAggregateKey = Buffer.from(signersKeyHex, 'hex');
|
|
57
|
+
if (signersAggregateKey.length !== 32) {
|
|
58
|
+
throw new Error(`signersAggregateKey must be 32 bytes x-only, got ${signersAggregateKey.length}`);
|
|
59
|
+
}
|
|
60
|
+
return { signersAggregateKey, maxFee, stacksRecipient };
|
|
61
|
+
}
|
|
62
|
+
function parseReclaimLeaf(reclaimNode, matcher) {
|
|
63
|
+
// and_v(r:older(<lockTime>), multi_a(2, k1, k2, k3))
|
|
64
|
+
const reclaimPattern = {
|
|
65
|
+
and_v: [{ 'r:older': { $var: 'lockTime' } }, { multi_a: { $var: 'reclaimMulti' } }],
|
|
66
|
+
};
|
|
67
|
+
const match = matcher.match(reclaimNode, reclaimPattern);
|
|
68
|
+
if (!match) {
|
|
69
|
+
throw new Error('Reclaim leaf does not match expected pattern');
|
|
70
|
+
}
|
|
71
|
+
const lockTime = asNumber(match.lockTime, 'r:older argument');
|
|
72
|
+
if (lockTime <= 0) {
|
|
73
|
+
throw new Error(`reclaim lockTime must be > 0, got ${lockTime}`);
|
|
74
|
+
}
|
|
75
|
+
const [threshold, reclaimKeyStrings] = parseMulti(match.reclaimMulti);
|
|
76
|
+
if (threshold !== 2) {
|
|
77
|
+
throw new Error(`reclaim multi_a threshold must be 2, got ${threshold}`);
|
|
78
|
+
}
|
|
79
|
+
if (reclaimKeyStrings.length !== 3) {
|
|
80
|
+
throw new Error(`reclaim multi_a must have exactly 3 keys, got ${reclaimKeyStrings.length}`);
|
|
81
|
+
}
|
|
82
|
+
return { lockTime, reclaimKeyStrings };
|
|
83
|
+
}
|
|
84
|
+
const HEX_X_ONLY_KEY = /^[0-9a-fA-F]{64}$/;
|
|
85
|
+
const XPUB_WITH_INDEX = /^([1-9A-HJ-NP-Za-km-z]+)\/(\d+)$/;
|
|
86
|
+
/**
|
|
87
|
+
* Resolve a single `multi_a` key entry to a 32-byte x-only public key.
|
|
88
|
+
*
|
|
89
|
+
* Accepts:
|
|
90
|
+
* - 64-hex-char string → returned as-is (already x-only)
|
|
91
|
+
* - `xpub.../<index>` → BIP32-derive at that index and drop the prefix byte
|
|
92
|
+
*
|
|
93
|
+
* Returns null for any other shape (e.g. wildcard `xpub.../*`, malformed input).
|
|
94
|
+
*/
|
|
95
|
+
function resolveReclaimKey(s) {
|
|
96
|
+
if (HEX_X_ONLY_KEY.test(s)) {
|
|
97
|
+
return Buffer.from(s, 'hex');
|
|
98
|
+
}
|
|
99
|
+
const m = s.match(XPUB_WITH_INDEX);
|
|
100
|
+
if (!m) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const [, xpub, indexStr] = m;
|
|
104
|
+
const index = Number.parseInt(indexStr, 10);
|
|
105
|
+
if (!Number.isFinite(index) || index < 0) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
let node;
|
|
109
|
+
try {
|
|
110
|
+
node = wasm_utxo_1.BIP32.fromBase58(xpub);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
// BIP32 public key is 33 bytes (1 prefix + 32 x-only). Drop the prefix.
|
|
116
|
+
return Buffer.from(node.derive(index).publicKey.subarray(1));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Convert reclaim-leaf key strings into 32-byte x-only buffers. Accepts both
|
|
120
|
+
* the definite/derived form (concrete 64-hex-char x-only keys) and the form
|
|
121
|
+
* produced by `Descriptor.atDerivationIndex(n)` (`xpub.../<n>`). Returns
|
|
122
|
+
* undefined if any entry is still wildcard (`xpub.../*`) or otherwise
|
|
123
|
+
* unresolvable.
|
|
124
|
+
*/
|
|
125
|
+
function reclaimKeysFromStrings(keyStrings) {
|
|
126
|
+
const resolved = keyStrings.map(resolveReclaimKey);
|
|
127
|
+
if (resolved.some((b) => b === null) || resolved.length !== 3) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
return [resolved[0], resolved[1], resolved[2]];
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Parse an sBTC peg-in deposit descriptor and return its components.
|
|
134
|
+
*
|
|
135
|
+
* Returns `null` if the descriptor does not match the expected
|
|
136
|
+
* `tr(<UNSPENDABLE>, {<depositLeaf>, <reclaimLeaf>})` shape — same convention
|
|
137
|
+
* as babylon's `parseStakingDescriptor`. Throws if the shape matches but a
|
|
138
|
+
* sub-field is malformed (e.g. signers key isn't 32 bytes, payload isn't 30
|
|
139
|
+
* bytes, threshold isn't 2).
|
|
140
|
+
*
|
|
141
|
+
* Accepts both the `Descriptor` WASM object (definite or derivable) and a
|
|
142
|
+
* pre-extracted `ast.DescriptorNode`
|
|
143
|
+
*/
|
|
144
|
+
function parseSbtcDepositDescriptor(descriptor) {
|
|
145
|
+
const pattern = {
|
|
146
|
+
tr: [constants_1.UNSPENDABLE_INTERNAL_KEY, [{ $var: 'depositLeaf' }, { $var: 'reclaimLeaf' }]],
|
|
147
|
+
};
|
|
148
|
+
const matcher = new descriptor_1.PatternMatcher();
|
|
149
|
+
const descriptorNode = descriptor instanceof wasm_utxo_1.Descriptor ? wasm_utxo_1.ast.fromDescriptor(descriptor) : descriptor;
|
|
150
|
+
const result = matcher.match(descriptorNode, pattern);
|
|
151
|
+
if (!result) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const depositMiniscriptNode = result.depositLeaf;
|
|
155
|
+
let reclaimMiniscriptNode = result.reclaimLeaf;
|
|
156
|
+
const { signersAggregateKey, maxFee, stacksRecipient } = parseDepositLeaf(depositMiniscriptNode, matcher);
|
|
157
|
+
const { lockTime, reclaimKeyStrings } = parseReclaimLeaf(reclaimMiniscriptNode, matcher);
|
|
158
|
+
const reclaimKeys = reclaimKeysFromStrings(reclaimKeyStrings);
|
|
159
|
+
if (reclaimKeys) {
|
|
160
|
+
// Rewrite the reclaim leaf with concrete hex keys when we can resolve
|
|
161
|
+
// them — `Miniscript.fromString(..., 'tap')` only accepts x-only hex in
|
|
162
|
+
// `multi_a`, not xpub-form strings. With this rewrite the formatted
|
|
163
|
+
// leaf is directly compilable; without it callers must do the
|
|
164
|
+
// resolution themselves.
|
|
165
|
+
reclaimMiniscriptNode = {
|
|
166
|
+
and_v: [{ 'r:older': lockTime }, { multi_a: [2, ...reclaimKeys.map((k) => k.toString('hex'))] }],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
signersAggregateKey,
|
|
171
|
+
maxFee,
|
|
172
|
+
stacksRecipient,
|
|
173
|
+
lockTime,
|
|
174
|
+
reclaimKeys,
|
|
175
|
+
depositMiniscriptNode,
|
|
176
|
+
reclaimMiniscriptNode,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VEZXNjcmlwdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3NidGMvcGFyc2VEZXNjcmlwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBd01BLGdFQTBDQztBQWxQRCxnREFBMEQ7QUFDMUQsaUVBQTJFO0FBRTNFLDJDQUEwRztBQW1DMUcsU0FBUyxRQUFRLENBQUMsQ0FBVSxFQUFFLEtBQWE7SUFDekMsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsS0FBSyxtQkFBbUIsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFDRCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFRCxTQUFTLFFBQVEsQ0FBQyxDQUFVLEVBQUUsS0FBYTtJQUN6QyxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLG1CQUFtQixDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUNELE9BQU8sQ0FBQyxDQUFDO0FBQ1gsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsVUFBVSxDQUFDLEtBQWM7SUFDaEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM5QyxNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUNELE1BQU0sQ0FBQyxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDbkMsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7SUFDMUUsQ0FBQztJQUNELElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMs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QUFxQjtRQUNyQixxQkFBcUI7S0FDdEIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCSVAzMiwgRGVzY3JpcHRvciwgYXN0IH0gZnJvbSAnQGJpdGdvL3dhc20tdXR4byc7XG5pbXBvcnQgeyBQYXR0ZXJuTWF0Y2hlciwgUGF0dGVybiB9IGZyb20gJ0BiaXRnby1iZXRhL3V0eG8tY29yZS9kZXNjcmlwdG9yJztcblxuaW1wb3J0IHsgTUFYX0ZFRV9CWVRFX0xFTkdUSCwgU1RBQ0tTX1JFQ0lQSUVOVF9CWVRFX0xFTkdUSCwgVU5TUEVOREFCTEVfSU5URVJOQUxfS0VZIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuXG4vKipcbiAqIFBhcnNlZCBjb21wb25lbnRzIG9mIGFuIHNCVEMgcGVnLWluIGRlcG9zaXQgZGVzY3JpcHRvci5cbiAqXG4gKiBUaGUgcGFyc2VyIHJldHVybnMgYm90aCB0aGUgaGlnaC1sZXZlbFxuICogZmllbGRzIGNhbGxlcnMgdXN1YWxseSBuZWVkIChrZXlzLCBsb2NrVGltZSwgZmVlLCByZWNpcGllbnQpIGFuZCB0aGUgcmF3XG4gKiBtaW5pc2NyaXB0IEFTVCBub2RlcyBzbyB0aGUgbGVhdmVzIGNhbiBiZSByZS1jb21waWxlZCBpbnRvIGFcbiAqIGBNaW5pc2NyaXB0YCB2aWEgYGFzdC5mb3JtYXROb2RlYCArIGBNaW5pc2NyaXB0LmZyb21TdHJpbmdgLlxuICovXG5leHBvcnQgdHlwZSBQYXJzZWRTYnRjRGVwb3NpdERlc2NyaXB0b3IgPSB7XG4gIC8qKiAzMi1ieXRlIHgtb25seSBzaWduZXJzIGFnZ3JlZ2F0ZSBrZXkgZnJvbSB0aGUgZGVwb3NpdCBsZWFmLiAqL1xuICBzaWduZXJzQWdncmVnYXRlS2V5OiBCdWZmZXI7XG4gIC8qKiBNYXggc2lnbmVyIGZlZSBwYXJzZWQgZnJvbSB0aGUgZmlyc3QgOCBieXRlcyBvZiB0aGUgcGF5bG9hZF9kcm9wIHZhbHVlLiAqL1xuICBtYXhGZWU6IGJpZ2ludDtcbiAgLyoqIDIyLWJ5dGUgU3RhY2tzIHJlY2lwaWVudCBwYXJzZWQgZnJvbSB0aGUgdHJhaWxpbmcgYnl0ZXMgb2YgdGhlIHBheWxvYWQuICovXG4gIHN0YWNrc1JlY2lwaWVudDogQnVmZmVyO1xuICAvKiogUmVjbGFpbS1sZWFmIHJlbGF0aXZlIHRpbWVsb2NrIChudW1iZXIgb2YgQml0Y29pbiBibG9ja3MsIE9QX0NTViBhcmd1bWVudCkuICovXG4gIGxvY2tUaW1lOiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgdGhyZWUgY29uY3JldGUgeC1vbmx5IHJlY2xhaW0ga2V5cyBmcm9tIHRoZSByZWNsYWltLWxlYWYgYG11bHRpX2FgLFxuICAgKiBpbiB0aGUgb3JkZXIgdGhleSBhcHBlYXIgaW5zaWRlIHRoZSBsZWFmIChkZXNjcmlwdG9yIGxpYnJhcnkgc29ydHMgYnkgaGV4KS5cbiAgICogT25seSBwcmVzZW50IHdoZW4gdGhlIGRlc2NyaXB0b3IgaXMgaW4gaXRzIGRlcml2ZWQvZGVmaW5pdGUgZm9ybSDigJQgZm9yXG4gICAqIGRlcml2YWJsZSBkZXNjcmlwdG9ycyB0aGUgbXVsdGlfYSBlbnRyaWVzIGFyZSB4cHViIHN0cmluZ3MgKGUuZy5cbiAgICogYHhwdWIuLi4vKmApLCB3aGljaCBjYW4ndCBiZSB0dXJuZWQgaW50byAzMi1ieXRlIGJ1ZmZlcnMgd2l0aG91dCBwaWNraW5nXG4gICAqIGEgZGVyaXZhdGlvbiBpbmRleC4gQ2FsbGVycyB0aGF0IG5lZWQgcmF3IGtleSBieXRlcyBNVVNUIHBhc3MgdGhlXG4gICAqIGRlcml2ZWQgZGVzY3JpcHRvciAoc2VlIGBkZXJpdmVSZWNsYWltS2V5c2AgZm9yIGRlcml2YWJsZSBpbnB1dHMpLlxuICAgKi9cbiAgcmVjbGFpbUtleXM6IFtCdWZmZXIsIEJ1ZmZlciwgQnVmZmVyXSB8IHVuZGVmaW5lZDtcbiAgLyoqIFJhdyBtaW5pc2NyaXB0IEFTVCBmb3IgdGhlIGRlcG9zaXQgbGVhZiAoZmlyc3QgdGFwLXRyZWUgbGVhZikuICovXG4gIGRlcG9zaXRNaW5pc2NyaXB0Tm9kZTogYXN0Lk1pbmlzY3JpcHROb2RlO1xuICAvKiogUmF3IG1pbmlzY3JpcHQgQVNUIGZvciB0aGUgcmVjbGFpbSBsZWFmIChzZWNvbmQgdGFwLXRyZWUgbGVhZikuICovXG4gIHJlY2xhaW1NaW5pc2NyaXB0Tm9kZTogYXN0Lk1pbmlzY3JpcHROb2RlO1xufTtcblxuZnVuY3Rpb24gYXNTdHJpbmcodjogdW5rbm93biwgZmllbGQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICh0eXBlb2YgdiAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZmllbGR9IG11c3QgYmUgYSBzdHJpbmdgKTtcbiAgfVxuICByZXR1cm4gdjtcbn1cblxuZnVuY3Rpb24gYXNOdW1iZXIodjogdW5rbm93biwgZmllbGQ6IHN0cmluZyk6IG51bWJlciB7XG4gIGlmICh0eXBlb2YgdiAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZmllbGR9IG11c3QgYmUgYSBudW1iZXJgKTtcbiAgfVxuICByZXR1cm4gdjtcbn1cblxuLyoqXG4gKiBQdWxsIGBbdGhyZXNob2xkLCAuLi5rZXlzXWAgb3V0IG9mIGEgYG11bHRpX2FgIEFTVCBub2RlIHZhbHVlLCB2YWxpZGF0aW5nXG4gKiBlYWNoIGVsZW1lbnQuIFRoZSBkZXNjcmlwdG9yJ3MgYG11bHRpX2FgIGlzIHJlbmRlcmVkIHdpdGgga2V5cyBlaXRoZXIgYXNcbiAqIGNvbmNyZXRlIGhleCAoZGVmaW5pdGUgZGVzY3JpcHRvcikgb3IgYXMgeHB1YiBzdHJpbmdzIGVuZGluZyBpbiBgLypgXG4gKiAoZGVyaXZhYmxlIGRlc2NyaXB0b3IpIOKAlCBib3RoIGFyZSBzdHJpbmdzIGhlcmUsIHNvIHdlIGRvbid0IHRyeSB0byBjb252ZXJ0XG4gKiB0byBCdWZmZXIgYXQgdGhpcyBsZXZlbC5cbiAqL1xuZnVuY3Rpb24gcGFyc2VNdWx0aShtdWx0aTogdW5rbm93bik6IFtudW1iZXIsIHN0cmluZ1tdXSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShtdWx0aSkgfHwgbXVsdGkubGVuZ3RoIDwgMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBtdWx0aV9hIHN0cnVjdHVyZTogbm90IGFuIGFycmF5IG9yIGVtcHR5Jyk7XG4gIH1cbiAgY29uc3QgW3RocmVzaG9sZCwgLi4ua2V5c10gPSBtdWx0aTtcbiAgaWYgKHR5cGVvZiB0aHJlc2hvbGQgIT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG11bHRpX2Egc3RydWN0dXJlOiB0aHJlc2hvbGQgaXMgbm90IGEgbnVtYmVyJyk7XG4gIH1cbiAgaWYgKCFrZXlzLmV2ZXJ5KChrKSA9PiB0eXBlb2YgayA9PT0gJ3N0cmluZycpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG11bHRpX2Egc3RydWN0dXJlOiBub3QgYWxsIGtleXMgYXJlIHN0cmluZ3MnKTtcbiAgfVxuICByZXR1cm4gW3RocmVzaG9sZCwga2V5c107XG59XG5cbmZ1bmN0aW9uIHBhcnNlRGVwb3NpdExlYWYoXG4gIGRlcG9zaXROb2RlOiBhc3QuTWluaXNjcmlwdE5vZGUsXG4gIG1hdGNoZXI6IFBhdHRlcm5NYXRjaGVyXG4pOiB7IHNpZ25lcnNBZ2dyZWdhdGVLZXk6IEJ1ZmZlcjsgbWF4RmVlOiBiaWdpbnQ7IHN0YWNrc1JlY2lwaWVudDogQnVmZmVyIH0ge1xuICBjb25zdCBkZXBvc2l0UGF0dGVybjogUGF0dGVybiA9IHtcbiAgICBhbmRfdjogW3sgcGF5bG9hZF9kcm9wOiB7ICR2YXI6ICdwYXlsb2FkSGV4JyB9IH0sIHsgcGs6IHsgJHZhcjogJ3NpZ25lcnNLZXknIH0gfV0sXG4gIH07XG4gIGNvbnN0IG1hdGNoID0gbWF0Y2hlci5tYXRjaChkZXBvc2l0Tm9kZSwgZGVwb3NpdFBhdHRlcm4pO1xuICBpZiAoIW1hdGNoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdEZXBvc2l0IGxlYWYgZG9lcyBub3QgbWF0Y2ggZXhwZWN0ZWQgcGF0dGVybicpO1xuICB9XG5cbiAgY29uc3QgcGF5bG9hZEhleCA9IGFzU3RyaW5nKG1hdGNoLnBheWxvYWRIZXgsICdwYXlsb2FkX2Ryb3AgdmFsdWUnKTtcbiAgY29uc3Qgc2lnbmVyc0tleUhleCA9IGFzU3RyaW5nKG1hdGNoLnNpZ25lcnNLZXksICdwa19rIGtleScpO1xuXG4gIGNvbnN0IGV4cGVjdGVkUGF5bG9hZExlbmd0aCA9IE1BWF9GRUVfQllURV9MRU5HVEggKyBTVEFDS1NfUkVDSVBJRU5UX0JZVEVfTEVOR1RIO1xuICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmZyb20ocGF5bG9hZEhleCwgJ2hleCcpO1xuICBpZiAocGF5bG9hZC5sZW5ndGggIT09IGV4cGVjdGVkUGF5bG9hZExlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBwYXlsb2FkX2Ryb3AgdmFsdWUgbXVzdCBiZSAke2V4cGVjdGVkUGF5bG9hZExlbmd0aH0gYnl0ZXMgKCR7ZXhwZWN0ZWRQYXlsb2FkTGVuZ3RoICogMn0gaGV4IGNoYXJzKSwgZ290ICR7XG4gICAgICAgIHBheWxvYWQubGVuZ3RoXG4gICAgICB9IGJ5dGVzYFxuICAgICk7XG4gIH1cblxuICBjb25zdCBtYXhGZWUgPSBwYXlsb2FkLnJlYWRCaWdVSW50NjRCRSgwKTtcbiAgY29uc3Qgc3RhY2tzUmVjaXBpZW50ID0gcGF5bG9hZC5zdWJhcnJheShNQVhfRkVFX0JZVEVfTEVOR1RIKTtcblxuICBjb25zdCBzaWduZXJzQWdncmVnYXRlS2V5ID0gQnVmZmVyLmZyb20oc2lnbmVyc0tleUhleCwgJ2hleCcpO1xuICBpZiAoc2lnbmVyc0FnZ3JlZ2F0ZUtleS5sZW5ndGggIT09IDMyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBzaWduZXJzQWdncmVnYXRlS2V5IG11c3QgYmUgMzIgYnl0ZXMgeC1vbmx5LCBnb3QgJHtzaWduZXJzQWdncmVnYXRlS2V5Lmxlbmd0aH1gKTtcbiAgfVxuXG4gIHJldHVybiB7IHNpZ25lcnNBZ2dyZWdhdGVLZXksIG1heEZlZSwgc3RhY2tzUmVjaXBpZW50IH07XG59XG5cbmZ1bmN0aW9uIHBhcnNlUmVjbGFpbUxlYWYoXG4gIHJlY2xhaW1Ob2RlOiBhc3QuTWluaXNjcmlwdE5vZGUsXG4gIG1hdGNoZXI6IFBhdHRlcm5NYXRjaGVyXG4pOiB7IGxvY2tUaW1lOiBudW1iZXI7IHJlY2xhaW1LZXlTdHJpbmdzOiBzdHJpbmdbXSB9IHtcbiAgLy8gYW5kX3YocjpvbGRlcig8bG9ja1RpbWU+KSwgbXVsdGlfYSgyLCBrMSwgazIsIGszKSlcbiAgY29uc3QgcmVjbGFpbVBhdHRlcm46IFBhdHRlcm4gPSB7XG4gICAgYW5kX3Y6IFt7ICdyOm9sZGVyJzogeyAkdmFyOiAnbG9ja1RpbWUnIH0gfSwgeyBtdWx0aV9hOiB7ICR2YXI6ICdyZWNsYWltTXVsdGknIH0gfV0sXG4gIH07XG4gIGNvbnN0IG1hdGNoID0gbWF0Y2hlci5tYXRjaChyZWNsYWltTm9kZSwgcmVjbGFpbVBhdHRlcm4pO1xuICBpZiAoIW1hdGNoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdSZWNsYWltIGxlYWYgZG9lcyBub3QgbWF0Y2ggZXhwZWN0ZWQgcGF0dGVybicpO1xuICB9XG5cbiAgY29uc3QgbG9ja1RpbWUgPSBhc051bWJlcihtYXRjaC5sb2NrVGltZSwgJ3I6b2xkZXIgYXJndW1lbnQnKTtcbiAgaWYgKGxvY2tUaW1lIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHJlY2xhaW0gbG9ja1RpbWUgbXVzdCBiZSA+IDAsIGdvdCAke2xvY2tUaW1lfWApO1xuICB9XG5cbiAgY29uc3QgW3RocmVzaG9sZCwgcmVjbGFpbUtleVN0cmluZ3NdID0gcGFyc2VNdWx0aShtYXRjaC5yZWNsYWltTXVsdGkpO1xuICBpZiAodGhyZXNob2xkICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGByZWNsYWltIG11bHRpX2EgdGhyZXNob2xkIG11c3QgYmUgMiwgZ290ICR7dGhyZXNob2xkfWApO1xuICB9XG4gIGlmIChyZWNsYWltS2V5U3RyaW5ncy5sZW5ndGggIT09IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHJlY2xhaW0gbXVsdGlfYSBtdXN0IGhhdmUgZXhhY3RseSAzIGtleXMsIGdvdCAke3JlY2xhaW1LZXlTdHJpbmdzLmxlbmd0aH1gKTtcbiAgfVxuXG4gIHJldHVybiB7IGxvY2tUaW1lLCByZWNsYWltS2V5U3RyaW5ncyB9O1xufVxuXG5jb25zdCBIRVhfWF9PTkxZX0tFWSA9IC9eWzAtOWEtZkEtRl17NjR9JC87XG5jb25zdCBYUFVCX1dJVEhfSU5ERVggPSAvXihbMS05QS1ISi1OUC1aYS1rbS16XSspXFwvKFxcZCspJC87XG5cbi8qKlxuICogUmVzb2x2ZSBhIHNpbmdsZSBgbXVsdGlfYWAga2V5IGVudHJ5IHRvIGEgMzItYnl0ZSB4LW9ubHkgcHVibGljIGtleS5cbiAqXG4gKiBBY2NlcHRzOlxuICogICAtIDY0LWhleC1jaGFyIHN0cmluZyDihpIgcmV0dXJuZWQgYXMtaXMgKGFscmVhZHkgeC1vbmx5KVxuICogICAtIGB4cHViLi4uLzxpbmRleD5gIOKGkiBCSVAzMi1kZXJpdmUgYXQgdGhhdCBpbmRleCBhbmQgZHJvcCB0aGUgcHJlZml4IGJ5dGVcbiAqXG4gKiBSZXR1cm5zIG51bGwgZm9yIGFueSBvdGhlciBzaGFwZSAoZS5nLiB3aWxkY2FyZCBgeHB1Yi4uLi8qYCwgbWFsZm9ybWVkIGlucHV0KS5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVJlY2xhaW1LZXkoczogc3RyaW5nKTogQnVmZmVyIHwgbnVsbCB7XG4gIGlmIChIRVhfWF9PTkxZX0tFWS50ZXN0KHMpKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHMsICdoZXgnKTtcbiAgfVxuICBjb25zdCBtID0gcy5tYXRjaChYUFVCX1dJVEhfSU5ERVgpO1xuICBpZiAoIW0pIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCBbLCB4cHViLCBpbmRleFN0cl0gPSBtO1xuICBjb25zdCBpbmRleCA9IE51bWJlci5wYXJzZUludChpbmRleFN0ciwgMTApO1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZShpbmRleCkgfHwgaW5kZXggPCAwKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgbGV0IG5vZGU7XG4gIHRyeSB7XG4gICAgbm9kZSA9IEJJUDMyLmZyb21CYXNlNTgoeHB1Yik7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIC8vIEJJUDMyIHB1YmxpYyBrZXkgaXMgMzMgYnl0ZXMgKDEgcHJlZml4ICsgMzIgeC1vbmx5KS4gRHJvcCB0aGUgcHJlZml4LlxuICByZXR1cm4gQnVmZmVyLmZyb20obm9kZS5kZXJpdmUoaW5kZXgpLnB1YmxpY0tleS5zdWJhcnJheSgxKSk7XG59XG5cbi8qKlxuICogQ29udmVydCByZWNsYWltLWxlYWYga2V5IHN0cmluZ3MgaW50byAzMi1ieXRlIHgtb25seSBidWZmZXJzLiBBY2NlcHRzIGJvdGhcbiAqIHRoZSBkZWZpbml0ZS9kZXJpdmVkIGZvcm0gKGNvbmNyZXRlIDY0LWhleC1jaGFyIHgtb25seSBrZXlzKSBhbmQgdGhlIGZvcm1cbiAqIHByb2R1Y2VkIGJ5IGBEZXNjcmlwdG9yLmF0RGVyaXZhdGlvbkluZGV4KG4pYCAoYHhwdWIuLi4vPG4+YCkuIFJldHVybnNcbiAqIHVuZGVmaW5lZCBpZiBhbnkgZW50cnkgaXMgc3RpbGwgd2lsZGNhcmQgKGB4cHViLi4uLypgKSBvciBvdGhlcndpc2VcbiAqIHVucmVzb2x2YWJsZS5cbiAqL1xuZnVuY3Rpb24gcmVjbGFpbUtleXNGcm9tU3RyaW5ncyhrZXlTdHJpbmdzOiBzdHJpbmdbXSk6IFtCdWZmZXIsIEJ1ZmZlciwgQnVmZmVyXSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHJlc29sdmVkID0ga2V5U3RyaW5ncy5tYXAocmVzb2x2ZVJlY2xhaW1LZXkpO1xuICBpZiAocmVzb2x2ZWQuc29tZSgoYikgPT4gYiA9PT0gbnVsbCkgfHwgcmVzb2x2ZWQubGVuZ3RoICE9PSAzKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gW3Jlc29sdmVkWzBdIGFzIEJ1ZmZlciwgcmVzb2x2ZWRbMV0gYXMgQnVmZmVyLCByZXNvbHZlZFsyXSBhcyBCdWZmZXJdO1xufVxuXG4vKipcbiAqIFBhcnNlIGFuIHNCVEMgcGVnLWluIGRlcG9zaXQgZGVzY3JpcHRvciBhbmQgcmV0dXJuIGl0cyBjb21wb25lbnRzLlxuICpcbiAqIFJldHVybnMgYG51bGxgIGlmIHRoZSBkZXNjcmlwdG9yIGRvZXMgbm90IG1hdGNoIHRoZSBleHBlY3RlZFxuICogYHRyKDxVTlNQRU5EQUJMRT4sIHs8ZGVwb3NpdExlYWY+LCA8cmVjbGFpbUxlYWY+fSlgIHNoYXBlIOKAlCBzYW1lIGNvbnZlbnRpb25cbiAqIGFzIGJhYnlsb24ncyBgcGFyc2VTdGFraW5nRGVzY3JpcHRvcmAuIFRocm93cyBpZiB0aGUgc2hhcGUgbWF0Y2hlcyBidXQgYVxuICogc3ViLWZpZWxkIGlzIG1hbGZvcm1lZCAoZS5nLiBzaWduZXJzIGtleSBpc24ndCAzMiBieXRlcywgcGF5bG9hZCBpc24ndCAzMFxuICogYnl0ZXMsIHRocmVzaG9sZCBpc24ndCAyKS5cbiAqXG4gKiBBY2NlcHRzIGJvdGggdGhlIGBEZXNjcmlwdG9yYCBXQVNNIG9iamVjdCAoZGVmaW5pdGUgb3IgZGVyaXZhYmxlKSBhbmQgYVxuICogcHJlLWV4dHJhY3RlZCBgYXN0LkRlc2NyaXB0b3JOb2RlYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTYnRjRGVwb3NpdERlc2NyaXB0b3IoXG4gIGRlc2NyaXB0b3I6IERlc2NyaXB0b3IgfCBhc3QuRGVzY3JpcHRvck5vZGVcbik6IFBhcnNlZFNidGNEZXBvc2l0RGVzY3JpcHRvciB8IG51bGwge1xuICBjb25zdCBwYXR0ZXJuOiBQYXR0ZXJuID0ge1xuICAgIHRyOiBbVU5TUEVOREFCTEVfSU5URVJOQUxfS0VZLCBbeyAkdmFyOiAnZGVwb3NpdExlYWYnIH0sIHsgJHZhcjogJ3JlY2xhaW1MZWFmJyB9XV0sXG4gIH07XG5cbiAgY29uc3QgbWF0Y2hlciA9IG5ldyBQYXR0ZXJuTWF0Y2hlcigpO1xuICBjb25zdCBkZXNjcmlwdG9yTm9kZSA9IGRlc2NyaXB0b3IgaW5zdGFuY2VvZiBEZXNjcmlwdG9yID8gYXN0LmZyb21EZXNjcmlwdG9yKGRlc2NyaXB0b3IpIDogZGVzY3JpcHRvcjtcbiAgY29uc3QgcmVzdWx0ID0gbWF0Y2hlci5tYXRjaChkZXNjcmlwdG9yTm9kZSwgcGF0dGVybik7XG5cbiAgaWYgKCFyZXN1bHQpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGRlcG9zaXRNaW5pc2NyaXB0Tm9kZSA9IHJlc3VsdC5kZXBvc2l0TGVhZiBhcyBhc3QuTWluaXNjcmlwdE5vZGU7XG4gIGxldCByZWNsYWltTWluaXNjcmlwdE5vZGUgPSByZXN1bHQucmVjbGFpbUxlYWYgYXMgYXN0Lk1pbmlzY3JpcHROb2RlO1xuXG4gIGNvbnN0IHsgc2lnbmVyc0FnZ3JlZ2F0ZUtleSwgbWF4RmVlLCBzdGFja3NSZWNpcGllbnQgfSA9IHBhcnNlRGVwb3NpdExlYWYoZGVwb3NpdE1pbmlzY3JpcHROb2RlLCBtYXRjaGVyKTtcbiAgY29uc3QgeyBsb2NrVGltZSwgcmVjbGFpbUtleVN0cmluZ3MgfSA9IHBhcnNlUmVjbGFpbUxlYWYocmVjbGFpbU1pbmlzY3JpcHROb2RlLCBtYXRjaGVyKTtcblxuICBjb25zdCByZWNsYWltS2V5cyA9IHJlY2xhaW1LZXlzRnJvbVN0cmluZ3MocmVjbGFpbUtleVN0cmluZ3MpO1xuICBpZiAocmVjbGFpbUtleXMpIHtcbiAgICAvLyBSZXdyaXRlIHRoZSByZWNsYWltIGxlYWYgd2l0aCBjb25jcmV0ZSBoZXgga2V5cyB3aGVuIHdlIGNhbiByZXNvbHZlXG4gICAgLy8gdGhlbSDigJQgYE1pbmlzY3JpcHQuZnJvbVN0cmluZyguLi4sICd0YXAnKWAgb25seSBhY2NlcHRzIHgtb25seSBoZXggaW5cbiAgICAvLyBgbXVsdGlfYWAsIG5vdCB4cHViLWZvcm0gc3RyaW5ncy4gV2l0aCB0aGlzIHJld3JpdGUgdGhlIGZvcm1hdHRlZFxuICAgIC8vIGxlYWYgaXMgZGlyZWN0bHkgY29tcGlsYWJsZTsgd2l0aG91dCBpdCBjYWxsZXJzIG11c3QgZG8gdGhlXG4gICAgLy8gcmVzb2x1dGlvbiB0aGVtc2VsdmVzLlxuICAgIHJlY2xhaW1NaW5pc2NyaXB0Tm9kZSA9IHtcbiAgICAgIGFuZF92OiBbeyAncjpvbGRlcic6IGxvY2tUaW1lIH0sIHsgbXVsdGlfYTogWzIsIC4uLnJlY2xhaW1LZXlzLm1hcCgoaykgPT4gay50b1N0cmluZygnaGV4JykpXSB9XSxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBzaWduZXJzQWdncmVnYXRlS2V5LFxuICAgIG1heEZlZSxcbiAgICBzdGFja3NSZWNpcGllbnQsXG4gICAgbG9ja1RpbWUsXG4gICAgcmVjbGFpbUtleXMsXG4gICAgZGVwb3NpdE1pbmlzY3JpcHROb2RlLFxuICAgIHJlY2xhaW1NaW5pc2NyaXB0Tm9kZSxcbiAgfTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseDescriptor.d.ts","sourceRoot":"","sources":["../../../../../test/unit/sbtc/parseDescriptor.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const assert = __importStar(require("assert"));
|
|
37
|
+
const wasm_utxo_1 = require("@bitgo/wasm-utxo");
|
|
38
|
+
const testutils_1 = require("@bitgo/wasm-utxo/testutils");
|
|
39
|
+
const sbtc_1 = require("../../../src/sbtc");
|
|
40
|
+
const SIGNERS_AGGREGATE_KEY = Buffer.from('c9c2312ca406dcb8eed50b829b5292f5fb3e846db0a556af61cc53834ce75421', 'hex');
|
|
41
|
+
const STACKS_RECIPIENT = Buffer.from('05' + '16' + '6d'.repeat(20), 'hex');
|
|
42
|
+
function getBip32Triple() {
|
|
43
|
+
const [user, backup, bitgo] = (0, testutils_1.getKeyTriple)('default');
|
|
44
|
+
return [user, backup, bitgo];
|
|
45
|
+
}
|
|
46
|
+
function buildParams(overrides = {}) {
|
|
47
|
+
return {
|
|
48
|
+
walletKeys: getBip32Triple(),
|
|
49
|
+
lockTime: sbtc_1.DEFAULT_RECLAIM_LOCK_TIME,
|
|
50
|
+
maxFee: sbtc_1.DEFAULT_MAX_SIGNER_FEE,
|
|
51
|
+
stacksRecipient: STACKS_RECIPIENT,
|
|
52
|
+
signersAggregateKey: SIGNERS_AGGREGATE_KEY,
|
|
53
|
+
...overrides,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
describe('parseSbtcDepositDescriptor', function () {
|
|
57
|
+
describe('definite descriptor (concrete x-only reclaim keys)', function () {
|
|
58
|
+
const reclaimKeyHex = [
|
|
59
|
+
'4d838759b2a74616a2298e0580ca815874f5e5a9d2dd1b2f0203b68c66fc6c1e',
|
|
60
|
+
'639779c4b700dc51ece012a0e20325fcafada22a4a122ffaa04d0c0ccae83943',
|
|
61
|
+
'd1d6084eac98303e9d28e082bfd9eadf0b8be033e223a17ad01df81bdaa8c7b2',
|
|
62
|
+
];
|
|
63
|
+
const reclaimKeys = [
|
|
64
|
+
Buffer.from(reclaimKeyHex[0], 'hex'),
|
|
65
|
+
Buffer.from(reclaimKeyHex[1], 'hex'),
|
|
66
|
+
Buffer.from(reclaimKeyHex[2], 'hex'),
|
|
67
|
+
];
|
|
68
|
+
const params = {
|
|
69
|
+
walletKeys: reclaimKeys,
|
|
70
|
+
lockTime: 144,
|
|
71
|
+
maxFee: 80000,
|
|
72
|
+
stacksRecipient: STACKS_RECIPIENT,
|
|
73
|
+
signersAggregateKey: SIGNERS_AGGREGATE_KEY,
|
|
74
|
+
};
|
|
75
|
+
const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'definite');
|
|
76
|
+
it('round-trips all high-level fields', function () {
|
|
77
|
+
const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
|
|
78
|
+
assert.ok(parsed);
|
|
79
|
+
assert.deepStrictEqual(parsed.signersAggregateKey, SIGNERS_AGGREGATE_KEY);
|
|
80
|
+
assert.strictEqual(parsed.maxFee, 80000n);
|
|
81
|
+
assert.deepStrictEqual(parsed.stacksRecipient, STACKS_RECIPIENT);
|
|
82
|
+
assert.strictEqual(parsed.lockTime, 144);
|
|
83
|
+
});
|
|
84
|
+
it('returns reclaim keys as 32-byte buffers in the descriptor order', function () {
|
|
85
|
+
const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
|
|
86
|
+
assert.ok(parsed);
|
|
87
|
+
assert.ok(parsed.reclaimKeys);
|
|
88
|
+
// multi_a sorts keys by hex; verify the parser returns whatever order
|
|
89
|
+
// the descriptor library produced rather than the original input order.
|
|
90
|
+
const sortedInput = [...reclaimKeyHex].sort().map((k) => Buffer.from(k, 'hex'));
|
|
91
|
+
assert.deepStrictEqual(parsed.reclaimKeys, sortedInput);
|
|
92
|
+
});
|
|
93
|
+
it('returns miniscript AST nodes for both leaves', function () {
|
|
94
|
+
const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
|
|
95
|
+
assert.ok(parsed);
|
|
96
|
+
const payloadHex = (0, sbtc_1.encodeDepositPayload)(params.maxFee, params.stacksRecipient).toString('hex');
|
|
97
|
+
assert.deepStrictEqual(parsed.depositMiniscriptNode, {
|
|
98
|
+
and_v: [{ payload_drop: payloadHex }, { pk: SIGNERS_AGGREGATE_KEY.toString('hex') }],
|
|
99
|
+
});
|
|
100
|
+
// r:older + multi_a must be present and correctly ordered in the AST.
|
|
101
|
+
assert.deepStrictEqual(parsed.reclaimMiniscriptNode, {
|
|
102
|
+
and_v: [{ 'r:older': 144 }, { multi_a: [2, ...[...reclaimKeyHex].sort()] }],
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
describe('derivable descriptor (xpub/* reclaim keys)', function () {
|
|
107
|
+
const params = buildParams();
|
|
108
|
+
const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'derivable');
|
|
109
|
+
it('round-trips lockTime, maxFee, recipient, and signers key', function () {
|
|
110
|
+
const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
|
|
111
|
+
assert.ok(parsed);
|
|
112
|
+
assert.deepStrictEqual(parsed.signersAggregateKey, SIGNERS_AGGREGATE_KEY);
|
|
113
|
+
assert.strictEqual(parsed.maxFee, BigInt(sbtc_1.DEFAULT_MAX_SIGNER_FEE));
|
|
114
|
+
assert.deepStrictEqual(parsed.stacksRecipient, STACKS_RECIPIENT);
|
|
115
|
+
assert.strictEqual(parsed.lockTime, sbtc_1.DEFAULT_RECLAIM_LOCK_TIME);
|
|
116
|
+
});
|
|
117
|
+
it('returns reclaimKeys=undefined for derivable inputs', function () {
|
|
118
|
+
// Derivable descriptors render multi_a entries as `xpub.../*`, not as
|
|
119
|
+
// 32-byte hex — they can't be reduced to bytes without picking an index.
|
|
120
|
+
const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
|
|
121
|
+
assert.ok(parsed);
|
|
122
|
+
assert.strictEqual(parsed.reclaimKeys, undefined);
|
|
123
|
+
});
|
|
124
|
+
it('resolves to concrete reclaim keys after atDerivationIndex(0) and compiles to a tap Miniscript', function () {
|
|
125
|
+
assert.strictEqual(descriptor.hasWildcard(), true);
|
|
126
|
+
const derivedZero = descriptor.atDerivationIndex(0);
|
|
127
|
+
const derivedOne = descriptor.atDerivationIndex(1);
|
|
128
|
+
assert.strictEqual(derivedZero.hasWildcard(), false);
|
|
129
|
+
const parsedZero = (0, sbtc_1.parseSbtcDepositDescriptor)(derivedZero);
|
|
130
|
+
assert.ok(parsedZero);
|
|
131
|
+
assert.ok(parsedZero.reclaimKeys);
|
|
132
|
+
for (const k of parsedZero.reclaimKeys) {
|
|
133
|
+
assert.strictEqual(k.length, 32, `expected 32-byte x-only key, got ${k.length}`);
|
|
134
|
+
}
|
|
135
|
+
// Deposit-leaf fields are derivation-independent.
|
|
136
|
+
assert.deepStrictEqual(parsedZero.signersAggregateKey, SIGNERS_AGGREGATE_KEY);
|
|
137
|
+
assert.strictEqual(parsedZero.lockTime, sbtc_1.DEFAULT_RECLAIM_LOCK_TIME);
|
|
138
|
+
const parsedOne = (0, sbtc_1.parseSbtcDepositDescriptor)(derivedOne);
|
|
139
|
+
assert.ok(parsedOne?.reclaimKeys);
|
|
140
|
+
assert.notDeepStrictEqual(parsedZero.reclaimKeys, parsedOne.reclaimKeys);
|
|
141
|
+
// The rewritten reclaim leaf carries concrete hex in multi_a, so the
|
|
142
|
+
// formatted string compiles as a tap-context Miniscript. `fromStringExt`
|
|
143
|
+
// is required because the leaf contains the `r:older` (drop) wrapper.
|
|
144
|
+
const reclaimMs = wasm_utxo_1.Miniscript.fromStringExt(wasm_utxo_1.ast.formatNode(parsedZero.reclaimMiniscriptNode), 'tap', {});
|
|
145
|
+
assert.ok(reclaimMs);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe('rejection paths', function () {
|
|
149
|
+
const params = buildParams();
|
|
150
|
+
const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'derivable');
|
|
151
|
+
it('returns null for a non-sBTC descriptor', function () {
|
|
152
|
+
const wpkhDescriptor = wasm_utxo_1.Descriptor.fromString(`wpkh(${getBip32Triple()[0].neutered().toBase58()}/*)`, 'derivable');
|
|
153
|
+
assert.strictEqual((0, sbtc_1.parseSbtcDepositDescriptor)(wpkhDescriptor), null);
|
|
154
|
+
});
|
|
155
|
+
it('returns null for a tr() that has a different internal key', function () {
|
|
156
|
+
// Swap UNSPENDABLE for an arbitrary 32-byte key — pattern match must
|
|
157
|
+
// require the canonical unspendable point, not just any tr().
|
|
158
|
+
const tampered = (0, sbtc_1.createSbtcDepositDescriptor)(buildParams()).replace(sbtc_1.UNSPENDABLE_INTERNAL_KEY, 'a'.repeat(64));
|
|
159
|
+
const node = wasm_utxo_1.ast.fromDescriptor(wasm_utxo_1.Descriptor.fromString(tampered, 'derivable'));
|
|
160
|
+
assert.strictEqual((0, sbtc_1.parseSbtcDepositDescriptor)(node), null);
|
|
161
|
+
});
|
|
162
|
+
it('accepts a pre-extracted ast.DescriptorNode', function () {
|
|
163
|
+
const node = wasm_utxo_1.ast.fromDescriptor(descriptor);
|
|
164
|
+
const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(node);
|
|
165
|
+
assert.ok(parsed);
|
|
166
|
+
assert.strictEqual(parsed.lockTime, sbtc_1.DEFAULT_RECLAIM_LOCK_TIME);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
describe('parameter round-trip', function () {
|
|
170
|
+
it('extracts the same maxFee and recipient that encodeDepositPayload produced', function () {
|
|
171
|
+
const recipient = Buffer.alloc(sbtc_1.STACKS_RECIPIENT_BYTE_LENGTH, 0x11);
|
|
172
|
+
const params = buildParams({ maxFee: 12345n, stacksRecipient: recipient });
|
|
173
|
+
const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'derivable');
|
|
174
|
+
const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
|
|
175
|
+
assert.ok(parsed);
|
|
176
|
+
assert.strictEqual(parsed.maxFee, 12345n);
|
|
177
|
+
assert.deepStrictEqual(parsed.stacksRecipient, recipient);
|
|
178
|
+
});
|
|
179
|
+
it('accepts the full unsigned 64-bit maxFee range', function () {
|
|
180
|
+
const max = 0xffffffffffffffffn;
|
|
181
|
+
const params = buildParams({ maxFee: max });
|
|
182
|
+
const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'derivable');
|
|
183
|
+
const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
|
|
184
|
+
assert.ok(parsed);
|
|
185
|
+
assert.strictEqual(parsed.maxFee, max);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VEZXNjcmlwdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGVzdC91bml0L3NidGMvcGFyc2VEZXNjcmlwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0NBQWlDO0FBRWpDLGdEQUFzRTtBQUN0RSwwREFBMEQ7QUFFMUQsNENBUzJCO0FBSTNCLE1BQU0scUJBQXFCLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxrRUFBa0UsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNySCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBRTNFLFNBQVMsY0FBYztJQUNyQixNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFBLHdCQUFZLEVBQUMsU0FBUyxDQUFDLENBQUM7SUFDdEQsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDL0IsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLFlBQWtELEVBQUU7SUFDdkUsT0FBTztRQUNMLFVBQVUsRUFBRSxjQUFjLEVBQUU7UUFDNUIsUUFBUSxFQUFFLGdDQUF5QjtRQUNuQyxNQUFNLEVBQUUsNkJBQXNCO1FBQzlCLGVBQWUsRUFBRSxnQkFBZ0I7UUFDakMsbUJBQW1CLEVBQUUscUJBQXFCO1FBQzFDLEdBQUcsU0FBUztLQUNiLENBQUM7QUFDSixDQUFDO0FBRUQsUUFBUSxDQUFDLDRCQUE0QixFQUFFO0lBQ3JDLFFBQVEsQ0FBQyxvREFBb0QsRUFBRTtRQUM3RCxNQUFNLGFBQWEsR0FBNkI7WUFDOUMsa0VBQWtFO1lBQ2xFLGtFQUFrRTtZQUNsRSxrRUFBa0U7U0FDbkUsQ0FBQztRQUNG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QyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsK0NBQStDLEVBQUU7WUFDbEQsTUFBTSxHQUFHLEdBQUcsbUJBQW1CLENBQUM7WUFDaEMsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDNUMsTUFBTSxVQUFVLEdBQUcsc0JBQVUsQ0FBQyxVQUFVLENBQUMsSUFBQSxrQ0FBMkIsRUFBQyxNQUFNLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUMzRixNQUFNLE1BQU0sR0FBRyxJQUFBLGlDQUEwQixFQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3RELE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbEIsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3pDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG5pbXBvcnQgeyBhc3QsIGJpcDMyLCBEZXNjcmlwdG9yLCBNaW5pc2NyaXB0IH0gZnJvbSAnQGJpdGdvL3dhc20tdXR4byc7XG5pbXBvcnQgeyBnZXRLZXlUcmlwbGUgfSBmcm9tICdAYml0Z28vd2FzbS11dHhvL3Rlc3R1dGlscyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVNidGNEZXBvc2l0RGVzY3JpcHRvcixcbiAgREVGQVVMVF9NQVhfU0lHTkVSX0ZFRSxcbiAgREVGQVVMVF9SRUNMQUlNX0xPQ0tfVElNRSxcbiAgZW5jb2RlRGVwb3NpdFBheWxvYWQsXG4gIHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yLFxuICBTYnRjRGVwb3NpdERlc2NyaXB0b3JQYXJhbXMsXG4gIFNUQUNLU19SRUNJUElFTlRfQllURV9MRU5HVEgsXG4gIFVOU1BFTkRBQkxFX0lOVEVSTkFMX0tFWSxcbn0gZnJvbSAnLi4vLi4vLi4vc3JjL3NidGMnO1xuXG50eXBlIEJJUDMySW50ZXJmYWNlID0gYmlwMzIuQklQMzJJbnRlcmZhY2U7XG5cbmNvbnN0IFNJR05FUlNfQUdHUkVHQVRFX0tFWSA9IEJ1ZmZlci5mcm9tKCdjOWMyMzEyY2E0MDZkY2I4ZWVkNTBiODI5YjUyOTJmNWZiM2U4NDZkYjBhNTU2YWY2MWNjNTM4MzRjZTc1NDIxJywgJ2hleCcpO1xuY29uc3QgU1RBQ0tTX1JFQ0lQSUVOVCA9IEJ1ZmZlci5mcm9tKCcwNScgKyAnMTYnICsgJzZkJy5yZXBlYXQoMjApLCAnaGV4Jyk7XG5cbmZ1bmN0aW9uIGdldEJpcDMyVHJpcGxlKCk6IFtCSVAzMkludGVyZmFjZSwgQklQMzJJbnRlcmZhY2UsIEJJUDMySW50ZXJmYWNlXSB7XG4gIGNvbnN0IFt1c2VyLCBiYWNrdXAsIGJpdGdvXSA9IGdldEtleVRyaXBsZSgnZGVmYXVsdCcpO1xuICByZXR1cm4gW3VzZXIsIGJhY2t1cCwgYml0Z29dO1xufVxuXG5mdW5jdGlvbiBidWlsZFBhcmFtcyhvdmVycmlkZXM6IFBhcnRpYWw8U2J0Y0RlcG9zaXREZXNjcmlwdG9yUGFyYW1zPiA9IHt9KTogU2J0Y0RlcG9zaXREZXNjcmlwdG9yUGFyYW1zIHtcbiAgcmV0dXJuIHtcbiAgICB3YWxsZXRLZXlzOiBnZXRCaXAzMlRyaXBsZSgpLFxuICAgIGxvY2tUaW1lOiBERUZBVUxUX1JFQ0xBSU1fTE9DS19USU1FLFxuICAgIG1heEZlZTogREVGQVVMVF9NQVhfU0lHTkVSX0ZFRSxcbiAgICBzdGFja3NSZWNpcGllbnQ6IFNUQUNLU19SRUNJUElFTlQsXG4gICAgc2lnbmVyc0FnZ3JlZ2F0ZUtleTogU0lHTkVSU19BR0dSRUdBVEVfS0VZLFxuICAgIC4uLm92ZXJyaWRlcyxcbiAgfTtcbn1cblxuZGVzY3JpYmUoJ3BhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yJywgZnVuY3Rpb24gKCkge1xuICBkZXNjcmliZSgnZGVmaW5pdGUgZGVzY3JpcHRvciAoY29uY3JldGUgeC1vbmx5IHJlY2xhaW0ga2V5cyknLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcmVjbGFpbUtleUhleDogW3N0cmluZywgc3RyaW5nLCBzdHJpbmddID0gW1xuICAgICAgJzRkODM4NzU5YjJhNzQ2MTZhMjI5OGUwNTgwY2E4MTU4NzRmNWU1YTlkMmRkMWIyZjAyMDNiNjhjNjZmYzZjMWUnLFxuICAgICAgJzYzOTc3OWM0YjcwMGRjNTFlY2UwMTJhMGUyMDMyNWZjYWZhZGEyMmE0YTEyMmZmYWEwNGQwYzBjY2FlODM5NDMnLFxuICAgICAgJ2QxZDYwODRlYWM5ODMwM2U5ZDI4ZTA4MmJmZDllYWRmMGI4YmUwMzNlMjIzYTE3YWQwMWRmODFiZGFhOGM3YjInLFxuICAgIF07XG4gICAgY29uc3QgcmVjbGFpbUtleXM6IFtCdWZmZXIsIEJ1ZmZlciwgQnVmZmVyXSA9IFtcbiAgICAgIEJ1ZmZlci5mcm9tKHJlY2xhaW1LZXlIZXhbMF0sICdoZXgnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKHJlY2xhaW1LZXlIZXhbMV0sICdoZXgnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKHJlY2xhaW1LZXlIZXhbMl0sICdoZXgnKSxcbiAgICBdO1xuICAgIGNvbnN0IHBhcmFtczogU2J0Y0RlcG9zaXREZXNjcmlwdG9yUGFyYW1zID0ge1xuICAgICAgd2FsbGV0S2V5czogcmVjbGFpbUtleXMsXG4gICAgICBsb2NrVGltZTogMTQ0LFxuICAgICAgbWF4RmVlOiA4MF8wMDAsXG4gICAgICBzdGFja3NSZWNpcGllbnQ6IFNUQUNLU19SRUNJUElFTlQsXG4gICAgICBzaWduZXJzQWdncmVnYXRlS2V5OiBTSUdORVJTX0FHR1JFR0FURV9LRVksXG4gICAgfTtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKGNyZWF0ZVNidGNEZXBvc2l0RGVzY3JpcHRvcihwYXJhbXMpLCAnZGVmaW5pdGUnKTtcblxuICAgIGl0KCdyb3VuZC10cmlwcyBhbGwgaGlnaC1sZXZlbCBmaWVsZHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihkZXNjcmlwdG9yKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQuc2lnbmVyc0FnZ3JlZ2F0ZUtleSwgU0lHTkVSU19BR0dSRUdBVEVfS0VZKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQubWF4RmVlLCA4MF8wMDBuKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkLnN0YWNrc1JlY2lwaWVudCwgU1RBQ0tTX1JFQ0lQSUVOVCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLmxvY2tUaW1lLCAxNDQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JldHVybnMgcmVjbGFpbSBrZXlzIGFzIDMyLWJ5dGUgYnVmZmVycyBpbiB0aGUgZGVzY3JpcHRvciBvcmRlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZCk7XG4gICAgICBhc3NlcnQub2socGFyc2VkLnJlY2xhaW1LZXlzKTtcbiAgICAgIC8vIG11bHRpX2Egc29ydHMga2V5cyBieSBoZXg7IHZlcmlmeSB0aGUgcGFyc2VyIHJldHVybnMgd2hhdGV2ZXIgb3JkZXJcbiAgICAgIC8vIHRoZSBkZXNjcmlwdG9yIGxpYnJhcnkgcHJvZHVjZWQgcmF0aGVyIHRoYW4gdGhlIG9yaWdpbmFsIGlucHV0IG9yZGVyLlxuICAgICAgY29uc3Qgc29ydGVkSW5wdXQgPSBbLi4ucmVjbGFpbUtleUhleF0uc29ydCgpLm1hcCgoaykgPT4gQnVmZmVyLmZyb20oaywgJ2hleCcpKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkLnJlY2xhaW1LZXlzLCBzb3J0ZWRJbnB1dCk7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyBtaW5pc2NyaXB0IEFTVCBub2RlcyBmb3IgYm90aCBsZWF2ZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihkZXNjcmlwdG9yKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWQpO1xuICAgICAgY29uc3QgcGF5bG9hZEhleCA9IGVuY29kZURlcG9zaXRQYXlsb2FkKHBhcmFtcy5tYXhGZWUsIHBhcmFtcy5zdGFja3NSZWNpcGllbnQpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkLmRlcG9zaXRNaW5pc2NyaXB0Tm9kZSwge1xuICAgICAgICBhbmRfdjogW3sgcGF5bG9hZF9kcm9wOiBwYXlsb2FkSGV4IH0sIHsgcGs6IFNJR05FUlNfQUdHUkVHQVRFX0tFWS50b1N0cmluZygnaGV4JykgfV0sXG4gICAgICB9IGFzIHVua25vd24gYXMgYXN0Lk1pbmlzY3JpcHROb2RlKTtcbiAgICAgIC8vIHI6b2xkZXIgKyBtdWx0aV9hIG11c3QgYmUgcHJlc2VudCBhbmQgY29ycmVjdGx5IG9yZGVyZWQgaW4gdGhlIEFTVC5cbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkLnJlY2xhaW1NaW5pc2NyaXB0Tm9kZSwge1xuICAgICAgICBhbmRfdjogW3sgJ3I6b2xkZXInOiAxNDQgfSwgeyBtdWx0aV9hOiBbMiwgLi4uWy4uLnJlY2xhaW1LZXlIZXhdLnNvcnQoKV0gfV0sXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2Rlcml2YWJsZSBkZXNjcmlwdG9yICh4cHViLyogcmVjbGFpbSBrZXlzKScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBwYXJhbXMgPSBidWlsZFBhcmFtcygpO1xuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBEZXNjcmlwdG9yLmZyb21TdHJpbmcoY3JlYXRlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKHBhcmFtcyksICdkZXJpdmFibGUnKTtcblxuICAgIGl0KCdyb3VuZC10cmlwcyBsb2NrVGltZSwgbWF4RmVlLCByZWNpcGllbnQsIGFuZCBzaWduZXJzIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZCk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZC5zaWduZXJzQWdncmVnYXRlS2V5LCBTSUdORVJTX0FHR1JFR0FURV9LRVkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5tYXhGZWUsIEJpZ0ludChERUZBVUxUX01BWF9TSUdORVJfRkVFKSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZC5zdGFja3NSZWNpcGllbnQsIFNUQUNLU19SRUNJUElFTlQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5sb2NrVGltZSwgREVGQVVMVF9SRUNMQUlNX0xPQ0tfVElNRSk7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyByZWNsYWltS2V5cz11bmRlZmluZWQgZm9yIGRlcml2YWJsZSBpbnB1dHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBEZXJpdmFibGUgZGVzY3JpcHRvcnMgcmVuZGVyIG11bHRpX2EgZW50cmllcyBhcyBgeHB1Yi4uLi8qYCwgbm90IGFzXG4gICAgICAvLyAzMi1ieXRlIGhleCDigJQgdGhleSBjYW4ndCBiZSByZWR1Y2VkIHRvIGJ5dGVzIHdpdGhvdXQgcGlja2luZyBhbiBpbmRleC5cbiAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnJlY2xhaW1LZXlzLCB1bmRlZmluZWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Jlc29sdmVzIHRvIGNvbmNyZXRlIHJlY2xhaW0ga2V5cyBhZnRlciBhdERlcml2YXRpb25JbmRleCgwKSBhbmQgY29tcGlsZXMgdG8gYSB0YXAgTWluaXNjcmlwdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChkZXNjcmlwdG9yLmhhc1dpbGRjYXJkKCksIHRydWUpO1xuICAgICAgY29uc3QgZGVyaXZlZFplcm8gPSBkZXNjcmlwdG9yLmF0RGVyaXZhdGlvbkluZGV4KDApO1xuICAgICAgY29uc3QgZGVyaXZlZE9uZSA9IGRlc2NyaXB0b3IuYXREZXJpdmF0aW9uSW5kZXgoMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZGVyaXZlZFplcm8uaGFzV2lsZGNhcmQoKSwgZmFsc2UpO1xuXG4gICAgICBjb25zdCBwYXJzZWRaZXJvID0gcGFyc2VTYnRjRGVwb3NpdERlc2NyaXB0b3IoZGVyaXZlZFplcm8pO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZFplcm8pO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZFplcm8ucmVjbGFpbUtleXMpO1xuICAgICAgZm9yIChjb25zdCBrIG9mIHBhcnNlZFplcm8ucmVjbGFpbUtleXMpIHtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGsubGVuZ3RoLCAzMiwgYGV4cGVjdGVkIDMyLWJ5dGUgeC1vbmx5IGtleSwgZ290ICR7ay5sZW5ndGh9YCk7XG4gICAgICB9XG4gICAgICAvLyBEZXBvc2l0LWxlYWYgZmllbGRzIGFyZSBkZXJpdmF0aW9uLWluZGVwZW5kZW50LlxuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWRaZXJvLnNpZ25lcnNBZ2dyZWdhdGVLZXksIFNJR05FUlNfQUdHUkVHQVRFX0tFWSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkWmVyby5sb2NrVGltZSwgREVGQVVMVF9SRUNMQUlNX0xPQ0tfVElNRSk7XG5cbiAgICAgIGNvbnN0IHBhcnNlZE9uZSA9IHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKGRlcml2ZWRPbmUpO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZE9uZT8ucmVjbGFpbUtleXMpO1xuICAgICAgYXNzZXJ0Lm5vdERlZXBTdHJpY3RFcXVhbChwYXJzZWRaZXJvLnJlY2xhaW1LZXlzLCBwYXJzZWRPbmUucmVjbGFpbUtleXMpO1xuXG4gICAgICAvLyBUaGUgcmV3cml0dGVuIHJlY2xhaW0gbGVhZiBjYXJyaWVzIGNvbmNyZXRlIGhleCBpbiBtdWx0aV9hLCBzbyB0aGVcbiAgICAgIC8vIGZvcm1hdHRlZCBzdHJpbmcgY29tcGlsZXMgYXMgYSB0YXAtY29udGV4dCBNaW5pc2NyaXB0LiBgZnJvbVN0cmluZ0V4dGBcbiAgICAgIC8vIGlzIHJlcXVpcmVkIGJlY2F1c2UgdGhlIGxlYWYgY29udGFpbnMgdGhlIGByOm9sZGVyYCAoZHJvcCkgd3JhcHBlci5cbiAgICAgIGNvbnN0IHJlY2xhaW1NcyA9IE1pbmlzY3JpcHQuZnJvbVN0cmluZ0V4dChhc3QuZm9ybWF0Tm9kZShwYXJzZWRaZXJvLnJlY2xhaW1NaW5pc2NyaXB0Tm9kZSksICd0YXAnLCB7fSk7XG4gICAgICBhc3NlcnQub2socmVjbGFpbU1zKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3JlamVjdGlvbiBwYXRocycsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBwYXJhbXMgPSBidWlsZFBhcmFtcygpO1xuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBEZXNjcmlwdG9yLmZyb21TdHJpbmcoY3JlYXRlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKHBhcmFtcyksICdkZXJpdmFibGUnKTtcblxuICAgIGl0KCdyZXR1cm5zIG51bGwgZm9yIGEgbm9uLXNCVEMgZGVzY3JpcHRvcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdwa2hEZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKGB3cGtoKCR7Z2V0QmlwMzJUcmlwbGUoKVswXS5uZXV0ZXJlZCgpLnRvQmFzZTU4KCl9LyopYCwgJ2Rlcml2YWJsZScpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKHdwa2hEZXNjcmlwdG9yKSwgbnVsbCk7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyBudWxsIGZvciBhIHRyKCkgdGhhdCBoYXMgYSBkaWZmZXJlbnQgaW50ZXJuYWwga2V5JywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gU3dhcCBVTlNQRU5EQUJMRSBmb3IgYW4gYXJiaXRyYXJ5IDMyLWJ5dGUga2V5IOKAlCBwYXR0ZXJuIG1hdGNoIG11c3RcbiAgICAgIC8vIHJlcXVpcmUgdGhlIGNhbm9uaWNhbCB1bnNwZW5kYWJsZSBwb2ludCwgbm90IGp1c3QgYW55IHRyKCkuXG4gICAgICBjb25zdCB0YW1wZXJlZCA9IGNyZWF0ZVNidGNEZXBvc2l0RGVzY3JpcHRvcihidWlsZFBhcmFtcygpKS5yZXBsYWNlKFVOU1BFTkRBQkxFX0lOVEVSTkFMX0tFWSwgJ2EnLnJlcGVhdCg2NCkpO1xuICAgICAgY29uc3Qgbm9kZSA9IGFzdC5mcm9tRGVzY3JpcHRvcihEZXNjcmlwdG9yLmZyb21TdHJpbmcodGFtcGVyZWQsICdkZXJpdmFibGUnKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VTYnRjRGVwb3NpdERlc2NyaXB0b3Iobm9kZSksIG51bGwpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2FjY2VwdHMgYSBwcmUtZXh0cmFjdGVkIGFzdC5EZXNjcmlwdG9yTm9kZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vZGUgPSBhc3QuZnJvbURlc2NyaXB0b3IoZGVzY3JpcHRvcik7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihub2RlKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5sb2NrVGltZSwgREVGQVVMVF9SRUNMQUlNX0xPQ0tfVElNRSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdwYXJhbWV0ZXIgcm91bmQtdHJpcCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnZXh0cmFjdHMgdGhlIHNhbWUgbWF4RmVlIGFuZCByZWNpcGllbnQgdGhhdCBlbmNvZGVEZXBvc2l0UGF5bG9hZCBwcm9kdWNlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlY2lwaWVudCA9IEJ1ZmZlci5hbGxvYyhTVEFDS1NfUkVDSVBJRU5UX0JZVEVfTEVOR1RILCAweDExKTtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IGJ1aWxkUGFyYW1zKHsgbWF4RmVlOiAxMjM0NW4sIHN0YWNrc1JlY2lwaWVudDogcmVjaXBpZW50IH0pO1xuICAgICAgY29uc3QgZGVzY3JpcHRvciA9IERlc2NyaXB0b3IuZnJvbVN0cmluZyhjcmVhdGVTYnRjRGVwb3NpdERlc2NyaXB0b3IocGFyYW1zKSwgJ2Rlcml2YWJsZScpO1xuICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VTYnRjRGVwb3NpdERlc2NyaXB0b3IoZGVzY3JpcHRvcik7XG4gICAgICBhc3NlcnQub2socGFyc2VkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQubWF4RmVlLCAxMjM0NW4pO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQuc3RhY2tzUmVjaXBpZW50LCByZWNpcGllbnQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2FjY2VwdHMgdGhlIGZ1bGwgdW5zaWduZWQgNjQtYml0IG1heEZlZSByYW5nZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1heCA9IDB4ZmZmZmZmZmZmZmZmZmZmZm47XG4gICAgICBjb25zdCBwYXJhbXMgPSBidWlsZFBhcmFtcyh7IG1heEZlZTogbWF4IH0pO1xuICAgICAgY29uc3QgZGVzY3JpcHRvciA9IERlc2NyaXB0b3IuZnJvbVN0cmluZyhjcmVhdGVTYnRjRGVwb3NpdERlc2NyaXB0b3IocGFyYW1zKSwgJ2Rlcml2YWJsZScpO1xuICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VTYnRjRGVwb3NpdERlc2NyaXB0b3IoZGVzY3JpcHRvcik7XG4gICAgICBhc3NlcnQub2socGFyc2VkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQubWF4RmVlLCBtYXgpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|