@bitgo-beta/utxo-descriptors 0.0.1-beta.26 → 0.0.1-beta.261
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/index.d.ts +1 -0
- package/dist/cjs/src/index.d.ts.map +1 -1
- package/dist/cjs/src/index.js +3 -2
- package/dist/cjs/src/pox5/descriptor.d.ts +22 -0
- package/dist/cjs/src/pox5/descriptor.d.ts.map +1 -0
- package/dist/cjs/src/pox5/descriptor.js +78 -0
- package/dist/cjs/src/pox5/index.d.ts +3 -0
- package/dist/cjs/src/pox5/index.d.ts.map +1 -0
- package/dist/cjs/src/pox5/index.js +19 -0
- package/dist/cjs/src/pox5/parseDescriptor.d.ts +16 -0
- package/dist/cjs/src/pox5/parseDescriptor.d.ts.map +1 -0
- package/dist/cjs/src/pox5/parseDescriptor.js +96 -0
- 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 +55 -0
- package/dist/cjs/src/sbtc/parseDescriptor.d.ts.map +1 -0
- package/dist/cjs/src/sbtc/parseDescriptor.js +185 -0
- package/dist/cjs/test/unit/pox5/descriptor.d.ts +2 -0
- package/dist/cjs/test/unit/pox5/descriptor.d.ts.map +1 -0
- package/dist/cjs/test/unit/pox5/descriptor.js +158 -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 +202 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/pox5/descriptor.d.ts +22 -0
- package/dist/esm/pox5/descriptor.d.ts.map +1 -0
- package/dist/esm/pox5/descriptor.js +73 -0
- package/dist/esm/pox5/index.d.ts +3 -0
- package/dist/esm/pox5/index.d.ts.map +1 -0
- package/dist/esm/pox5/index.js +3 -0
- package/dist/esm/pox5/parseDescriptor.d.ts +16 -0
- package/dist/esm/pox5/parseDescriptor.d.ts.map +1 -0
- package/dist/esm/pox5/parseDescriptor.js +93 -0
- 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 +55 -0
- package/dist/esm/sbtc/parseDescriptor.d.ts.map +1 -0
- package/dist/esm/sbtc/parseDescriptor.js +182 -0
- package/package.json +7 -4
|
@@ -0,0 +1,158 @@
|
|
|
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 crypto_1 = require("crypto");
|
|
38
|
+
const bitcoin_staking_1 = require("@stacks/bitcoin-staking");
|
|
39
|
+
const wasm_utxo_1 = require("@bitgo/wasm-utxo");
|
|
40
|
+
const testutils_1 = require("@bitgo/wasm-utxo/testutils");
|
|
41
|
+
const pox5_1 = require("../../../src/pox5");
|
|
42
|
+
const OPCODES = {
|
|
43
|
+
OP_0: 0x00,
|
|
44
|
+
OP_IF: 0x63,
|
|
45
|
+
OP_ELSE: 0x67,
|
|
46
|
+
OP_ENDIF: 0x68,
|
|
47
|
+
OP_VERIFY: 0x69,
|
|
48
|
+
OP_SIZE: 0x82,
|
|
49
|
+
OP_EQUAL: 0x87,
|
|
50
|
+
OP_EQUALVERIFY: 0x88,
|
|
51
|
+
OP_SHA256: 0xa8,
|
|
52
|
+
OP_CHECKSIG: 0xac,
|
|
53
|
+
OP_CHECKMULTISIG: 0xae,
|
|
54
|
+
OP_CLTV: 0xb1,
|
|
55
|
+
};
|
|
56
|
+
function getBip32Triple() {
|
|
57
|
+
const [user, backup, bitgo] = (0, testutils_1.getKeyTriple)('default');
|
|
58
|
+
return [user, backup, bitgo];
|
|
59
|
+
}
|
|
60
|
+
function sha256(value) {
|
|
61
|
+
return (0, crypto_1.createHash)('sha256').update(value).digest();
|
|
62
|
+
}
|
|
63
|
+
function params(overrides = {}) {
|
|
64
|
+
const stakerKeys = getBip32Triple();
|
|
65
|
+
const earlyExitKey = Buffer.from(stakerKeys[0].derive(9).publicKey);
|
|
66
|
+
return {
|
|
67
|
+
unlockHeight: 840000,
|
|
68
|
+
stakerCommitment: sha256((0, bitcoin_staking_1.computeRegisterPreimage)('SP000000000000000000002Q6VF78')),
|
|
69
|
+
earlyExitKey,
|
|
70
|
+
stakerKeys,
|
|
71
|
+
...overrides,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function asmToScript(asm) {
|
|
75
|
+
const tokens = asm.split(' ');
|
|
76
|
+
const chunks = [];
|
|
77
|
+
for (let index = 0; index < tokens.length; index++) {
|
|
78
|
+
const token = tokens[index];
|
|
79
|
+
const push = token.match(/^OP_PUSHBYTES_(\d+)$/);
|
|
80
|
+
if (push) {
|
|
81
|
+
const bytes = Buffer.from(tokens[++index], 'hex');
|
|
82
|
+
assert.strictEqual(bytes.length, Number(push[1]));
|
|
83
|
+
chunks.push(Buffer.of(bytes.length), bytes);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const number = token.match(/^OP_PUSHNUM_(\d+)$/);
|
|
87
|
+
if (number) {
|
|
88
|
+
chunks.push(Buffer.of(0x50 + Number(number[1])));
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const opcode = OPCODES[token];
|
|
92
|
+
assert.notStrictEqual(opcode, undefined, `unsupported ASM token ${token}`);
|
|
93
|
+
chunks.push(Buffer.of(opcode));
|
|
94
|
+
}
|
|
95
|
+
return Buffer.concat(chunks);
|
|
96
|
+
}
|
|
97
|
+
function encodeTwoOfThreeUnlock(keys) {
|
|
98
|
+
return Buffer.concat([Buffer.of(0x52), ...keys.flatMap((key) => [Buffer.of(33), key]), Buffer.of(0x53, 0xae)]);
|
|
99
|
+
}
|
|
100
|
+
describe('PoX-5 lockup descriptors', function () {
|
|
101
|
+
it('renders the required byte-identical canonical script and P2WSH output', function () {
|
|
102
|
+
const derivable = params();
|
|
103
|
+
const stakerKeys = (0, pox5_1.derivePox5StakerKeys)(derivable.stakerKeys, 0);
|
|
104
|
+
const definite = { ...derivable, stakerKeys };
|
|
105
|
+
const descriptorString = (0, pox5_1.createPox5LockupDescriptor)(definite);
|
|
106
|
+
const descriptor = wasm_utxo_1.Descriptor.fromString(descriptorString, 'definite');
|
|
107
|
+
const localWitnessScript = asmToScript(descriptor.toAsmString());
|
|
108
|
+
const unlockBytes = encodeTwoOfThreeUnlock(stakerKeys);
|
|
109
|
+
const earlyUnlockBytes = (0, bitcoin_staking_1.buildUnlockScript)(definite.earlyExitKey);
|
|
110
|
+
const sdkWitnessScript = Buffer.from((0, bitcoin_staking_1.buildLockScript)({
|
|
111
|
+
stxAddress: 'SP000000000000000000002Q6VF78',
|
|
112
|
+
unlockHeight: definite.unlockHeight,
|
|
113
|
+
unlockBytes,
|
|
114
|
+
earlyUnlockBytes,
|
|
115
|
+
validateEarlyUnlockBytes: false,
|
|
116
|
+
}));
|
|
117
|
+
assert.deepStrictEqual(localWitnessScript, sdkWitnessScript);
|
|
118
|
+
assert.ok(descriptor.toAsmString().includes('OP_SHA256 OP_PUSHBYTES_32'));
|
|
119
|
+
assert.ok(descriptor.toAsmString().includes('OP_EQUALVERIFY OP_PUSHBYTES_33'));
|
|
120
|
+
const localScriptPubKey = (0, pox5_1.createPox5LockupScriptPubKey)(definite);
|
|
121
|
+
const sdkScriptPubKey = Buffer.from((0, bitcoin_staking_1.buildLockOutputScript)({
|
|
122
|
+
stxAddress: 'SP000000000000000000002Q6VF78',
|
|
123
|
+
unlockHeight: definite.unlockHeight,
|
|
124
|
+
unlockBytes,
|
|
125
|
+
earlyUnlockBytes,
|
|
126
|
+
}));
|
|
127
|
+
assert.deepStrictEqual(localScriptPubKey, sdkScriptPubKey);
|
|
128
|
+
assert.strictEqual(wasm_utxo_1.address.fromOutputScriptWithCoin(localScriptPubKey, 'btc'), (0, bitcoin_staking_1.buildLockAddress)({
|
|
129
|
+
stxAddress: 'SP000000000000000000002Q6VF78',
|
|
130
|
+
unlockHeight: definite.unlockHeight,
|
|
131
|
+
unlockBytes,
|
|
132
|
+
earlyUnlockBytes,
|
|
133
|
+
network: 'mainnet',
|
|
134
|
+
validateEarlyUnlockBytes: false,
|
|
135
|
+
}));
|
|
136
|
+
});
|
|
137
|
+
it('supports derivation and preserves wildcard keys until an index is selected', function () {
|
|
138
|
+
const value = params();
|
|
139
|
+
const descriptor = wasm_utxo_1.Descriptor.fromString((0, pox5_1.createPox5LockupDescriptor)(value), 'derivable');
|
|
140
|
+
const wildcard = (0, pox5_1.parsePox5LockupDescriptor)(descriptor);
|
|
141
|
+
const derived = (0, pox5_1.parsePox5LockupDescriptor)(descriptor.atDerivationIndex(4));
|
|
142
|
+
assert.ok(wildcard);
|
|
143
|
+
assert.strictEqual(wildcard.stakerKeys, undefined);
|
|
144
|
+
assert.ok(wildcard.stakerKeyStrings.every((key) => key.endsWith('/*')));
|
|
145
|
+
assert.ok(derived?.stakerKeys);
|
|
146
|
+
assert.deepStrictEqual(derived?.stakerKeys, (0, pox5_1.derivePox5StakerKeys)(value.stakerKeys, 4));
|
|
147
|
+
});
|
|
148
|
+
it('rejects noncanonical parameter values and descriptor templates', function () {
|
|
149
|
+
assert.throws(() => (0, pox5_1.createPox5LockupDescriptor)(params({ unlockHeight: 0 })));
|
|
150
|
+
assert.throws(() => (0, pox5_1.createPox5LockupDescriptor)(params({ unlockHeight: 500000000 })));
|
|
151
|
+
assert.throws(() => (0, pox5_1.createPox5LockupDescriptor)(params({ stakerCommitment: Buffer.alloc(31) })));
|
|
152
|
+
assert.throws(() => (0, pox5_1.createPox5LockupDescriptor)(params({ earlyExitKey: Buffer.alloc(32) })));
|
|
153
|
+
assert.throws(() => (0, pox5_1.createPox5LockupDescriptor)(params({ stakerKeys: [getBip32Triple()[0], Buffer.alloc(33, 2), Buffer.alloc(33, 2)] })));
|
|
154
|
+
const validKey = params().earlyExitKey.toString('hex');
|
|
155
|
+
assert.strictEqual((0, pox5_1.parsePox5LockupDescriptor)(wasm_utxo_1.Descriptor.fromString(`wsh(pk(${validKey}))`, 'definite')), null);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVzY3JpcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Rlc3QvdW5pdC9wb3g1L2Rlc2NyaXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBaUM7QUFDakMsbUNBQW9DO0FBRXBDLDZEQU1pQztBQUNqQyxnREFBOEQ7QUFDOUQsMERBQTBEO0FBRTFELDRDQU0yQjtBQUkzQixNQUFNLE9BQU8sR0FBMkI7SUFDdEMsSUFBSSxFQUFFLElBQUk7SUFDVixLQUFLLEVBQUUsSUFBSTtJQUNYLE9BQU8sRUFBRSxJQUFJO0lBQ2IsUUFBUSxFQUFFLElBQUk7SUFDZCxTQUFTLEVBQUUsSUFBSTtJQUNmLE9BQU8sRUFBRSxJQUFJO0lBQ2IsUUFBUSxFQUFFLElBQUk7SUFDZCxjQUFjLEVBQUUsSUFBSTtJQUNwQixTQUFTLEVBQUUsSUFBSTtJQUNmLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLGdCQUFnQixFQUFFLElBQUk7SUFDdEIsT0FBTyxFQUFFLElBQUk7Q0FDZCxDQUFDO0FBRUYsU0FBUyxjQUFjO0lBQ3JCLE1BQU0sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHLElBQUEsd0JBQVksRUFBQyxTQUFTLENBQUMsQ0FBQztJQUN0RCxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztBQUMvQixDQUFDO0FBRUQsU0FBUyxNQUFNLENBQUMsS0FBaUI7SUFDL0IsT0FBTyxJQUFBLG1CQUFVLEVBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0FBQ3JELENBQUM7QUFFRCxTQUFTLE1BQU0sQ0FBQyxZQUFpRCxFQUFFO0lBQ2pFLE1BQU0sVUFBVSxHQUFHLGNBQWMsRUFBRSxDQUFDO0lBQ3BDLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxJ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LENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2RCxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsZ0NBQXlCLEVBQUMsc0JBQVUsQ0FBQyxVQUFVLENBQUMsVUFBVSxRQUFRLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuXG5pbXBvcnQge1xuICBidWlsZExvY2tBZGRyZXNzLFxuICBidWlsZExvY2tPdXRwdXRTY3JpcHQsXG4gIGJ1aWxkTG9ja1NjcmlwdCxcbiAgYnVpbGRVbmxvY2tTY3JpcHQsXG4gIGNvbXB1dGVSZWdpc3RlclByZWltYWdlLFxufSBmcm9tICdAc3RhY2tzL2JpdGNvaW4tc3Rha2luZyc7XG5pbXBvcnQgeyBhZGRyZXNzLCBiaXAzMiwgRGVzY3JpcHRvciB9IGZyb20gJ0BiaXRnby93YXNtLXV0eG8nO1xuaW1wb3J0IHsgZ2V0S2V5VHJpcGxlIH0gZnJvbSAnQGJpdGdvL3dhc20tdXR4by90ZXN0dXRpbHMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVQb3g1TG9ja3VwRGVzY3JpcHRvcixcbiAgY3JlYXRlUG94NUxvY2t1cFNjcmlwdFB1YktleSxcbiAgZGVyaXZlUG94NVN0YWtlcktleXMsXG4gIHBhcnNlUG94NUxvY2t1cERlc2NyaXB0b3IsXG4gIFBveDVMb2NrdXBEZXNjcmlwdG9yUGFyYW1zLFxufSBmcm9tICcuLi8uLi8uLi9zcmMvcG94NSc7XG5cbnR5cGUgQklQMzJJbnRlcmZhY2UgPSBiaXAzMi5CSVAzMkludGVyZmFjZTtcblxuY29uc3QgT1BDT0RFUzogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHtcbiAgT1BfMDogMHgwMCxcbiAgT1BfSUY6IDB4NjMsXG4gIE9QX0VMU0U6IDB4NjcsXG4gIE9QX0VORElGOiAweDY4LFxuICBPUF9WRVJJRlk6IDB4NjksXG4gIE9QX1NJWkU6IDB4ODIsXG4gIE9QX0VRVUFMOiAweDg3LFxuICBPUF9FUVVBTFZFUklGWTogMHg4OCxcbiAgT1BfU0hBMjU2OiAweGE4LFxuICBPUF9DSEVDS1NJRzogMHhhYyxcbiAgT1BfQ0hFQ0tNVUxUSVNJRzogMHhhZSxcbiAgT1BfQ0xUVjogMHhiMSxcbn07XG5cbmZ1bmN0aW9uIGdldEJpcDMyVHJpcGxlKCk6IFtCSVAzMkludGVyZmFjZSwgQklQMzJJbnRlcmZhY2UsIEJJUDMySW50ZXJmYWNlXSB7XG4gIGNvbnN0IFt1c2VyLCBiYWNrdXAsIGJpdGdvXSA9IGdldEtleVRyaXBsZSgnZGVmYXVsdCcpO1xuICByZXR1cm4gW3VzZXIsIGJhY2t1cCwgYml0Z29dO1xufVxuXG5mdW5jdGlvbiBzaGEyNTYodmFsdWU6IFVpbnQ4QXJyYXkpOiBCdWZmZXIge1xuICByZXR1cm4gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHZhbHVlKS5kaWdlc3QoKTtcbn1cblxuZnVuY3Rpb24gcGFyYW1zKG92ZXJyaWRlczogUGFydGlhbDxQb3g1TG9ja3VwRGVzY3JpcHRvclBhcmFtcz4gPSB7fSk6IFBveDVMb2NrdXBEZXNjcmlwdG9yUGFyYW1zIHtcbiAgY29uc3Qgc3Rha2VyS2V5cyA9IGdldEJpcDMyVHJpcGxlKCk7XG4gIGNvbnN0IGVhcmx5RXhpdEtleSA9IEJ1ZmZlci5mcm9tKHN0YWtlcktleXNbMF0uZGVyaXZlKDkpLnB1YmxpY0tleSk7XG4gIHJldHVybiB7XG4gICAgdW5sb2NrSGVpZ2h0OiA4NDBfMDAwLFxuICAgIHN0YWtlckNvbW1pdG1lbnQ6IHNoYTI1Nihjb21wdXRlUmVnaXN0ZXJQcmVpbWFnZSgnU1AwMDAwMDAwMDAwMDAwMDAwMDAwMDJRNlZGNzgnKSksXG4gICAgZWFybHlFeGl0S2V5LFxuICAgIHN0YWtlcktleXMsXG4gICAgLi4ub3ZlcnJpZGVzLFxuICB9O1xufVxuXG5mdW5jdGlvbiBhc21Ub1NjcmlwdChhc206IHN0cmluZyk6IEJ1ZmZlciB7XG4gIGNvbnN0IHRva2VucyA9IGFzbS5zcGxpdCgnICcpO1xuICBjb25zdCBjaHVua3M6IEJ1ZmZlcltdID0gW107XG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB0b2tlbnMubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgY29uc3QgdG9rZW4gPSB0b2tlbnNbaW5kZXhdO1xuICAgIGNvbnN0IHB1c2ggPSB0b2tlbi5tYXRjaCgvXk9QX1BVU0hCWVRFU18oXFxkKykkLyk7XG4gICAgaWYgKHB1c2gpIHtcbiAgICAgIGNvbnN0IGJ5dGVzID0gQnVmZmVyLmZyb20odG9rZW5zWysraW5kZXhdLCAnaGV4Jyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYnl0ZXMubGVuZ3RoLCBOdW1iZXIocHVzaFsxXSkpO1xuICAgICAgY2h1bmtzLnB1c2goQnVmZmVyLm9mKGJ5dGVzLmxlbmd0aCksIGJ5dGVzKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBudW1iZXIgPSB0b2tlbi5tYXRjaCgvXk9QX1BVU0hOVU1fKFxcZCspJC8pO1xuICAgIGlmIChudW1iZXIpIHtcbiAgICAgIGNodW5rcy5wdXNoKEJ1ZmZlci5vZigweDUwICsgTnVtYmVyKG51bWJlclsxXSkpKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBvcGNvZGUgPSBPUENPREVTW3Rva2VuXTtcbiAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwob3Bjb2RlLCB1bmRlZmluZWQsIGB1bnN1cHBvcnRlZCBBU00gdG9rZW4gJHt0b2tlbn1gKTtcbiAgICBjaHVua3MucHVzaChCdWZmZXIub2Yob3Bjb2RlKSk7XG4gIH1cbiAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoY2h1bmtzKTtcbn1cblxuZnVuY3Rpb24gZW5jb2RlVHdvT2ZUaHJlZVVubG9jayhrZXlzOiBbQnVmZmVyLCBCdWZmZXIsIEJ1ZmZlcl0pOiBCdWZmZXIge1xuICByZXR1cm4gQnVmZmVyLmNvbmNhdChbQnVmZmVyLm9mKDB4NTIpLCAuLi5rZXlzLmZsYXRNYXAoKGtleSkgPT4gW0J1ZmZlci5vZigzMyksIGtleV0pLCBCdWZmZXIub2YoMHg1MywgMHhhZSldKTtcbn1cblxuZGVzY3JpYmUoJ1BvWC01IGxvY2t1cCBkZXNjcmlwdG9ycycsIGZ1bmN0aW9uICgpIHtcbiAgaXQoJ3JlbmRlcnMgdGhlIHJlcXVpcmVkIGJ5dGUtaWRlbnRpY2FsIGNhbm9uaWNhbCBzY3JpcHQgYW5kIFAyV1NIIG91dHB1dCcsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBkZXJpdmFibGUgPSBwYXJhbXMoKTtcbiAgICBjb25zdCBzdGFrZXJLZXlzID0gZGVyaXZlUG94NVN0YWtlcktleXMoXG4gICAgICBkZXJpdmFibGUuc3Rha2VyS2V5cyBhcyBbQklQMzJJbnRlcmZhY2UsIEJJUDMySW50ZXJmYWNlLCBCSVAzMkludGVyZmFjZV0sXG4gICAgICAwXG4gICAgKTtcbiAgICBjb25zdCBkZWZpbml0ZSA9IHsgLi4uZGVyaXZhYmxlLCBzdGFrZXJLZXlzIH07XG4gICAgY29uc3QgZGVzY3JpcHRvclN0cmluZyA9IGNyZWF0ZVBveDVMb2NrdXBEZXNjcmlwdG9yKGRlZmluaXRlKTtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKGRlc2NyaXB0b3JTdHJpbmcsICdkZWZpbml0ZScpO1xuICAgIGNvbnN0IGxvY2FsV2l0bmVzc1NjcmlwdCA9IGFzbVRvU2NyaXB0KGRlc2NyaXB0b3IudG9Bc21TdHJpbmcoKSk7XG4gICAgY29uc3QgdW5sb2NrQnl0ZXMgPSBlbmNvZGVUd29PZlRocmVlVW5sb2NrKHN0YWtlcktleXMpO1xuICAgIGNvbnN0IGVhcmx5VW5sb2NrQnl0ZXMgPSBidWlsZFVubG9ja1NjcmlwdChkZWZpbml0ZS5lYXJseUV4aXRLZXkpO1xuICAgIGNvbnN0IHNka1dpdG5lc3NTY3JpcHQgPSBCdWZmZXIuZnJvbShcbiAgICAgIGJ1aWxkTG9ja1NjcmlwdCh7XG4gICAgICAgIHN0eEFkZHJlc3M6ICdTUDAwMDAwMDAwMDAwMDAwMDAwMDAwMlE2VkY3OCcsXG4gICAgICAgIHVubG9ja0hlaWdodDogZGVmaW5pdGUudW5sb2NrSGVpZ2h0LFxuICAgICAgICB1bmxvY2tCeXRlcyxcbiAgICAgICAgZWFybHlVbmxvY2tCeXRlcyxcbiAgICAgICAgdmFsaWRhdGVFYXJseVVubG9ja0J5dGVzOiBmYWxzZSxcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwobG9jYWxXaXRuZXNzU2NyaXB0LCBzZGtXaXRuZXNzU2NyaXB0KTtcbiAgICBhc3NlcnQub2soZGVzY3JpcHRvci50b0FzbVN0cmluZygpLmluY2x1ZGVzKCdPUF9TSEEyNTYgT1BfUFVTSEJZVEVTXzMyJykpO1xuICAgIGFzc2VydC5vayhkZXNjcmlwdG9yLnRvQXNtU3RyaW5nKCkuaW5jbHVkZXMoJ09QX0VRVUFMVkVSSUZZIE9QX1BVU0hCWVRFU18zMycpKTtcblxuICAgIGNvbnN0IGxvY2FsU2NyaXB0UHViS2V5ID0gY3JlYXRlUG94NUxvY2t1cFNjcmlwdFB1YktleShkZWZpbml0ZSk7XG4gICAgY29uc3Qgc2RrU2NyaXB0UHViS2V5ID0gQnVmZmVyLmZyb20oXG4gICAgICBidWlsZExvY2tPdXRwdXRTY3JpcHQoe1xuICAgICAgICBzdHhBZGRyZXNzOiAnU1AwMDAwMDAwMDAwMDAwMDAwMDAwMDJRNlZGNzgnLFxuICAgICAgICB1bmxvY2tIZWlnaHQ6IGRlZmluaXRlLnVubG9ja0hlaWdodCxcbiAgICAgICAgdW5sb2NrQnl0ZXMsXG4gICAgICAgIGVhcmx5VW5sb2NrQnl0ZXMsXG4gICAgICB9KVxuICAgICk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChsb2NhbFNjcmlwdFB1YktleSwgc2RrU2NyaXB0UHViS2V5KTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoXG4gICAgICBhZGRyZXNzLmZyb21PdXRwdXRTY3JpcHRXaXRoQ29pbihsb2NhbFNjcmlwdFB1YktleSwgJ2J0YycpLFxuICAgICAgYnVpbGRMb2NrQWRkcmVzcyh7XG4gICAgICAgIHN0eEFkZHJlc3M6ICdTUDAwMDAwMDAwMDAwMDAwMDAwMDAwMlE2VkY3OCcsXG4gICAgICAgIHVubG9ja0hlaWdodDogZGVmaW5pdGUudW5sb2NrSGVpZ2h0LFxuICAgICAgICB1bmxvY2tCeXRlcyxcbiAgICAgICAgZWFybHlVbmxvY2tCeXRlcyxcbiAgICAgICAgbmV0d29yazogJ21haW5uZXQnLFxuICAgICAgICB2YWxpZGF0ZUVhcmx5VW5sb2NrQnl0ZXM6IGZhbHNlLFxuICAgICAgfSlcbiAgICApO1xuICB9KTtcblxuICBpdCgnc3VwcG9ydHMgZGVyaXZhdGlvbiBhbmQgcHJlc2VydmVzIHdpbGRjYXJkIGtleXMgdW50aWwgYW4gaW5kZXggaXMgc2VsZWN0ZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdmFsdWUgPSBwYXJhbXMoKTtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKGNyZWF0ZVBveDVMb2NrdXBEZXNjcmlwdG9yKHZhbHVlKSwgJ2Rlcml2YWJsZScpO1xuICAgIGNvbnN0IHdpbGRjYXJkID0gcGFyc2VQb3g1TG9ja3VwRGVzY3JpcHRvcihkZXNjcmlwdG9yKTtcbiAgICBjb25zdCBkZXJpdmVkID0gcGFyc2VQb3g1TG9ja3VwRGVzY3JpcHRvcihkZXNjcmlwdG9yLmF0RGVyaXZhdGlvbkluZGV4KDQpKTtcblxuICAgIGFzc2VydC5vayh3aWxkY2FyZCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHdpbGRjYXJkLnN0YWtlcktleXMsIHVuZGVmaW5lZCk7XG4gICAgYXNzZXJ0Lm9rKHdpbGRjYXJkLnN0YWtlcktleVN0cmluZ3MuZXZlcnkoKGtleSkgPT4ga2V5LmVuZHNXaXRoKCcvKicpKSk7XG4gICAgYXNzZXJ0Lm9rKGRlcml2ZWQ/LnN0YWtlcktleXMpO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoXG4gICAgICBkZXJpdmVkPy5zdGFrZXJLZXlzLFxuICAgICAgZGVyaXZlUG94NVN0YWtlcktleXModmFsdWUuc3Rha2VyS2V5cyBhcyBbQklQMzJJbnRlcmZhY2UsIEJJUDMySW50ZXJmYWNlLCBCSVAzMkludGVyZmFjZV0sIDQpXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3JlamVjdHMgbm9uY2Fub25pY2FsIHBhcmFtZXRlciB2YWx1ZXMgYW5kIGRlc2NyaXB0b3IgdGVtcGxhdGVzJywgZnVuY3Rpb24gKCkge1xuICAgIGFzc2VydC50aHJvd3MoKCkgPT4gY3JlYXRlUG94NUxvY2t1cERlc2NyaXB0b3IocGFyYW1zKHsgdW5sb2NrSGVpZ2h0OiAwIH0pKSk7XG4gICAgYXNzZXJ0LnRocm93cygoKSA9PiBjcmVhdGVQb3g1TG9ja3VwRGVzY3JpcHRvcihwYXJhbXMoeyB1bmxvY2tIZWlnaHQ6IDUwMF8wMDBfMDAwIH0pKSk7XG4gICAgYXNzZXJ0LnRocm93cygoKSA9PiBjcmVhdGVQb3g1TG9ja3VwRGVzY3JpcHRvcihwYXJhbXMoeyBzdGFrZXJDb21taXRtZW50OiBCdWZmZXIuYWxsb2MoMzEpIH0pKSk7XG4gICAgYXNzZXJ0LnRocm93cygoKSA9PiBjcmVhdGVQb3g1TG9ja3VwRGVzY3JpcHRvcihwYXJhbXMoeyBlYXJseUV4aXRLZXk6IEJ1ZmZlci5hbGxvYygzMikgfSkpKTtcbiAgICBhc3NlcnQudGhyb3dzKCgpID0+XG4gICAgICBjcmVhdGVQb3g1TG9ja3VwRGVzY3JpcHRvcihcbiAgICAgICAgcGFyYW1zKHsgc3Rha2VyS2V5czogW2dldEJpcDMyVHJpcGxlKClbMF0sIEJ1ZmZlci5hbGxvYygzMywgMiksIEJ1ZmZlci5hbGxvYygzMywgMildIH0pXG4gICAgICApXG4gICAgKTtcbiAgICBjb25zdCB2YWxpZEtleSA9IHBhcmFtcygpLmVhcmx5RXhpdEtleS50b1N0cmluZygnaGV4Jyk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlUG94NUxvY2t1cERlc2NyaXB0b3IoRGVzY3JpcHRvci5mcm9tU3RyaW5nKGB3c2gocGsoJHt2YWxpZEtleX0pKWAsICdkZWZpbml0ZScpKSwgbnVsbCk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -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==
|