@bitgo-beta/utxo-descriptors 0.0.1-beta.9 → 0.0.1-beta.91

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.
@@ -1,4 +1,5 @@
1
1
  export * from './constants';
2
2
  export * from './descriptor';
3
3
  export * from './depositAddress';
4
+ export * from './parseDescriptor';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -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
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2J0Yy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsOENBQTRCO0FBQzVCLCtDQUE2QjtBQUM3QixtREFBaUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2NvbnN0YW50cyc7XG5leHBvcnQgKiBmcm9tICcuL2Rlc2NyaXB0b3InO1xuZXhwb3J0ICogZnJvbSAnLi9kZXBvc2l0QWRkcmVzcyc7XG4iXX0=
20
+ __exportStar(require("./parseDescriptor"), exports);
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2J0Yy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsOENBQTRCO0FBQzVCLCtDQUE2QjtBQUM3QixtREFBaUM7QUFDakMsb0RBQWtDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9jb25zdGFudHMnO1xuZXhwb3J0ICogZnJvbSAnLi9kZXNjcmlwdG9yJztcbmV4cG9ydCAqIGZyb20gJy4vZGVwb3NpdEFkZHJlc3MnO1xuZXhwb3J0ICogZnJvbSAnLi9wYXJzZURlc2NyaXB0b3InO1xuIl19
@@ -0,0 +1,55 @@
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
+ * The three raw `multi_a` key entries from the reclaim leaf, exactly as
35
+ * they appear in the descriptor — `xpub.../*` for derivable descriptors and
36
+ * 64-hex-char x-only keys for definite descriptors. Useful for callers that
37
+ * need the original xpub form (e.g. to round-trip back to a descriptor
38
+ * builder) and don't want the resolved `reclaimKeys` buffers.
39
+ */
40
+ reclaimKeyStrings: [string, string, string];
41
+ };
42
+ /**
43
+ * Parse an sBTC peg-in deposit descriptor and return its components.
44
+ *
45
+ * Returns `null` if the descriptor does not match the expected
46
+ * `tr(<UNSPENDABLE>, {<depositLeaf>, <reclaimLeaf>})` shape — same convention
47
+ * as babylon's `parseStakingDescriptor`. Throws if the shape matches but a
48
+ * sub-field is malformed (e.g. signers key isn't 32 bytes, payload isn't 30
49
+ * bytes, threshold isn't 2).
50
+ *
51
+ * Accepts both the `Descriptor` WASM object (definite or derivable) and a
52
+ * pre-extracted `ast.DescriptorNode`
53
+ */
54
+ export declare function parseSbtcDepositDescriptor(descriptor: Descriptor | ast.DescriptorNode): ParsedSbtcDepositDescriptor | null;
55
+ //# 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;IAC1C;;;;;;OAMG;IACH,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C,CAAC;AAwJF;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,GAAG,GAAG,CAAC,cAAc,GAC1C,2BAA2B,GAAG,IAAI,CA8CpC"}
@@ -0,0 +1,185 @@
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 reclaimKeyStringsTuple = [
159
+ reclaimKeyStrings[0],
160
+ reclaimKeyStrings[1],
161
+ reclaimKeyStrings[2],
162
+ ];
163
+ const reclaimKeys = reclaimKeysFromStrings(reclaimKeyStrings);
164
+ if (reclaimKeys) {
165
+ // Rewrite the reclaim leaf with concrete hex keys when we can resolve
166
+ // them — `Miniscript.fromString(..., 'tap')` only accepts x-only hex in
167
+ // `multi_a`, not xpub-form strings. With this rewrite the formatted
168
+ // leaf is directly compilable; without it callers must do the
169
+ // resolution themselves.
170
+ reclaimMiniscriptNode = {
171
+ and_v: [{ 'r:older': lockTime }, { multi_a: [2, ...reclaimKeys.map((k) => k.toString('hex'))] }],
172
+ };
173
+ }
174
+ return {
175
+ signersAggregateKey,
176
+ maxFee,
177
+ stacksRecipient,
178
+ lockTime,
179
+ reclaimKeys,
180
+ reclaimKeyStrings: reclaimKeyStringsTuple,
181
+ depositMiniscriptNode,
182
+ reclaimMiniscriptNode,
183
+ };
184
+ }
185
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VEZXNjcmlwdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3NidGMvcGFyc2VEZXNjcmlwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBZ05BLGdFQWdEQztBQWhRRCxnREFBMEQ7QUFDMUQsaUVBQTJFO0FBRTNFLDJDQUEwRztBQTJDMUcsU0FBUyxRQUFRLENBQUMsQ0FBVSxFQUFFLEtBQWE7SUFDekMsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsS0FBSyxtQkFBbUIsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFDRCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFRCxTQUFTLFFBQVEsQ0FBQyxDQUFVLEVBQUUsS0FBYTtJQUN6QyxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLG1CQUFtQixDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUNELE9BQU8sQ0FBQyxDQUFDO0FBQ1gsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsVUFBVSxDQUFDLEtBQWM7SUFDaEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM5QyxNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUNELE1BQU0sQ0FBQyxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDbkMsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7SUFDMUUsQ0FBQztJQUNELElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMs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SyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDakcsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPO1FBQ0wsbUJBQW1CO1FBQ25CLE1BQU07UUFDTixlQUFlO1FBQ2YsUUFBUTtRQUNSLFdBQVc7UUFDWCxpQkFBaUIsRUFBRSxzQkFBc0I7UUFDekMscUJBQXFCO1FBQ3JCLHFCQUFxQjtLQUN0QixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJJUDMyLCBEZXNjcmlwdG9yLCBhc3QgfSBmcm9tICdAYml0Z28vd2FzbS11dHhvJztcbmltcG9ydCB7IFBhdHRlcm5NYXRjaGVyLCBQYXR0ZXJuIH0gZnJvbSAnQGJpdGdvLWJldGEvdXR4by1jb3JlL2Rlc2NyaXB0b3InO1xuXG5pbXBvcnQgeyBNQVhfRkVFX0JZVEVfTEVOR1RILCBTVEFDS1NfUkVDSVBJRU5UX0JZVEVfTEVOR1RILCBVTlNQRU5EQUJMRV9JTlRFUk5BTF9LRVkgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbi8qKlxuICogUGFyc2VkIGNvbXBvbmVudHMgb2YgYW4gc0JUQyBwZWctaW4gZGVwb3NpdCBkZXNjcmlwdG9yLlxuICpcbiAqIFRoZSBwYXJzZXIgcmV0dXJucyBib3RoIHRoZSBoaWdoLWxldmVsXG4gKiBmaWVsZHMgY2FsbGVycyB1c3VhbGx5IG5lZWQgKGtleXMsIGxvY2tUaW1lLCBmZWUsIHJlY2lwaWVudCkgYW5kIHRoZSByYXdcbiAqIG1pbmlzY3JpcHQgQVNUIG5vZGVzIHNvIHRoZSBsZWF2ZXMgY2FuIGJlIHJlLWNvbXBpbGVkIGludG8gYVxuICogYE1pbmlzY3JpcHRgIHZpYSBgYXN0LmZvcm1hdE5vZGVgICsgYE1pbmlzY3JpcHQuZnJvbVN0cmluZ2AuXG4gKi9cbmV4cG9ydCB0eXBlIFBhcnNlZFNidGNEZXBvc2l0RGVzY3JpcHRvciA9IHtcbiAgLyoqIDMyLWJ5dGUgeC1vbmx5IHNpZ25lcnMgYWdncmVnYXRlIGtleSBmcm9tIHRoZSBkZXBvc2l0IGxlYWYuICovXG4gIHNpZ25lcnNBZ2dyZWdhdGVLZXk6IEJ1ZmZlcjtcbiAgLyoqIE1heCBzaWduZXIgZmVlIHBhcnNlZCBmcm9tIHRoZSBmaXJzdCA4IGJ5dGVzIG9mIHRoZSBwYXlsb2FkX2Ryb3AgdmFsdWUuICovXG4gIG1heEZlZTogYmlnaW50O1xuICAvKiogMjItYnl0ZSBTdGFja3MgcmVjaXBpZW50IHBhcnNlZCBmcm9tIHRoZSB0cmFpbGluZyBieXRlcyBvZiB0aGUgcGF5bG9hZC4gKi9cbiAgc3RhY2tzUmVjaXBpZW50OiBCdWZmZXI7XG4gIC8qKiBSZWNsYWltLWxlYWYgcmVsYXRpdmUgdGltZWxvY2sgKG51bWJlciBvZiBCaXRjb2luIGJsb2NrcywgT1BfQ1NWIGFyZ3VtZW50KS4gKi9cbiAgbG9ja1RpbWU6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSB0aHJlZSBjb25jcmV0ZSB4LW9ubHkgcmVjbGFpbSBrZXlzIGZyb20gdGhlIHJlY2xhaW0tbGVhZiBgbXVsdGlfYWAsXG4gICAqIGluIHRoZSBvcmRlciB0aGV5IGFwcGVhciBpbnNpZGUgdGhlIGxlYWYgKGRlc2NyaXB0b3IgbGlicmFyeSBzb3J0cyBieSBoZXgpLlxuICAgKiBPbmx5IHByZXNlbnQgd2hlbiB0aGUgZGVzY3JpcHRvciBpcyBpbiBpdHMgZGVyaXZlZC9kZWZpbml0ZSBmb3JtIOKAlCBmb3JcbiAgICogZGVyaXZhYmxlIGRlc2NyaXB0b3JzIHRoZSBtdWx0aV9hIGVudHJpZXMgYXJlIHhwdWIgc3RyaW5ncyAoZS5nLlxuICAgKiBgeHB1Yi4uLi8qYCksIHdoaWNoIGNhbid0IGJlIHR1cm5lZCBpbnRvIDMyLWJ5dGUgYnVmZmVycyB3aXRob3V0IHBpY2tpbmdcbiAgICogYSBkZXJpdmF0aW9uIGluZGV4LiBDYWxsZXJzIHRoYXQgbmVlZCByYXcga2V5IGJ5dGVzIE1VU1QgcGFzcyB0aGVcbiAgICogZGVyaXZlZCBkZXNjcmlwdG9yIChzZWUgYGRlcml2ZVJlY2xhaW1LZXlzYCBmb3IgZGVyaXZhYmxlIGlucHV0cykuXG4gICAqL1xuICByZWNsYWltS2V5czogW0J1ZmZlciwgQnVmZmVyLCBCdWZmZXJdIHwgdW5kZWZpbmVkO1xuICAvKiogUmF3IG1pbmlzY3JpcHQgQVNUIGZvciB0aGUgZGVwb3NpdCBsZWFmIChmaXJzdCB0YXAtdHJlZSBsZWFmKS4gKi9cbiAgZGVwb3NpdE1pbmlzY3JpcHROb2RlOiBhc3QuTWluaXNjcmlwdE5vZGU7XG4gIC8qKiBSYXcgbWluaXNjcmlwdCBBU1QgZm9yIHRoZSByZWNsYWltIGxlYWYgKHNlY29uZCB0YXAtdHJlZSBsZWFmKS4gKi9cbiAgcmVjbGFpbU1pbmlzY3JpcHROb2RlOiBhc3QuTWluaXNjcmlwdE5vZGU7XG4gIC8qKlxuICAgKiBUaGUgdGhyZWUgcmF3IGBtdWx0aV9hYCBrZXkgZW50cmllcyBmcm9tIHRoZSByZWNsYWltIGxlYWYsIGV4YWN0bHkgYXNcbiAgICogdGhleSBhcHBlYXIgaW4gdGhlIGRlc2NyaXB0b3Ig4oCUIGB4cHViLi4uLypgIGZvciBkZXJpdmFibGUgZGVzY3JpcHRvcnMgYW5kXG4gICAqIDY0LWhleC1jaGFyIHgtb25seSBrZXlzIGZvciBkZWZpbml0ZSBkZXNjcmlwdG9ycy4gVXNlZnVsIGZvciBjYWxsZXJzIHRoYXRcbiAgICogbmVlZCB0aGUgb3JpZ2luYWwgeHB1YiBmb3JtIChlLmcuIHRvIHJvdW5kLXRyaXAgYmFjayB0byBhIGRlc2NyaXB0b3JcbiAgICogYnVpbGRlcikgYW5kIGRvbid0IHdhbnQgdGhlIHJlc29sdmVkIGByZWNsYWltS2V5c2AgYnVmZmVycy5cbiAgICovXG4gIHJlY2xhaW1LZXlTdHJpbmdzOiBbc3RyaW5nLCBzdHJpbmcsIHN0cmluZ107XG59O1xuXG5mdW5jdGlvbiBhc1N0cmluZyh2OiB1bmtub3duLCBmaWVsZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiB2ICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtmaWVsZH0gbXVzdCBiZSBhIHN0cmluZ2ApO1xuICB9XG4gIHJldHVybiB2O1xufVxuXG5mdW5jdGlvbiBhc051bWJlcih2OiB1bmtub3duLCBmaWVsZDogc3RyaW5nKTogbnVtYmVyIHtcbiAgaWYgKHR5cGVvZiB2ICE9PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtmaWVsZH0gbXVzdCBiZSBhIG51bWJlcmApO1xuICB9XG4gIHJldHVybiB2O1xufVxuXG4vKipcbiAqIFB1bGwgYFt0aHJlc2hvbGQsIC4uLmtleXNdYCBvdXQgb2YgYSBgbXVsdGlfYWAgQVNUIG5vZGUgdmFsdWUsIHZhbGlkYXRpbmdcbiAqIGVhY2ggZWxlbWVudC4gVGhlIGRlc2NyaXB0b3IncyBgbXVsdGlfYWAgaXMgcmVuZGVyZWQgd2l0aCBrZXlzIGVpdGhlciBhc1xuICogY29uY3JldGUgaGV4IChkZWZpbml0ZSBkZXNjcmlwdG9yKSBvciBhcyB4cHViIHN0cmluZ3MgZW5kaW5nIGluIGAvKmBcbiAqIChkZXJpdmFibGUgZGVzY3JpcHRvcikg4oCUIGJvdGggYXJlIHN0cmluZ3MgaGVyZSwgc28gd2UgZG9uJ3QgdHJ5IHRvIGNvbnZlcnRcbiAqIHRvIEJ1ZmZlciBhdCB0aGlzIGxldmVsLlxuICovXG5mdW5jdGlvbiBwYXJzZU11bHRpKG11bHRpOiB1bmtub3duKTogW251bWJlciwgc3RyaW5nW11dIHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KG11bHRpKSB8fCBtdWx0aS5sZW5ndGggPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG11bHRpX2Egc3RydWN0dXJlOiBub3QgYW4gYXJyYXkgb3IgZW1wdHknKTtcbiAgfVxuICBjb25zdCBbdGhyZXNob2xkLCAuLi5rZXlzXSA9IG11bHRpO1xuICBpZiAodHlwZW9mIHRocmVzaG9sZCAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgbXVsdGlfYSBzdHJ1Y3R1cmU6IHRocmVzaG9sZCBpcyBub3QgYSBudW1iZXInKTtcbiAgfVxuICBpZiAoIWtleXMuZXZlcnkoKGspID0+IHR5cGVvZiBrID09PSAnc3RyaW5nJykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgbXVsdGlfYSBzdHJ1Y3R1cmU6IG5vdCBhbGwga2V5cyBhcmUgc3RyaW5ncycpO1xuICB9XG4gIHJldHVybiBbdGhyZXNob2xkLCBrZXlzXTtcbn1cblxuZnVuY3Rpb24gcGFyc2VEZXBvc2l0TGVhZihcbiAgZGVwb3NpdE5vZGU6IGFzdC5NaW5pc2NyaXB0Tm9kZSxcbiAgbWF0Y2hlcjogUGF0dGVybk1hdGNoZXJcbik6IHsgc2lnbmVyc0FnZ3JlZ2F0ZUtleTogQnVmZmVyOyBtYXhGZWU6IGJpZ2ludDsgc3RhY2tzUmVjaXBpZW50OiBCdWZmZXIgfSB7XG4gIGNvbnN0IGRlcG9zaXRQYXR0ZXJuOiBQYXR0ZXJuID0ge1xuICAgIGFuZF92OiBbeyBwYXlsb2FkX2Ryb3A6IHsgJHZhcjogJ3BheWxvYWRIZXgnIH0gfSwgeyBwazogeyAkdmFyOiAnc2lnbmVyc0tleScgfSB9XSxcbiAgfTtcbiAgY29uc3QgbWF0Y2ggPSBtYXRjaGVyLm1hdGNoKGRlcG9zaXROb2RlLCBkZXBvc2l0UGF0dGVybik7XG4gIGlmICghbWF0Y2gpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0RlcG9zaXQgbGVhZiBkb2VzIG5vdCBtYXRjaCBleHBlY3RlZCBwYXR0ZXJuJyk7XG4gIH1cblxuICBjb25zdCBwYXlsb2FkSGV4ID0gYXNTdHJpbmcobWF0Y2gucGF5bG9hZEhleCwgJ3BheWxvYWRfZHJvcCB2YWx1ZScpO1xuICBjb25zdCBzaWduZXJzS2V5SGV4ID0gYXNTdHJpbmcobWF0Y2guc2lnbmVyc0tleSwgJ3BrX2sga2V5Jyk7XG5cbiAgY29uc3QgZXhwZWN0ZWRQYXlsb2FkTGVuZ3RoID0gTUFYX0ZFRV9CWVRFX0xFTkdUSCArIFNUQUNLU19SRUNJUElFTlRfQllURV9MRU5HVEg7XG4gIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuZnJvbShwYXlsb2FkSGV4LCAnaGV4Jyk7XG4gIGlmIChwYXlsb2FkLmxlbmd0aCAhPT0gZXhwZWN0ZWRQYXlsb2FkTGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYHBheWxvYWRfZHJvcCB2YWx1ZSBtdXN0IGJlICR7ZXhwZWN0ZWRQYXlsb2FkTGVuZ3RofSBieXRlcyAoJHtleHBlY3RlZFBheWxvYWRMZW5ndGggKiAyfSBoZXggY2hhcnMpLCBnb3QgJHtcbiAgICAgICAgcGF5bG9hZC5sZW5ndGhcbiAgICAgIH0gYnl0ZXNgXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IG1heEZlZSA9IHBheWxvYWQucmVhZEJpZ1VJbnQ2NEJFKDApO1xuICBjb25zdCBzdGFja3NSZWNpcGllbnQgPSBwYXlsb2FkLnN1YmFycmF5KE1BWF9GRUVfQllURV9MRU5HVEgpO1xuXG4gIGNvbnN0IHNpZ25lcnNBZ2dyZWdhdGVLZXkgPSBCdWZmZXIuZnJvbShzaWduZXJzS2V5SGV4LCAnaGV4Jyk7XG4gIGlmIChzaWduZXJzQWdncmVnYXRlS2V5Lmxlbmd0aCAhPT0gMzIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHNpZ25lcnNBZ2dyZWdhdGVLZXkgbXVzdCBiZSAzMiBieXRlcyB4LW9ubHksIGdvdCAke3NpZ25lcnNBZ2dyZWdhdGVLZXkubGVuZ3RofWApO1xuICB9XG5cbiAgcmV0dXJuIHsgc2lnbmVyc0FnZ3JlZ2F0ZUtleSwgbWF4RmVlLCBzdGFja3NSZWNpcGllbnQgfTtcbn1cblxuZnVuY3Rpb24gcGFyc2VSZWNsYWltTGVhZihcbiAgcmVjbGFpbU5vZGU6IGFzdC5NaW5pc2NyaXB0Tm9kZSxcbiAgbWF0Y2hlcjogUGF0dGVybk1hdGNoZXJcbik6IHsgbG9ja1RpbWU6IG51bWJlcjsgcmVjbGFpbUtleVN0cmluZ3M6IHN0cmluZ1tdIH0ge1xuICAvLyBhbmRfdihyOm9sZGVyKDxsb2NrVGltZT4pLCBtdWx0aV9hKDIsIGsxLCBrMiwgazMpKVxuICBjb25zdCByZWNsYWltUGF0dGVybjogUGF0dGVybiA9IHtcbiAgICBhbmRfdjogW3sgJ3I6b2xkZXInOiB7ICR2YXI6ICdsb2NrVGltZScgfSB9LCB7IG11bHRpX2E6IHsgJHZhcjogJ3JlY2xhaW1NdWx0aScgfSB9XSxcbiAgfTtcbiAgY29uc3QgbWF0Y2ggPSBtYXRjaGVyLm1hdGNoKHJlY2xhaW1Ob2RlLCByZWNsYWltUGF0dGVybik7XG4gIGlmICghbWF0Y2gpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlY2xhaW0gbGVhZiBkb2VzIG5vdCBtYXRjaCBleHBlY3RlZCBwYXR0ZXJuJyk7XG4gIH1cblxuICBjb25zdCBsb2NrVGltZSA9IGFzTnVtYmVyKG1hdGNoLmxvY2tUaW1lLCAncjpvbGRlciBhcmd1bWVudCcpO1xuICBpZiAobG9ja1RpbWUgPD0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgcmVjbGFpbSBsb2NrVGltZSBtdXN0IGJlID4gMCwgZ290ICR7bG9ja1RpbWV9YCk7XG4gIH1cblxuICBjb25zdCBbdGhyZXNob2xkLCByZWNsYWltS2V5U3RyaW5nc10gPSBwYXJzZU11bHRpKG1hdGNoLnJlY2xhaW1NdWx0aSk7XG4gIGlmICh0aHJlc2hvbGQgIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHJlY2xhaW0gbXVsdGlfYSB0aHJlc2hvbGQgbXVzdCBiZSAyLCBnb3QgJHt0aHJlc2hvbGR9YCk7XG4gIH1cbiAgaWYgKHJlY2xhaW1LZXlTdHJpbmdzLmxlbmd0aCAhPT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcihgcmVjbGFpbSBtdWx0aV9hIG11c3QgaGF2ZSBleGFjdGx5IDMga2V5cywgZ290ICR7cmVjbGFpbUtleVN0cmluZ3MubGVuZ3RofWApO1xuICB9XG5cbiAgcmV0dXJuIHsgbG9ja1RpbWUsIHJlY2xhaW1LZXlTdHJpbmdzIH07XG59XG5cbmNvbnN0IEhFWF9YX09OTFlfS0VZID0gL15bMC05YS1mQS1GXXs2NH0kLztcbmNvbnN0IFhQVUJfV0lUSF9JTkRFWCA9IC9eKFsxLTlBLUhKLU5QLVphLWttLXpdKylcXC8oXFxkKykkLztcblxuLyoqXG4gKiBSZXNvbHZlIGEgc2luZ2xlIGBtdWx0aV9hYCBrZXkgZW50cnkgdG8gYSAzMi1ieXRlIHgtb25seSBwdWJsaWMga2V5LlxuICpcbiAqIEFjY2VwdHM6XG4gKiAgIC0gNjQtaGV4LWNoYXIgc3RyaW5nIOKGkiByZXR1cm5lZCBhcy1pcyAoYWxyZWFkeSB4LW9ubHkpXG4gKiAgIC0gYHhwdWIuLi4vPGluZGV4PmAg4oaSIEJJUDMyLWRlcml2ZSBhdCB0aGF0IGluZGV4IGFuZCBkcm9wIHRoZSBwcmVmaXggYnl0ZVxuICpcbiAqIFJldHVybnMgbnVsbCBmb3IgYW55IG90aGVyIHNoYXBlIChlLmcuIHdpbGRjYXJkIGB4cHViLi4uLypgLCBtYWxmb3JtZWQgaW5wdXQpLlxuICovXG5mdW5jdGlvbiByZXNvbHZlUmVjbGFpbUtleShzOiBzdHJpbmcpOiBCdWZmZXIgfCBudWxsIHtcbiAgaWYgKEhFWF9YX09OTFlfS0VZLnRlc3QocykpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20ocywgJ2hleCcpO1xuICB9XG4gIGNvbnN0IG0gPSBzLm1hdGNoKFhQVUJfV0lUSF9JTkRFWCk7XG4gIGlmICghbSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IFssIHhwdWIsIGluZGV4U3RyXSA9IG07XG4gIGNvbnN0IGluZGV4ID0gTnVtYmVyLnBhcnNlSW50KGluZGV4U3RyLCAxMCk7XG4gIGlmICghTnVtYmVyLmlzRmluaXRlKGluZGV4KSB8fCBpbmRleCA8IDApIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBsZXQgbm9kZTtcbiAgdHJ5IHtcbiAgICBub2RlID0gQklQMzIuZnJvbUJhc2U1OCh4cHViKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgLy8gQklQMzIgcHVibGljIGtleSBpcyAzMyBieXRlcyAoMSBwcmVmaXggKyAzMiB4LW9ubHkpLiBEcm9wIHRoZSBwcmVmaXguXG4gIHJldHVybiBCdWZmZXIuZnJvbShub2RlLmRlcml2ZShpbmRleCkucHVibGljS2V5LnN1YmFycmF5KDEpKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IHJlY2xhaW0tbGVhZiBrZXkgc3RyaW5ncyBpbnRvIDMyLWJ5dGUgeC1vbmx5IGJ1ZmZlcnMuIEFjY2VwdHMgYm90aFxuICogdGhlIGRlZmluaXRlL2Rlcml2ZWQgZm9ybSAoY29uY3JldGUgNjQtaGV4LWNoYXIgeC1vbmx5IGtleXMpIGFuZCB0aGUgZm9ybVxuICogcHJvZHVjZWQgYnkgYERlc2NyaXB0b3IuYXREZXJpdmF0aW9uSW5kZXgobilgIChgeHB1Yi4uLi88bj5gKS4gUmV0dXJuc1xuICogdW5kZWZpbmVkIGlmIGFueSBlbnRyeSBpcyBzdGlsbCB3aWxkY2FyZCAoYHhwdWIuLi4vKmApIG9yIG90aGVyd2lzZVxuICogdW5yZXNvbHZhYmxlLlxuICovXG5mdW5jdGlvbiByZWNsYWltS2V5c0Zyb21TdHJpbmdzKGtleVN0cmluZ3M6IHN0cmluZ1tdKTogW0J1ZmZlciwgQnVmZmVyLCBCdWZmZXJdIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcmVzb2x2ZWQgPSBrZXlTdHJpbmdzLm1hcChyZXNvbHZlUmVjbGFpbUtleSk7XG4gIGlmIChyZXNvbHZlZC5zb21lKChiKSA9PiBiID09PSBudWxsKSB8fCByZXNvbHZlZC5sZW5ndGggIT09IDMpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiBbcmVzb2x2ZWRbMF0gYXMgQnVmZmVyLCByZXNvbHZlZFsxXSBhcyBCdWZmZXIsIHJlc29sdmVkWzJdIGFzIEJ1ZmZlcl07XG59XG5cbi8qKlxuICogUGFyc2UgYW4gc0JUQyBwZWctaW4gZGVwb3NpdCBkZXNjcmlwdG9yIGFuZCByZXR1cm4gaXRzIGNvbXBvbmVudHMuXG4gKlxuICogUmV0dXJucyBgbnVsbGAgaWYgdGhlIGRlc2NyaXB0b3IgZG9lcyBub3QgbWF0Y2ggdGhlIGV4cGVjdGVkXG4gKiBgdHIoPFVOU1BFTkRBQkxFPiwgezxkZXBvc2l0TGVhZj4sIDxyZWNsYWltTGVhZj59KWAgc2hhcGUg4oCUIHNhbWUgY29udmVudGlvblxuICogYXMgYmFieWxvbidzIGBwYXJzZVN0YWtpbmdEZXNjcmlwdG9yYC4gVGhyb3dzIGlmIHRoZSBzaGFwZSBtYXRjaGVzIGJ1dCBhXG4gKiBzdWItZmllbGQgaXMgbWFsZm9ybWVkIChlLmcuIHNpZ25lcnMga2V5IGlzbid0IDMyIGJ5dGVzLCBwYXlsb2FkIGlzbid0IDMwXG4gKiBieXRlcywgdGhyZXNob2xkIGlzbid0IDIpLlxuICpcbiAqIEFjY2VwdHMgYm90aCB0aGUgYERlc2NyaXB0b3JgIFdBU00gb2JqZWN0IChkZWZpbml0ZSBvciBkZXJpdmFibGUpIGFuZCBhXG4gKiBwcmUtZXh0cmFjdGVkIGBhc3QuRGVzY3JpcHRvck5vZGVgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihcbiAgZGVzY3JpcHRvcjogRGVzY3JpcHRvciB8IGFzdC5EZXNjcmlwdG9yTm9kZVxuKTogUGFyc2VkU2J0Y0RlcG9zaXREZXNjcmlwdG9yIHwgbnVsbCB7XG4gIGNvbnN0IHBhdHRlcm46IFBhdHRlcm4gPSB7XG4gICAgdHI6IFtVTlNQRU5EQUJMRV9JTlRFUk5BTF9LRVksIFt7ICR2YXI6ICdkZXBvc2l0TGVhZicgfSwgeyAkdmFyOiAncmVjbGFpbUxlYWYnIH1dXSxcbiAgfTtcblxuICBjb25zdCBtYXRjaGVyID0gbmV3IFBhdHRlcm5NYXRjaGVyKCk7XG4gIGNvbnN0IGRlc2NyaXB0b3JOb2RlID0gZGVzY3JpcHRvciBpbnN0YW5jZW9mIERlc2NyaXB0b3IgPyBhc3QuZnJvbURlc2NyaXB0b3IoZGVzY3JpcHRvcikgOiBkZXNjcmlwdG9yO1xuICBjb25zdCByZXN1bHQgPSBtYXRjaGVyLm1hdGNoKGRlc2NyaXB0b3JOb2RlLCBwYXR0ZXJuKTtcblxuICBpZiAoIXJlc3VsdCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgZGVwb3NpdE1pbmlzY3JpcHROb2RlID0gcmVzdWx0LmRlcG9zaXRMZWFmIGFzIGFzdC5NaW5pc2NyaXB0Tm9kZTtcbiAgbGV0IHJlY2xhaW1NaW5pc2NyaXB0Tm9kZSA9IHJlc3VsdC5yZWNsYWltTGVhZiBhcyBhc3QuTWluaXNjcmlwdE5vZGU7XG5cbiAgY29uc3QgeyBzaWduZXJzQWdncmVnYXRlS2V5LCBtYXhGZWUsIHN0YWNrc1JlY2lwaWVudCB9ID0gcGFyc2VEZXBvc2l0TGVhZihkZXBvc2l0TWluaXNjcmlwdE5vZGUsIG1hdGNoZXIpO1xuICBjb25zdCB7IGxvY2tUaW1lLCByZWNsYWltS2V5U3RyaW5ncyB9ID0gcGFyc2VSZWNsYWltTGVhZihyZWNsYWltTWluaXNjcmlwdE5vZGUsIG1hdGNoZXIpO1xuICBjb25zdCByZWNsYWltS2V5U3RyaW5nc1R1cGxlOiBbc3RyaW5nLCBzdHJpbmcsIHN0cmluZ10gPSBbXG4gICAgcmVjbGFpbUtleVN0cmluZ3NbMF0sXG4gICAgcmVjbGFpbUtleVN0cmluZ3NbMV0sXG4gICAgcmVjbGFpbUtleVN0cmluZ3NbMl0sXG4gIF07XG5cbiAgY29uc3QgcmVjbGFpbUtleXMgPSByZWNsYWltS2V5c0Zyb21TdHJpbmdzKHJlY2xhaW1LZXlTdHJpbmdzKTtcbiAgaWYgKHJlY2xhaW1LZXlzKSB7XG4gICAgLy8gUmV3cml0ZSB0aGUgcmVjbGFpbSBsZWFmIHdpdGggY29uY3JldGUgaGV4IGtleXMgd2hlbiB3ZSBjYW4gcmVzb2x2ZVxuICAgIC8vIHRoZW0g4oCUIGBNaW5pc2NyaXB0LmZyb21TdHJpbmcoLi4uLCAndGFwJylgIG9ubHkgYWNjZXB0cyB4LW9ubHkgaGV4IGluXG4gICAgLy8gYG11bHRpX2FgLCBub3QgeHB1Yi1mb3JtIHN0cmluZ3MuIFdpdGggdGhpcyByZXdyaXRlIHRoZSBmb3JtYXR0ZWRcbiAgICAvLyBsZWFmIGlzIGRpcmVjdGx5IGNvbXBpbGFibGU7IHdpdGhvdXQgaXQgY2FsbGVycyBtdXN0IGRvIHRoZVxuICAgIC8vIHJlc29sdXRpb24gdGhlbXNlbHZlcy5cbiAgICByZWNsYWltTWluaXNjcmlwdE5vZGUgPSB7XG4gICAgICBhbmRfdjogW3sgJ3I6b2xkZXInOiBsb2NrVGltZSB9LCB7IG11bHRpX2E6IFsyLCAuLi5yZWNsYWltS2V5cy5tYXAoKGspID0+IGsudG9TdHJpbmcoJ2hleCcpKV0gfV0sXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgc2lnbmVyc0FnZ3JlZ2F0ZUtleSxcbiAgICBtYXhGZWUsXG4gICAgc3RhY2tzUmVjaXBpZW50LFxuICAgIGxvY2tUaW1lLFxuICAgIHJlY2xhaW1LZXlzLFxuICAgIHJlY2xhaW1LZXlTdHJpbmdzOiByZWNsYWltS2V5U3RyaW5nc1R1cGxlLFxuICAgIGRlcG9zaXRNaW5pc2NyaXB0Tm9kZSxcbiAgICByZWNsYWltTWluaXNjcmlwdE5vZGUsXG4gIH07XG59XG4iXX0=
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parseDescriptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseDescriptor.d.ts","sourceRoot":"","sources":["../../../../../test/unit/sbtc/parseDescriptor.ts"],"names":[],"mappings":""}
@@ -0,0 +1,202 @@
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('exposes raw hex reclaimKeyStrings for definite inputs', function () {
94
+ const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
95
+ assert.ok(parsed);
96
+ assert.deepStrictEqual(parsed.reclaimKeyStrings, [...reclaimKeyHex].sort());
97
+ });
98
+ it('returns miniscript AST nodes for both leaves', function () {
99
+ const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
100
+ assert.ok(parsed);
101
+ const payloadHex = (0, sbtc_1.encodeDepositPayload)(params.maxFee, params.stacksRecipient).toString('hex');
102
+ assert.deepStrictEqual(parsed.depositMiniscriptNode, {
103
+ and_v: [{ payload_drop: payloadHex }, { pk: SIGNERS_AGGREGATE_KEY.toString('hex') }],
104
+ });
105
+ // r:older + multi_a must be present and correctly ordered in the AST.
106
+ assert.deepStrictEqual(parsed.reclaimMiniscriptNode, {
107
+ and_v: [{ 'r:older': 144 }, { multi_a: [2, ...[...reclaimKeyHex].sort()] }],
108
+ });
109
+ });
110
+ });
111
+ describe('derivable descriptor (xpub/* reclaim keys)', function () {
112
+ const params = buildParams();
113
+ const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'derivable');
114
+ it('round-trips lockTime, maxFee, recipient, and signers key', function () {
115
+ const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
116
+ assert.ok(parsed);
117
+ assert.deepStrictEqual(parsed.signersAggregateKey, SIGNERS_AGGREGATE_KEY);
118
+ assert.strictEqual(parsed.maxFee, BigInt(sbtc_1.DEFAULT_MAX_SIGNER_FEE));
119
+ assert.deepStrictEqual(parsed.stacksRecipient, STACKS_RECIPIENT);
120
+ assert.strictEqual(parsed.lockTime, sbtc_1.DEFAULT_RECLAIM_LOCK_TIME);
121
+ });
122
+ it('returns reclaimKeys=undefined for derivable inputs', function () {
123
+ // Derivable descriptors render multi_a entries as `xpub.../*`, not as
124
+ // 32-byte hex — they can't be reduced to bytes without picking an index.
125
+ const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
126
+ assert.ok(parsed);
127
+ assert.strictEqual(parsed.reclaimKeys, undefined);
128
+ });
129
+ it('exposes the raw xpub.../* reclaimKeyStrings for derivable inputs', function () {
130
+ const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
131
+ assert.ok(parsed);
132
+ assert.strictEqual(parsed.reclaimKeyStrings.length, 3);
133
+ for (const k of parsed.reclaimKeyStrings) {
134
+ assert.match(k, /^xpub[1-9A-HJ-NP-Za-km-z]+\/\*$/);
135
+ }
136
+ });
137
+ it('resolves to concrete reclaim keys after atDerivationIndex(0) and compiles to a tap Miniscript', function () {
138
+ assert.strictEqual(descriptor.hasWildcard(), true);
139
+ const derivedZero = descriptor.atDerivationIndex(0);
140
+ const derivedOne = descriptor.atDerivationIndex(1);
141
+ assert.strictEqual(derivedZero.hasWildcard(), false);
142
+ const parsedZero = (0, sbtc_1.parseSbtcDepositDescriptor)(derivedZero);
143
+ assert.ok(parsedZero);
144
+ assert.ok(parsedZero.reclaimKeys);
145
+ for (const k of parsedZero.reclaimKeys) {
146
+ assert.strictEqual(k.length, 32, `expected 32-byte x-only key, got ${k.length}`);
147
+ }
148
+ // Deposit-leaf fields are derivation-independent.
149
+ assert.deepStrictEqual(parsedZero.signersAggregateKey, SIGNERS_AGGREGATE_KEY);
150
+ assert.strictEqual(parsedZero.lockTime, sbtc_1.DEFAULT_RECLAIM_LOCK_TIME);
151
+ const parsedOne = (0, sbtc_1.parseSbtcDepositDescriptor)(derivedOne);
152
+ assert.ok(parsedOne?.reclaimKeys);
153
+ assert.notDeepStrictEqual(parsedZero.reclaimKeys, parsedOne.reclaimKeys);
154
+ // The rewritten reclaim leaf carries concrete hex in multi_a, so the
155
+ // formatted string compiles as a tap-context Miniscript. `fromStringExt`
156
+ // is required because the leaf contains the `r:older` (drop) wrapper.
157
+ const reclaimMs = wasm_utxo_1.Miniscript.fromStringExt(wasm_utxo_1.ast.formatNode(parsedZero.reclaimMiniscriptNode), 'tap', {});
158
+ assert.ok(reclaimMs);
159
+ });
160
+ });
161
+ describe('rejection paths', function () {
162
+ const params = buildParams();
163
+ const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'derivable');
164
+ it('returns null for a non-sBTC descriptor', function () {
165
+ const wpkhDescriptor = wasm_utxo_1.Descriptor.fromString(`wpkh(${getBip32Triple()[0].neutered().toBase58()}/*)`, 'derivable');
166
+ assert.strictEqual((0, sbtc_1.parseSbtcDepositDescriptor)(wpkhDescriptor), null);
167
+ });
168
+ it('returns null for a tr() that has a different internal key', function () {
169
+ // Swap UNSPENDABLE for an arbitrary 32-byte key — pattern match must
170
+ // require the canonical unspendable point, not just any tr().
171
+ const tampered = (0, sbtc_1.createSbtcDepositDescriptor)(buildParams()).replace(sbtc_1.UNSPENDABLE_INTERNAL_KEY, 'a'.repeat(64));
172
+ const node = wasm_utxo_1.ast.fromDescriptor(wasm_utxo_1.Descriptor.fromString(tampered, 'derivable'));
173
+ assert.strictEqual((0, sbtc_1.parseSbtcDepositDescriptor)(node), null);
174
+ });
175
+ it('accepts a pre-extracted ast.DescriptorNode', function () {
176
+ const node = wasm_utxo_1.ast.fromDescriptor(descriptor);
177
+ const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(node);
178
+ assert.ok(parsed);
179
+ assert.strictEqual(parsed.lockTime, sbtc_1.DEFAULT_RECLAIM_LOCK_TIME);
180
+ });
181
+ });
182
+ describe('parameter round-trip', function () {
183
+ it('extracts the same maxFee and recipient that encodeDepositPayload produced', function () {
184
+ const recipient = Buffer.alloc(sbtc_1.STACKS_RECIPIENT_BYTE_LENGTH, 0x11);
185
+ const params = buildParams({ maxFee: 12345n, stacksRecipient: recipient });
186
+ const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'derivable');
187
+ const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
188
+ assert.ok(parsed);
189
+ assert.strictEqual(parsed.maxFee, 12345n);
190
+ assert.deepStrictEqual(parsed.stacksRecipient, recipient);
191
+ });
192
+ it('accepts the full unsigned 64-bit maxFee range', function () {
193
+ const max = 0xffffffffffffffffn;
194
+ const params = buildParams({ maxFee: max });
195
+ const descriptor = wasm_utxo_1.Descriptor.fromString((0, sbtc_1.createSbtcDepositDescriptor)(params), 'derivable');
196
+ const parsed = (0, sbtc_1.parseSbtcDepositDescriptor)(descriptor);
197
+ assert.ok(parsed);
198
+ assert.strictEqual(parsed.maxFee, max);
199
+ });
200
+ });
201
+ });
202
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VEZXNjcmlwdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGVzdC91bml0L3NidGMvcGFyc2VEZXNjcmlwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0NBQWlDO0FBRWpDLGdEQUFzRTtBQUN0RSwwREFBMEQ7QUFFMUQsNENBUzJCO0FBSTNCLE1BQU0scUJBQXFCLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxrRUFBa0UsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNySCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBRTNFLFNBQVMsY0FBYztJQUNyQixNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFBLHdCQUFZLEVBQUMsU0FBUyxDQUFDLENBQUM7SUFDdEQsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDL0IsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLFlBQWtELEVBQUU7SUFDdkUsT0FBTztRQUNMLFVBQVUsRUFBRSxjQUFjLEVBQUU7UUFDNUIsUUFBUSxFQUFFLGdDQUF5QjtRQUNuQyxNQUFNLEVBQUUsNkJBQXNCO1FBQzlCLGVBQWUsRUFBRSxnQkFBZ0I7UUFDakMsbUJBQW1CLEVBQUUscUJBQXFCO1FBQzFDLEdBQUcsU0FBUztLQUNiLENBQUM7QUFDSixDQUFDO0FBRUQsUUFBUSxDQUFDLDRCQUE0QixFQUFFO0lBQ3JDLFFBQVEsQ0FBQyxvREFBb0QsRUFBRTtRQUM3RCxNQUFNLGFBQWEsR0FBNkI7WUFDOUMsa0VBQWtFO1lBQ2xFLGtFQUFrRTtZQUNsRSxrRUFBa0U7U0FDbkUsQ0FBQztRQUNG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QUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3pDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG5pbXBvcnQgeyBhc3QsIGJpcDMyLCBEZXNjcmlwdG9yLCBNaW5pc2NyaXB0IH0gZnJvbSAnQGJpdGdvL3dhc20tdXR4byc7XG5pbXBvcnQgeyBnZXRLZXlUcmlwbGUgfSBmcm9tICdAYml0Z28vd2FzbS11dHhvL3Rlc3R1dGlscyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVNidGNEZXBvc2l0RGVzY3JpcHRvcixcbiAgREVGQVVMVF9NQVhfU0lHTkVSX0ZFRSxcbiAgREVGQVVMVF9SRUNMQUlNX0xPQ0tfVElNRSxcbiAgZW5jb2RlRGVwb3NpdFBheWxvYWQsXG4gIHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yLFxuICBTYnRjRGVwb3NpdERlc2NyaXB0b3JQYXJhbXMsXG4gIFNUQUNLU19SRUNJUElFTlRfQllURV9MRU5HVEgsXG4gIFVOU1BFTkRBQkxFX0lOVEVSTkFMX0tFWSxcbn0gZnJvbSAnLi4vLi4vLi4vc3JjL3NidGMnO1xuXG50eXBlIEJJUDMySW50ZXJmYWNlID0gYmlwMzIuQklQMzJJbnRlcmZhY2U7XG5cbmNvbnN0IFNJR05FUlNfQUdHUkVHQVRFX0tFWSA9IEJ1ZmZlci5mcm9tKCdjOWMyMzEyY2E0MDZkY2I4ZWVkNTBiODI5YjUyOTJmNWZiM2U4NDZkYjBhNTU2YWY2MWNjNTM4MzRjZTc1NDIxJywgJ2hleCcpO1xuY29uc3QgU1RBQ0tTX1JFQ0lQSUVOVCA9IEJ1ZmZlci5mcm9tKCcwNScgKyAnMTYnICsgJzZkJy5yZXBlYXQoMjApLCAnaGV4Jyk7XG5cbmZ1bmN0aW9uIGdldEJpcDMyVHJpcGxlKCk6IFtCSVAzMkludGVyZmFjZSwgQklQMzJJbnRlcmZhY2UsIEJJUDMySW50ZXJmYWNlXSB7XG4gIGNvbnN0IFt1c2VyLCBiYWNrdXAsIGJpdGdvXSA9IGdldEtleVRyaXBsZSgnZGVmYXVsdCcpO1xuICByZXR1cm4gW3VzZXIsIGJhY2t1cCwgYml0Z29dO1xufVxuXG5mdW5jdGlvbiBidWlsZFBhcmFtcyhvdmVycmlkZXM6IFBhcnRpYWw8U2J0Y0RlcG9zaXREZXNjcmlwdG9yUGFyYW1zPiA9IHt9KTogU2J0Y0RlcG9zaXREZXNjcmlwdG9yUGFyYW1zIHtcbiAgcmV0dXJuIHtcbiAgICB3YWxsZXRLZXlzOiBnZXRCaXAzMlRyaXBsZSgpLFxuICAgIGxvY2tUaW1lOiBERUZBVUxUX1JFQ0xBSU1fTE9DS19USU1FLFxuICAgIG1heEZlZTogREVGQVVMVF9NQVhfU0lHTkVSX0ZFRSxcbiAgICBzdGFja3NSZWNpcGllbnQ6IFNUQUNLU19SRUNJUElFTlQsXG4gICAgc2lnbmVyc0FnZ3JlZ2F0ZUtleTogU0lHTkVSU19BR0dSRUdBVEVfS0VZLFxuICAgIC4uLm92ZXJyaWRlcyxcbiAgfTtcbn1cblxuZGVzY3JpYmUoJ3BhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yJywgZnVuY3Rpb24gKCkge1xuICBkZXNjcmliZSgnZGVmaW5pdGUgZGVzY3JpcHRvciAoY29uY3JldGUgeC1vbmx5IHJlY2xhaW0ga2V5cyknLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcmVjbGFpbUtleUhleDogW3N0cmluZywgc3RyaW5nLCBzdHJpbmddID0gW1xuICAgICAgJzRkODM4NzU5YjJhNzQ2MTZhMjI5OGUwNTgwY2E4MTU4NzRmNWU1YTlkMmRkMWIyZjAyMDNiNjhjNjZmYzZjMWUnLFxuICAgICAgJzYzOTc3OWM0YjcwMGRjNTFlY2UwMTJhMGUyMDMyNWZjYWZhZGEyMmE0YTEyMmZmYWEwNGQwYzBjY2FlODM5NDMnLFxuICAgICAgJ2QxZDYwODRlYWM5ODMwM2U5ZDI4ZTA4MmJmZDllYWRmMGI4YmUwMzNlMjIzYTE3YWQwMWRmODFiZGFhOGM3YjInLFxuICAgIF07XG4gICAgY29uc3QgcmVjbGFpbUtleXM6IFtCdWZmZXIsIEJ1ZmZlciwgQnVmZmVyXSA9IFtcbiAgICAgIEJ1ZmZlci5mcm9tKHJlY2xhaW1LZXlIZXhbMF0sICdoZXgnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKHJlY2xhaW1LZXlIZXhbMV0sICdoZXgnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKHJlY2xhaW1LZXlIZXhbMl0sICdoZXgnKSxcbiAgICBdO1xuICAgIGNvbnN0IHBhcmFtczogU2J0Y0RlcG9zaXREZXNjcmlwdG9yUGFyYW1zID0ge1xuICAgICAgd2FsbGV0S2V5czogcmVjbGFpbUtleXMsXG4gICAgICBsb2NrVGltZTogMTQ0LFxuICAgICAgbWF4RmVlOiA4MF8wMDAsXG4gICAgICBzdGFja3NSZWNpcGllbnQ6IFNUQUNLU19SRUNJUElFTlQsXG4gICAgICBzaWduZXJzQWdncmVnYXRlS2V5OiBTSUdORVJTX0FHR1JFR0FURV9LRVksXG4gICAgfTtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKGNyZWF0ZVNidGNEZXBvc2l0RGVzY3JpcHRvcihwYXJhbXMpLCAnZGVmaW5pdGUnKTtcblxuICAgIGl0KCdyb3VuZC10cmlwcyBhbGwgaGlnaC1sZXZlbCBmaWVsZHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihkZXNjcmlwdG9yKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQuc2lnbmVyc0FnZ3JlZ2F0ZUtleSwgU0lHTkVSU19BR0dSRUdBVEVfS0VZKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQubWF4RmVlLCA4MF8wMDBuKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkLnN0YWNrc1JlY2lwaWVudCwgU1RBQ0tTX1JFQ0lQSUVOVCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLmxvY2tUaW1lLCAxNDQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JldHVybnMgcmVjbGFpbSBrZXlzIGFzIDMyLWJ5dGUgYnVmZmVycyBpbiB0aGUgZGVzY3JpcHRvciBvcmRlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZCk7XG4gICAgICBhc3NlcnQub2socGFyc2VkLnJlY2xhaW1LZXlzKTtcbiAgICAgIC8vIG11bHRpX2Egc29ydHMga2V5cyBieSBoZXg7IHZlcmlmeSB0aGUgcGFyc2VyIHJldHVybnMgd2hhdGV2ZXIgb3JkZXJcbiAgICAgIC8vIHRoZSBkZXNjcmlwdG9yIGxpYnJhcnkgcHJvZHVjZWQgcmF0aGVyIHRoYW4gdGhlIG9yaWdpbmFsIGlucHV0IG9yZGVyLlxuICAgICAgY29uc3Qgc29ydGVkSW5wdXQgPSBbLi4ucmVjbGFpbUtleUhleF0uc29ydCgpLm1hcCgoaykgPT4gQnVmZmVyLmZyb20oaywgJ2hleCcpKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkLnJlY2xhaW1LZXlzLCBzb3J0ZWRJbnB1dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnZXhwb3NlcyByYXcgaGV4IHJlY2xhaW1LZXlTdHJpbmdzIGZvciBkZWZpbml0ZSBpbnB1dHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihkZXNjcmlwdG9yKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQucmVjbGFpbUtleVN0cmluZ3MsIFsuLi5yZWNsYWltS2V5SGV4XS5zb3J0KCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JldHVybnMgbWluaXNjcmlwdCBBU1Qgbm9kZXMgZm9yIGJvdGggbGVhdmVzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VTYnRjRGVwb3NpdERlc2NyaXB0b3IoZGVzY3JpcHRvcik7XG4gICAgICBhc3NlcnQub2socGFyc2VkKTtcbiAgICAgIGNvbnN0IHBheWxvYWRIZXggPSBlbmNvZGVEZXBvc2l0UGF5bG9hZChwYXJhbXMubWF4RmVlLCBwYXJhbXMuc3RhY2tzUmVjaXBpZW50KS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZC5kZXBvc2l0TWluaXNjcmlwdE5vZGUsIHtcbiAgICAgICAgYW5kX3Y6IFt7IHBheWxvYWRfZHJvcDogcGF5bG9hZEhleCB9LCB7IHBrOiBTSUdORVJTX0FHR1JFR0FURV9LRVkudG9TdHJpbmcoJ2hleCcpIH1dLFxuICAgICAgfSBhcyB1bmtub3duIGFzIGFzdC5NaW5pc2NyaXB0Tm9kZSk7XG4gICAgICAvLyByOm9sZGVyICsgbXVsdGlfYSBtdXN0IGJlIHByZXNlbnQgYW5kIGNvcnJlY3RseSBvcmRlcmVkIGluIHRoZSBBU1QuXG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZC5yZWNsYWltTWluaXNjcmlwdE5vZGUsIHtcbiAgICAgICAgYW5kX3Y6IFt7ICdyOm9sZGVyJzogMTQ0IH0sIHsgbXVsdGlfYTogWzIsIC4uLlsuLi5yZWNsYWltS2V5SGV4XS5zb3J0KCldIH1dLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdkZXJpdmFibGUgZGVzY3JpcHRvciAoeHB1Yi8qIHJlY2xhaW0ga2V5cyknLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcGFyYW1zID0gYnVpbGRQYXJhbXMoKTtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKGNyZWF0ZVNidGNEZXBvc2l0RGVzY3JpcHRvcihwYXJhbXMpLCAnZGVyaXZhYmxlJyk7XG5cbiAgICBpdCgncm91bmQtdHJpcHMgbG9ja1RpbWUsIG1heEZlZSwgcmVjaXBpZW50LCBhbmQgc2lnbmVycyBrZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihkZXNjcmlwdG9yKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQuc2lnbmVyc0FnZ3JlZ2F0ZUtleSwgU0lHTkVSU19BR0dSRUdBVEVfS0VZKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQubWF4RmVlLCBCaWdJbnQoREVGQVVMVF9NQVhfU0lHTkVSX0ZFRSkpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQuc3RhY2tzUmVjaXBpZW50LCBTVEFDS1NfUkVDSVBJRU5UKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQubG9ja1RpbWUsIERFRkFVTFRfUkVDTEFJTV9MT0NLX1RJTUUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JldHVybnMgcmVjbGFpbUtleXM9dW5kZWZpbmVkIGZvciBkZXJpdmFibGUgaW5wdXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gRGVyaXZhYmxlIGRlc2NyaXB0b3JzIHJlbmRlciBtdWx0aV9hIGVudHJpZXMgYXMgYHhwdWIuLi4vKmAsIG5vdCBhc1xuICAgICAgLy8gMzItYnl0ZSBoZXgg4oCUIHRoZXkgY2FuJ3QgYmUgcmVkdWNlZCB0byBieXRlcyB3aXRob3V0IHBpY2tpbmcgYW4gaW5kZXguXG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihkZXNjcmlwdG9yKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5yZWNsYWltS2V5cywgdW5kZWZpbmVkKTtcbiAgICB9KTtcblxuICAgIGl0KCdleHBvc2VzIHRoZSByYXcgeHB1Yi4uLi8qIHJlY2xhaW1LZXlTdHJpbmdzIGZvciBkZXJpdmFibGUgaW5wdXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VTYnRjRGVwb3NpdERlc2NyaXB0b3IoZGVzY3JpcHRvcik7XG4gICAgICBhc3NlcnQub2socGFyc2VkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQucmVjbGFpbUtleVN0cmluZ3MubGVuZ3RoLCAzKTtcbiAgICAgIGZvciAoY29uc3QgayBvZiBwYXJzZWQucmVjbGFpbUtleVN0cmluZ3MpIHtcbiAgICAgICAgYXNzZXJ0Lm1hdGNoKGssIC9eeHB1YlsxLTlBLUhKLU5QLVphLWttLXpdK1xcL1xcKiQvKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdyZXNvbHZlcyB0byBjb25jcmV0ZSByZWNsYWltIGtleXMgYWZ0ZXIgYXREZXJpdmF0aW9uSW5kZXgoMCkgYW5kIGNvbXBpbGVzIHRvIGEgdGFwIE1pbmlzY3JpcHQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZGVzY3JpcHRvci5oYXNXaWxkY2FyZCgpLCB0cnVlKTtcbiAgICAgIGNvbnN0IGRlcml2ZWRaZXJvID0gZGVzY3JpcHRvci5hdERlcml2YXRpb25JbmRleCgwKTtcbiAgICAgIGNvbnN0IGRlcml2ZWRPbmUgPSBkZXNjcmlwdG9yLmF0RGVyaXZhdGlvbkluZGV4KDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGRlcml2ZWRaZXJvLmhhc1dpbGRjYXJkKCksIGZhbHNlKTtcblxuICAgICAgY29uc3QgcGFyc2VkWmVybyA9IHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKGRlcml2ZWRaZXJvKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWRaZXJvKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWRaZXJvLnJlY2xhaW1LZXlzKTtcbiAgICAgIGZvciAoY29uc3QgayBvZiBwYXJzZWRaZXJvLnJlY2xhaW1LZXlzKSB7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChrLmxlbmd0aCwgMzIsIGBleHBlY3RlZCAzMi1ieXRlIHgtb25seSBrZXksIGdvdCAke2subGVuZ3RofWApO1xuICAgICAgfVxuICAgICAgLy8gRGVwb3NpdC1sZWFmIGZpZWxkcyBhcmUgZGVyaXZhdGlvbi1pbmRlcGVuZGVudC5cbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkWmVyby5zaWduZXJzQWdncmVnYXRlS2V5LCBTSUdORVJTX0FHR1JFR0FURV9LRVkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZFplcm8ubG9ja1RpbWUsIERFRkFVTFRfUkVDTEFJTV9MT0NLX1RJTUUpO1xuXG4gICAgICBjb25zdCBwYXJzZWRPbmUgPSBwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcihkZXJpdmVkT25lKTtcbiAgICAgIGFzc2VydC5vayhwYXJzZWRPbmU/LnJlY2xhaW1LZXlzKTtcbiAgICAgIGFzc2VydC5ub3REZWVwU3RyaWN0RXF1YWwocGFyc2VkWmVyby5yZWNsYWltS2V5cywgcGFyc2VkT25lLnJlY2xhaW1LZXlzKTtcblxuICAgICAgLy8gVGhlIHJld3JpdHRlbiByZWNsYWltIGxlYWYgY2FycmllcyBjb25jcmV0ZSBoZXggaW4gbXVsdGlfYSwgc28gdGhlXG4gICAgICAvLyBmb3JtYXR0ZWQgc3RyaW5nIGNvbXBpbGVzIGFzIGEgdGFwLWNvbnRleHQgTWluaXNjcmlwdC4gYGZyb21TdHJpbmdFeHRgXG4gICAgICAvLyBpcyByZXF1aXJlZCBiZWNhdXNlIHRoZSBsZWFmIGNvbnRhaW5zIHRoZSBgcjpvbGRlcmAgKGRyb3ApIHdyYXBwZXIuXG4gICAgICBjb25zdCByZWNsYWltTXMgPSBNaW5pc2NyaXB0LmZyb21TdHJpbmdFeHQoYXN0LmZvcm1hdE5vZGUocGFyc2VkWmVyby5yZWNsYWltTWluaXNjcmlwdE5vZGUpLCAndGFwJywge30pO1xuICAgICAgYXNzZXJ0Lm9rKHJlY2xhaW1Ncyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdyZWplY3Rpb24gcGF0aHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcGFyYW1zID0gYnVpbGRQYXJhbXMoKTtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKGNyZWF0ZVNidGNEZXBvc2l0RGVzY3JpcHRvcihwYXJhbXMpLCAnZGVyaXZhYmxlJyk7XG5cbiAgICBpdCgncmV0dXJucyBudWxsIGZvciBhIG5vbi1zQlRDIGRlc2NyaXB0b3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3cGtoRGVzY3JpcHRvciA9IERlc2NyaXB0b3IuZnJvbVN0cmluZyhgd3BraCgke2dldEJpcDMyVHJpcGxlKClbMF0ubmV1dGVyZWQoKS50b0Jhc2U1OCgpfS8qKWAsICdkZXJpdmFibGUnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZVNidGNEZXBvc2l0RGVzY3JpcHRvcih3cGtoRGVzY3JpcHRvciksIG51bGwpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JldHVybnMgbnVsbCBmb3IgYSB0cigpIHRoYXQgaGFzIGEgZGlmZmVyZW50IGludGVybmFsIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFN3YXAgVU5TUEVOREFCTEUgZm9yIGFuIGFyYml0cmFyeSAzMi1ieXRlIGtleSDigJQgcGF0dGVybiBtYXRjaCBtdXN0XG4gICAgICAvLyByZXF1aXJlIHRoZSBjYW5vbmljYWwgdW5zcGVuZGFibGUgcG9pbnQsIG5vdCBqdXN0IGFueSB0cigpLlxuICAgICAgY29uc3QgdGFtcGVyZWQgPSBjcmVhdGVTYnRjRGVwb3NpdERlc2NyaXB0b3IoYnVpbGRQYXJhbXMoKSkucmVwbGFjZShVTlNQRU5EQUJMRV9JTlRFUk5BTF9LRVksICdhJy5yZXBlYXQoNjQpKTtcbiAgICAgIGNvbnN0IG5vZGUgPSBhc3QuZnJvbURlc2NyaXB0b3IoRGVzY3JpcHRvci5mcm9tU3RyaW5nKHRhbXBlcmVkLCAnZGVyaXZhYmxlJykpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKG5vZGUpLCBudWxsKTtcbiAgICB9KTtcblxuICAgIGl0KCdhY2NlcHRzIGEgcHJlLWV4dHJhY3RlZCBhc3QuRGVzY3JpcHRvck5vZGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBub2RlID0gYXN0LmZyb21EZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VTYnRjRGVwb3NpdERlc2NyaXB0b3Iobm9kZSk7XG4gICAgICBhc3NlcnQub2socGFyc2VkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQubG9ja1RpbWUsIERFRkFVTFRfUkVDTEFJTV9MT0NLX1RJTUUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncGFyYW1ldGVyIHJvdW5kLXRyaXAnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ2V4dHJhY3RzIHRoZSBzYW1lIG1heEZlZSBhbmQgcmVjaXBpZW50IHRoYXQgZW5jb2RlRGVwb3NpdFBheWxvYWQgcHJvZHVjZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZWNpcGllbnQgPSBCdWZmZXIuYWxsb2MoU1RBQ0tTX1JFQ0lQSUVOVF9CWVRFX0xFTkdUSCwgMHgxMSk7XG4gICAgICBjb25zdCBwYXJhbXMgPSBidWlsZFBhcmFtcyh7IG1heEZlZTogMTIzNDVuLCBzdGFja3NSZWNpcGllbnQ6IHJlY2lwaWVudCB9KTtcbiAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBEZXNjcmlwdG9yLmZyb21TdHJpbmcoY3JlYXRlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKHBhcmFtcyksICdkZXJpdmFibGUnKTtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLm1heEZlZSwgMTIzNDVuKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkLnN0YWNrc1JlY2lwaWVudCwgcmVjaXBpZW50KTtcbiAgICB9KTtcblxuICAgIGl0KCdhY2NlcHRzIHRoZSBmdWxsIHVuc2lnbmVkIDY0LWJpdCBtYXhGZWUgcmFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtYXggPSAweGZmZmZmZmZmZmZmZmZmZmZuO1xuICAgICAgY29uc3QgcGFyYW1zID0gYnVpbGRQYXJhbXMoeyBtYXhGZWU6IG1heCB9KTtcbiAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBEZXNjcmlwdG9yLmZyb21TdHJpbmcoY3JlYXRlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKHBhcmFtcyksICdkZXJpdmFibGUnKTtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlU2J0Y0RlcG9zaXREZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICAgICAgYXNzZXJ0Lm9rKHBhcnNlZCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLm1heEZlZSwgbWF4KTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==