@bitgo-beta/utxo-descriptors 0.0.1-beta.37 → 0.0.1-beta.371
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 +79 -0
- package/dist/cjs/src/pox5/index.d.ts +6 -0
- package/dist/cjs/src/pox5/index.d.ts.map +1 -0
- package/dist/cjs/src/pox5/index.js +22 -0
- package/dist/cjs/src/pox5/input.d.ts +28 -0
- package/dist/cjs/src/pox5/input.d.ts.map +1 -0
- package/dist/cjs/src/pox5/input.js +47 -0
- package/dist/cjs/src/pox5/parseDescriptor.d.ts +20 -0
- package/dist/cjs/src/pox5/parseDescriptor.d.ts.map +1 -0
- package/dist/cjs/src/pox5/parseDescriptor.js +113 -0
- package/dist/cjs/src/pox5/recovery.d.ts +13 -0
- package/dist/cjs/src/pox5/recovery.d.ts.map +1 -0
- package/dist/cjs/src/pox5/recovery.js +75 -0
- package/dist/cjs/src/pox5/validation.d.ts +12 -0
- package/dist/cjs/src/pox5/validation.d.ts.map +1 -0
- package/dist/cjs/src/pox5/validation.js +70 -0
- package/dist/cjs/src/sbtc/parseDescriptor.d.ts +8 -0
- package/dist/cjs/src/sbtc/parseDescriptor.d.ts.map +1 -1
- package/dist/cjs/src/sbtc/parseDescriptor.js +7 -1
- 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 +163 -0
- package/dist/cjs/test/unit/pox5/input.d.ts +2 -0
- package/dist/cjs/test/unit/pox5/input.d.ts.map +1 -0
- package/dist/cjs/test/unit/pox5/input.js +113 -0
- package/dist/cjs/test/unit/pox5/recovery.d.ts +2 -0
- package/dist/cjs/test/unit/pox5/recovery.d.ts.map +1 -0
- package/dist/cjs/test/unit/pox5/recovery.js +87 -0
- package/dist/cjs/test/unit/pox5/validation.d.ts +2 -0
- package/dist/cjs/test/unit/pox5/validation.d.ts.map +1 -0
- package/dist/cjs/test/unit/pox5/validation.js +99 -0
- package/dist/cjs/test/unit/sbtc/parseDescriptor.js +14 -1
- 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 +74 -0
- package/dist/esm/pox5/index.d.ts +6 -0
- package/dist/esm/pox5/index.d.ts.map +1 -0
- package/dist/esm/pox5/index.js +6 -0
- package/dist/esm/pox5/input.d.ts +28 -0
- package/dist/esm/pox5/input.d.ts.map +1 -0
- package/dist/esm/pox5/input.js +43 -0
- package/dist/esm/pox5/parseDescriptor.d.ts +20 -0
- package/dist/esm/pox5/parseDescriptor.d.ts.map +1 -0
- package/dist/esm/pox5/parseDescriptor.js +109 -0
- package/dist/esm/pox5/recovery.d.ts +13 -0
- package/dist/esm/pox5/recovery.d.ts.map +1 -0
- package/dist/esm/pox5/recovery.js +68 -0
- package/dist/esm/pox5/validation.d.ts +12 -0
- package/dist/esm/pox5/validation.d.ts.map +1 -0
- package/dist/esm/pox5/validation.js +65 -0
- package/dist/esm/sbtc/parseDescriptor.d.ts +8 -0
- package/dist/esm/sbtc/parseDescriptor.d.ts.map +1 -1
- package/dist/esm/sbtc/parseDescriptor.js +7 -1
- package/package.json +8 -5
package/dist/esm/index.d.ts
CHANGED
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export * as sbtc from './sbtc';
|
|
2
|
-
|
|
2
|
+
export * as pox5 from './pox5';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLElBQUksTUFBTSxRQUFRLENBQUM7QUFDL0IsT0FBTyxLQUFLLElBQUksTUFBTSxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBhcyBzYnRjIGZyb20gJy4vc2J0Yyc7XG5leHBvcnQgKiBhcyBwb3g1IGZyb20gJy4vcG94NSc7XG4iXX0=
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { bip32, Descriptor } from '@bitgo/wasm-utxo';
|
|
2
|
+
type BIP32Interface = bip32.BIP32Interface;
|
|
3
|
+
export type Pox5StakerKey = BIP32Interface | Buffer;
|
|
4
|
+
export type Pox5LockupDescriptorParams = {
|
|
5
|
+
unlockHeight: number;
|
|
6
|
+
/** sha256(sha256(Clarity consensus principal bytes)). */
|
|
7
|
+
stakerCommitment: Buffer;
|
|
8
|
+
earlyExitKey: Buffer;
|
|
9
|
+
/** User, backup, and BitGo keys, all BIP32 or all concrete compressed keys. */
|
|
10
|
+
stakerKeys: [Pox5StakerKey, Pox5StakerKey, Pox5StakerKey];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Build the canonical PoX-5 P2WSH descriptor. The post-CLTV and early-exit
|
|
14
|
+
* paths share BitGo's standard 2-of-3 compressed-key multisig tail.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createPox5LockupDescriptor(params: Pox5LockupDescriptorParams): Descriptor;
|
|
17
|
+
/** Compile the PoX-5 P2WSH scriptPubKey at a BIP32 derivation index. */
|
|
18
|
+
export declare function createPox5LockupScriptPubKey(params: Pox5LockupDescriptorParams, derivationIndex?: number): Buffer;
|
|
19
|
+
/** Derive the compressed staker keys needed to prepare a witness at an index. */
|
|
20
|
+
export declare function derivePox5StakerKeys(stakerKeys: [BIP32Interface, BIP32Interface, BIP32Interface], index: number): [Buffer, Buffer, Buffer];
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=descriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptor.d.ts","sourceRoot":"","sources":["../../../src/pox5/descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE1D,KAAK,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,MAAM,CAAC;AAEpD,MAAM,MAAM,0BAA0B,GAAG;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,UAAU,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;CAC3D,CAAC;AA0CF;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,0BAA0B,GAAG,UAAU,CAqBzF;AAED,wEAAwE;AACxE,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,0BAA0B,EAAE,eAAe,SAAI,GAAG,MAAM,CAM5G;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,CAAC,cAAc,EAAE,cAAc,EAAE,cAAc,CAAC,EAC5D,KAAK,EAAE,MAAM,GACZ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAG1B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ast, Descriptor } from '@bitgo/wasm-utxo';
|
|
2
|
+
function validateCompressedKey(key, field) {
|
|
3
|
+
if (key.length !== 33 || (key[0] !== 0x02 && key[0] !== 0x03)) {
|
|
4
|
+
throw new Error(`${field} must be a 33-byte compressed public key`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
function isBip32Triple(keys) {
|
|
8
|
+
return keys.every((key) => !Buffer.isBuffer(key));
|
|
9
|
+
}
|
|
10
|
+
function asDescriptorKey(key, field) {
|
|
11
|
+
if (Buffer.isBuffer(key)) {
|
|
12
|
+
validateCompressedKey(key, field);
|
|
13
|
+
return key.toString('hex');
|
|
14
|
+
}
|
|
15
|
+
return key.neutered().toBase58() + '/*';
|
|
16
|
+
}
|
|
17
|
+
function validateParams(params) {
|
|
18
|
+
if (!Number.isSafeInteger(params.unlockHeight) || params.unlockHeight <= 0 || params.unlockHeight >= 500000000) {
|
|
19
|
+
throw new Error(`unlockHeight (${params.unlockHeight}) must be a positive block height below 500000000`);
|
|
20
|
+
}
|
|
21
|
+
if (params.stakerCommitment.length !== 32) {
|
|
22
|
+
throw new Error(`stakerCommitment must be 32 bytes (got ${params.stakerCommitment.length})`);
|
|
23
|
+
}
|
|
24
|
+
validateCompressedKey(params.earlyExitKey, 'earlyExitKey');
|
|
25
|
+
const bufferCount = params.stakerKeys.filter(Buffer.isBuffer).length;
|
|
26
|
+
if (bufferCount !== 0 && bufferCount !== params.stakerKeys.length) {
|
|
27
|
+
throw new Error('stakerKeys must contain either three BIP32 keys or three compressed public keys');
|
|
28
|
+
}
|
|
29
|
+
params.stakerKeys.forEach((key, index) => {
|
|
30
|
+
if (Buffer.isBuffer(key)) {
|
|
31
|
+
validateCompressedKey(key, `stakerKeys[${index}]`);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build the canonical PoX-5 P2WSH descriptor. The post-CLTV and early-exit
|
|
37
|
+
* paths share BitGo's standard 2-of-3 compressed-key multisig tail.
|
|
38
|
+
*/
|
|
39
|
+
export function createPox5LockupDescriptor(params) {
|
|
40
|
+
validateParams(params);
|
|
41
|
+
const stakerKeys = params.stakerKeys.map((key, index) => asDescriptorKey(key, `stakerKeys[${index}]`));
|
|
42
|
+
const miniscript = {
|
|
43
|
+
and_v: [
|
|
44
|
+
{
|
|
45
|
+
'v:or_i': [
|
|
46
|
+
{ after: params.unlockHeight },
|
|
47
|
+
{
|
|
48
|
+
and_v: [
|
|
49
|
+
{ 'v:sha256': params.stakerCommitment.toString('hex') },
|
|
50
|
+
{ pk: params.earlyExitKey.toString('hex') },
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{ multi: [2, ...stakerKeys] },
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
const descriptorString = ast.formatNode({ wsh: miniscript });
|
|
59
|
+
return Descriptor.fromString(descriptorString, isBip32Triple(params.stakerKeys) ? 'derivable' : 'definite');
|
|
60
|
+
}
|
|
61
|
+
/** Compile the PoX-5 P2WSH scriptPubKey at a BIP32 derivation index. */
|
|
62
|
+
export function createPox5LockupScriptPubKey(params, derivationIndex = 0) {
|
|
63
|
+
const descriptor = createPox5LockupDescriptor(params);
|
|
64
|
+
if (isBip32Triple(params.stakerKeys)) {
|
|
65
|
+
return Buffer.from(descriptor.atDerivationIndex(derivationIndex).scriptPubkey());
|
|
66
|
+
}
|
|
67
|
+
return Buffer.from(descriptor.scriptPubkey());
|
|
68
|
+
}
|
|
69
|
+
/** Derive the compressed staker keys needed to prepare a witness at an index. */
|
|
70
|
+
export function derivePox5StakerKeys(stakerKeys, index) {
|
|
71
|
+
const keys = stakerKeys.map((key) => Buffer.from(key.derive(index).publicKey));
|
|
72
|
+
return [keys[0], keys[1], keys[2]];
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVzY3JpcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wb3g1L2Rlc2NyaXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEdBQUcsRUFBUyxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQWUxRCxTQUFTLHFCQUFxQixDQUFDLEdBQVcsRUFBRSxLQUFhO0lBQ3ZELElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzlELE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLDBDQUEwQyxDQUFDLENBQUM7SUFDdEUsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FDcEIsSUFBOEM7SUFFOUMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUNwRCxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsR0FBa0IsRUFBRSxLQUFhO0lBQ3hELElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3pCLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNsQyxPQUFPLEdBQUcsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQztBQUMxQyxDQUFDO0FBRUQsU0FBUyxjQUFjLENBQUMsTUFBa0M7SUFDeEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLE1BQU0s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RCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUM7QUFDaEQsQ0FBQztBQUVELGlGQUFpRjtBQUNqRixNQUFNLFVBQVUsb0JBQW9CLENBQ2xDLFVBQTRELEVBQzVELEtBQWE7SUFFYixNQUFNLElBQUksR0FBRyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUMvRSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgYXN0LCBiaXAzMiwgRGVzY3JpcHRvciB9IGZyb20gJ0BiaXRnby93YXNtLXV0eG8nO1xuXG50eXBlIEJJUDMySW50ZXJmYWNlID0gYmlwMzIuQklQMzJJbnRlcmZhY2U7XG5cbmV4cG9ydCB0eXBlIFBveDVTdGFrZXJLZXkgPSBCSVAzMkludGVyZmFjZSB8IEJ1ZmZlcjtcblxuZXhwb3J0IHR5cGUgUG94NUxvY2t1cERlc2NyaXB0b3JQYXJhbXMgPSB7XG4gIHVubG9ja0hlaWdodDogbnVtYmVyO1xuICAvKiogc2hhMjU2KHNoYTI1NihDbGFyaXR5IGNvbnNlbnN1cyBwcmluY2lwYWwgYnl0ZXMpKS4gKi9cbiAgc3Rha2VyQ29tbWl0bWVudDogQnVmZmVyO1xuICBlYXJseUV4aXRLZXk6IEJ1ZmZlcjtcbiAgLyoqIFVzZXIsIGJhY2t1cCwgYW5kIEJpdEdvIGtleXMsIGFsbCBCSVAzMiBvciBhbGwgY29uY3JldGUgY29tcHJlc3NlZCBrZXlzLiAqL1xuICBzdGFrZXJLZXlzOiBbUG94NVN0YWtlcktleSwgUG94NVN0YWtlcktleSwgUG94NVN0YWtlcktleV07XG59O1xuXG5mdW5jdGlvbiB2YWxpZGF0ZUNvbXByZXNzZWRLZXkoa2V5OiBCdWZmZXIsIGZpZWxkOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKGtleS5sZW5ndGggIT09IDMzIHx8IChrZXlbMF0gIT09IDB4MDIgJiYga2V5WzBdICE9PSAweDAzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtmaWVsZH0gbXVzdCBiZSBhIDMzLWJ5dGUgY29tcHJlc3NlZCBwdWJsaWMga2V5YCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNCaXAzMlRyaXBsZShcbiAga2V5czogUG94NUxvY2t1cERlc2NyaXB0b3JQYXJhbXNbJ3N0YWtlcktleXMnXVxuKToga2V5cyBpcyBbQklQMzJJbnRlcmZhY2UsIEJJUDMySW50ZXJmYWNlLCBCSVAzMkludGVyZmFjZV0ge1xuICByZXR1cm4ga2V5cy5ldmVyeSgoa2V5KSA9PiAhQnVmZmVyLmlzQnVmZmVyKGtleSkpO1xufVxuXG5mdW5jdGlvbiBhc0Rlc2NyaXB0b3JLZXkoa2V5OiBQb3g1U3Rha2VyS2V5LCBmaWVsZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihrZXkpKSB7XG4gICAgdmFsaWRhdGVDb21wcmVzc2VkS2V5KGtleSwgZmllbGQpO1xuICAgIHJldHVybiBrZXkudG9TdHJpbmcoJ2hleCcpO1xuICB9XG4gIHJldHVybiBrZXkubmV1dGVyZWQoKS50b0Jhc2U1OCgpICsgJy8qJztcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVQYXJhbXMocGFyYW1zOiBQb3g1TG9ja3VwRGVzY3JpcHRvclBhcmFtcyk6IHZvaWQge1xuICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKHBhcmFtcy51bmxvY2tIZWlnaHQpIHx8IHBhcmFtcy51bmxvY2tIZWlnaHQgPD0gMCB8fCBwYXJhbXMudW5sb2NrSGVpZ2h0ID49IDUwMF8wMDBfMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGB1bmxvY2tIZWlnaHQgKCR7cGFyYW1zLnVubG9ja0hlaWdodH0pIG11c3QgYmUgYSBwb3NpdGl2ZSBibG9jayBoZWlnaHQgYmVsb3cgNTAwMDAwMDAwYCk7XG4gIH1cbiAgaWYgKHBhcmFtcy5zdGFrZXJDb21taXRtZW50Lmxlbmd0aCAhPT0gMzIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHN0YWtlckNvbW1pdG1lbnQgbXVzdCBiZSAzMiBieXRlcyAoZ290ICR7cGFyYW1zLnN0YWtlckNvbW1pdG1lbnQubGVuZ3RofSlgKTtcbiAgfVxuICB2YWxpZGF0ZUNvbXByZXNzZWRLZXkocGFyYW1zLmVhcmx5RXhpdEtleSwgJ2Vhcmx5RXhpdEtleScpO1xuXG4gIGNvbnN0IGJ1ZmZlckNvdW50ID0gcGFyYW1zLnN0YWtlcktleXMuZmlsdGVyKEJ1ZmZlci5pc0J1ZmZlcikubGVuZ3RoO1xuICBpZiAoYnVmZmVyQ291bnQgIT09IDAgJiYgYnVmZmVyQ291bnQgIT09IHBhcmFtcy5zdGFrZXJLZXlzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc3Rha2VyS2V5cyBtdXN0IGNvbnRhaW4gZWl0aGVyIHRocmVlIEJJUDMyIGtleXMgb3IgdGhyZWUgY29tcHJlc3NlZCBwdWJsaWMga2V5cycpO1xuICB9XG4gIHBhcmFtcy5zdGFrZXJLZXlzLmZvckVhY2goKGtleSwgaW5kZXgpID0+IHtcbiAgICBpZiAoQnVmZmVyLmlzQnVmZmVyKGtleSkpIHtcbiAgICAgIHZhbGlkYXRlQ29tcHJlc3NlZEtleShrZXksIGBzdGFrZXJLZXlzWyR7aW5kZXh9XWApO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogQnVpbGQgdGhlIGNhbm9uaWNhbCBQb1gtNSBQMldTSCBkZXNjcmlwdG9yLiBUaGUgcG9zdC1DTFRWIGFuZCBlYXJseS1leGl0XG4gKiBwYXRocyBzaGFyZSBCaXRHbydzIHN0YW5kYXJkIDItb2YtMyBjb21wcmVzc2VkLWtleSBtdWx0aXNpZyB0YWlsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUG94NUxvY2t1cERlc2NyaXB0b3IocGFyYW1zOiBQb3g1TG9ja3VwRGVzY3JpcHRvclBhcmFtcyk6IERlc2NyaXB0b3Ige1xuICB2YWxpZGF0ZVBhcmFtcyhwYXJhbXMpO1xuICBjb25zdCBzdGFrZXJLZXlzID0gcGFyYW1zLnN0YWtlcktleXMubWFwKChrZXksIGluZGV4KSA9PiBhc0Rlc2NyaXB0b3JLZXkoa2V5LCBgc3Rha2VyS2V5c1ske2luZGV4fV1gKSk7XG4gIGNvbnN0IG1pbmlzY3JpcHQ6IGFzdC5NaW5pc2NyaXB0Tm9kZSA9IHtcbiAgICBhbmRfdjogW1xuICAgICAge1xuICAgICAgICAndjpvcl9pJzogW1xuICAgICAgICAgIHsgYWZ0ZXI6IHBhcmFtcy51bmxvY2tIZWlnaHQgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhbmRfdjogW1xuICAgICAgICAgICAgICB7ICd2OnNoYTI1Nic6IHBhcmFtcy5zdGFrZXJDb21taXRtZW50LnRvU3RyaW5nKCdoZXgnKSB9LFxuICAgICAgICAgICAgICB7IHBrOiBwYXJhbXMuZWFybHlFeGl0S2V5LnRvU3RyaW5nKCdoZXgnKSB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICAgIHsgbXVsdGk6IFsyLCAuLi5zdGFrZXJLZXlzXSB9LFxuICAgIF0sXG4gIH07XG4gIGNvbnN0IGRlc2NyaXB0b3JTdHJpbmcgPSBhc3QuZm9ybWF0Tm9kZSh7IHdzaDogbWluaXNjcmlwdCB9KTtcbiAgcmV0dXJuIERlc2NyaXB0b3IuZnJvbVN0cmluZyhkZXNjcmlwdG9yU3RyaW5nLCBpc0JpcDMyVHJpcGxlKHBhcmFtcy5zdGFrZXJLZXlzKSA/ICdkZXJpdmFibGUnIDogJ2RlZmluaXRlJyk7XG59XG5cbi8qKiBDb21waWxlIHRoZSBQb1gtNSBQMldTSCBzY3JpcHRQdWJLZXkgYXQgYSBCSVAzMiBkZXJpdmF0aW9uIGluZGV4LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVBveDVMb2NrdXBTY3JpcHRQdWJLZXkocGFyYW1zOiBQb3g1TG9ja3VwRGVzY3JpcHRvclBhcmFtcywgZGVyaXZhdGlvbkluZGV4ID0gMCk6IEJ1ZmZlciB7XG4gIGNvbnN0IGRlc2NyaXB0b3IgPSBjcmVhdGVQb3g1TG9ja3VwRGVzY3JpcHRvcihwYXJhbXMpO1xuICBpZiAoaXNCaXAzMlRyaXBsZShwYXJhbXMuc3Rha2VyS2V5cykpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oZGVzY3JpcHRvci5hdERlcml2YXRpb25JbmRleChkZXJpdmF0aW9uSW5kZXgpLnNjcmlwdFB1YmtleSgpKTtcbiAgfVxuICByZXR1cm4gQnVmZmVyLmZyb20oZGVzY3JpcHRvci5zY3JpcHRQdWJrZXkoKSk7XG59XG5cbi8qKiBEZXJpdmUgdGhlIGNvbXByZXNzZWQgc3Rha2VyIGtleXMgbmVlZGVkIHRvIHByZXBhcmUgYSB3aXRuZXNzIGF0IGFuIGluZGV4LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlcml2ZVBveDVTdGFrZXJLZXlzKFxuICBzdGFrZXJLZXlzOiBbQklQMzJJbnRlcmZhY2UsIEJJUDMySW50ZXJmYWNlLCBCSVAzMkludGVyZmFjZV0sXG4gIGluZGV4OiBudW1iZXJcbik6IFtCdWZmZXIsIEJ1ZmZlciwgQnVmZmVyXSB7XG4gIGNvbnN0IGtleXMgPSBzdGFrZXJLZXlzLm1hcCgoa2V5KSA9PiBCdWZmZXIuZnJvbShrZXkuZGVyaXZlKGluZGV4KS5wdWJsaWNLZXkpKTtcbiAgcmV0dXJuIFtrZXlzWzBdLCBrZXlzWzFdLCBrZXlzWzJdXTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/pox5/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './descriptor';
|
|
2
|
+
export * from './parseDescriptor';
|
|
3
|
+
export * from './input';
|
|
4
|
+
export * from './validation';
|
|
5
|
+
export * from './recovery';
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcG94NS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLG1CQUFtQixDQUFDO0FBQ2xDLGNBQWMsU0FBUyxDQUFDO0FBQ3hCLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsWUFBWSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9kZXNjcmlwdG9yJztcbmV4cG9ydCAqIGZyb20gJy4vcGFyc2VEZXNjcmlwdG9yJztcbmV4cG9ydCAqIGZyb20gJy4vaW5wdXQnO1xuZXhwb3J0ICogZnJvbSAnLi92YWxpZGF0aW9uJztcbmV4cG9ydCAqIGZyb20gJy4vcmVjb3ZlcnknO1xuIl19
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Descriptor, Psbt, descriptorWallet } from '@bitgo/wasm-utxo';
|
|
2
|
+
import { Pox5DescriptorInfo } from './parseDescriptor';
|
|
3
|
+
type ResolvedPox5DescriptorInfo = Pox5DescriptorInfo & {
|
|
4
|
+
stakerKeys: [Buffer, Buffer, Buffer];
|
|
5
|
+
};
|
|
6
|
+
export type Pox5DescriptorMatch = {
|
|
7
|
+
/** The concrete descriptor whose script matches the input. */
|
|
8
|
+
descriptor: Descriptor;
|
|
9
|
+
/** The derivation index used for a wildcard descriptor, if any. */
|
|
10
|
+
index: number | undefined;
|
|
11
|
+
info: ResolvedPox5DescriptorInfo;
|
|
12
|
+
};
|
|
13
|
+
/** A canonical PoX-5 descriptor match bound to a native PSBT input. */
|
|
14
|
+
export type Pox5InputMatch = Pox5DescriptorMatch & {
|
|
15
|
+
inputIndex: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Find and parse a canonical PoX-5 descriptor for a native PSBT input projection.
|
|
19
|
+
*
|
|
20
|
+
* Foreign root derivations are ignored by the shared native descriptor matcher. A
|
|
21
|
+
* match is returned only when all three staker keys can be resolved at the matched
|
|
22
|
+
* descriptor index.
|
|
23
|
+
*/
|
|
24
|
+
export declare function findPox5DescriptorForInput(input: descriptorWallet.PsbtInput, descriptors: descriptorWallet.DescriptorMap): Pox5DescriptorMatch | undefined;
|
|
25
|
+
/** Find and parse a canonical PoX-5 descriptor for one native PSBT input. */
|
|
26
|
+
export declare function matchPox5Input(psbt: Psbt, inputIndex: number, descriptors: descriptorWallet.DescriptorMap): Pox5InputMatch | undefined;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/pox5/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAA6B,MAAM,mBAAmB,CAAC;AAElF,KAAK,0BAA0B,GAAG,kBAAkB,GAAG;IACrD,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,8DAA8D;IAC9D,UAAU,EAAE,UAAU,CAAC;IACvB,mEAAmE;IACnE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,EAAE,0BAA0B,CAAC;CAClC,CAAC;AAEF,uEAAuE;AACvE,MAAM,MAAM,cAAc,GAAG,mBAAmB,GAAG;IACjD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAMF;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,gBAAgB,CAAC,SAAS,EACjC,WAAW,EAAE,gBAAgB,CAAC,aAAa,GAC1C,mBAAmB,GAAG,SAAS,CAsBjC;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,gBAAgB,CAAC,aAAa,GAC1C,cAAc,GAAG,SAAS,CAI5B"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { descriptorWallet } from '@bitgo/wasm-utxo';
|
|
2
|
+
import { parsePox5LockupDescriptor } from './parseDescriptor';
|
|
3
|
+
function getConcreteDescriptor(descriptor, index) {
|
|
4
|
+
return index === undefined ? descriptor : descriptor.atDerivationIndex(index);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Find and parse a canonical PoX-5 descriptor for a native PSBT input projection.
|
|
8
|
+
*
|
|
9
|
+
* Foreign root derivations are ignored by the shared native descriptor matcher. A
|
|
10
|
+
* match is returned only when all three staker keys can be resolved at the matched
|
|
11
|
+
* descriptor index.
|
|
12
|
+
*/
|
|
13
|
+
export function findPox5DescriptorForInput(input, descriptors) {
|
|
14
|
+
try {
|
|
15
|
+
const matched = descriptorWallet.findDescriptorForInput(input, descriptors);
|
|
16
|
+
if (!matched) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const descriptor = getConcreteDescriptor(matched.descriptor, matched.index);
|
|
20
|
+
const info = parsePox5LockupDescriptor(descriptor);
|
|
21
|
+
if (!info?.stakerKeys) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
descriptor,
|
|
26
|
+
index: matched.index,
|
|
27
|
+
info: {
|
|
28
|
+
...info,
|
|
29
|
+
stakerKeys: info.stakerKeys,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Find and parse a canonical PoX-5 descriptor for one native PSBT input. */
|
|
38
|
+
export function matchPox5Input(psbt, inputIndex, descriptors) {
|
|
39
|
+
const input = psbt.getInputs()[inputIndex];
|
|
40
|
+
const match = input ? findPox5DescriptorForInput(input, descriptors) : undefined;
|
|
41
|
+
return match ? { ...match, inputIndex } : undefined;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcG94NS9pbnB1dC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQW9CLGdCQUFnQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFdEUsT0FBTyxFQUFzQix5QkFBeUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBbUJsRixTQUFTLHFCQUFxQixDQUFDLFVBQXNCLEVBQUUsS0FBeUI7SUFDOUUsT0FBTyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoRixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLDBCQUEwQixDQUN4QyxLQUFpQyxFQUNqQyxXQUEyQztJQUUzQyxJQUFJLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDNUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2IsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztRQUNELE1BQU0sVUFBVSxHQUFHLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVFLE1BQU0sSUFBSSxHQUFHLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLENBQUM7WUFDdEIsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztRQUNELE9BQU87WUFDTCxVQUFVO1lBQ1YsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO1lBQ3BCLElBQUksRUFBRTtnQkFDSixHQUFHLElBQUk7Z0JBQ1AsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO2FBQzVCO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQztBQUVELDZFQUE2RTtBQUM3RSxNQUFNLFVBQVUsY0FBYyxDQUM1QixJQUFVLEVBQ1YsVUFBa0IsRUFDbEIsV0FBMkM7SUFFM0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzNDLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsMEJBQTBCLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDakYsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxLQUFLLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUN0RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVzY3JpcHRvciwgUHNidCwgZGVzY3JpcHRvcldhbGxldCB9IGZyb20gJ0BiaXRnby93YXNtLXV0eG8nO1xuXG5pbXBvcnQgeyBQb3g1RGVzY3JpcHRvckluZm8sIHBhcnNlUG94NUxvY2t1cERlc2NyaXB0b3IgfSBmcm9tICcuL3BhcnNlRGVzY3JpcHRvcic7XG5cbnR5cGUgUmVzb2x2ZWRQb3g1RGVzY3JpcHRvckluZm8gPSBQb3g1RGVzY3JpcHRvckluZm8gJiB7XG4gIHN0YWtlcktleXM6IFtCdWZmZXIsIEJ1ZmZlciwgQnVmZmVyXTtcbn07XG5cbmV4cG9ydCB0eXBlIFBveDVEZXNjcmlwdG9yTWF0Y2ggPSB7XG4gIC8qKiBUaGUgY29uY3JldGUgZGVzY3JpcHRvciB3aG9zZSBzY3JpcHQgbWF0Y2hlcyB0aGUgaW5wdXQuICovXG4gIGRlc2NyaXB0b3I6IERlc2NyaXB0b3I7XG4gIC8qKiBUaGUgZGVyaXZhdGlvbiBpbmRleCB1c2VkIGZvciBhIHdpbGRjYXJkIGRlc2NyaXB0b3IsIGlmIGFueS4gKi9cbiAgaW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgaW5mbzogUmVzb2x2ZWRQb3g1RGVzY3JpcHRvckluZm87XG59O1xuXG4vKiogQSBjYW5vbmljYWwgUG9YLTUgZGVzY3JpcHRvciBtYXRjaCBib3VuZCB0byBhIG5hdGl2ZSBQU0JUIGlucHV0LiAqL1xuZXhwb3J0IHR5cGUgUG94NUlucHV0TWF0Y2ggPSBQb3g1RGVzY3JpcHRvck1hdGNoICYge1xuICBpbnB1dEluZGV4OiBudW1iZXI7XG59O1xuXG5mdW5jdGlvbiBnZXRDb25jcmV0ZURlc2NyaXB0b3IoZGVzY3JpcHRvcjogRGVzY3JpcHRvciwgaW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZCk6IERlc2NyaXB0b3Ige1xuICByZXR1cm4gaW5kZXggPT09IHVuZGVmaW5lZCA/IGRlc2NyaXB0b3IgOiBkZXNjcmlwdG9yLmF0RGVyaXZhdGlvbkluZGV4KGluZGV4KTtcbn1cblxuLyoqXG4gKiBGaW5kIGFuZCBwYXJzZSBhIGNhbm9uaWNhbCBQb1gtNSBkZXNjcmlwdG9yIGZvciBhIG5hdGl2ZSBQU0JUIGlucHV0IHByb2plY3Rpb24uXG4gKlxuICogRm9yZWlnbiByb290IGRlcml2YXRpb25zIGFyZSBpZ25vcmVkIGJ5IHRoZSBzaGFyZWQgbmF0aXZlIGRlc2NyaXB0b3IgbWF0Y2hlci4gQVxuICogbWF0Y2ggaXMgcmV0dXJuZWQgb25seSB3aGVuIGFsbCB0aHJlZSBzdGFrZXIga2V5cyBjYW4gYmUgcmVzb2x2ZWQgYXQgdGhlIG1hdGNoZWRcbiAqIGRlc2NyaXB0b3IgaW5kZXguXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kUG94NURlc2NyaXB0b3JGb3JJbnB1dChcbiAgaW5wdXQ6IGRlc2NyaXB0b3JXYWxsZXQuUHNidElucHV0LFxuICBkZXNjcmlwdG9yczogZGVzY3JpcHRvcldhbGxldC5EZXNjcmlwdG9yTWFwXG4pOiBQb3g1RGVzY3JpcHRvck1hdGNoIHwgdW5kZWZpbmVkIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBtYXRjaGVkID0gZGVzY3JpcHRvcldhbGxldC5maW5kRGVzY3JpcHRvckZvcklucHV0KGlucHV0LCBkZXNjcmlwdG9ycyk7XG4gICAgaWYgKCFtYXRjaGVkKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCBkZXNjcmlwdG9yID0gZ2V0Q29uY3JldGVEZXNjcmlwdG9yKG1hdGNoZWQuZGVzY3JpcHRvciwgbWF0Y2hlZC5pbmRleCk7XG4gICAgY29uc3QgaW5mbyA9IHBhcnNlUG94NUxvY2t1cERlc2NyaXB0b3IoZGVzY3JpcHRvcik7XG4gICAgaWYgKCFpbmZvPy5zdGFrZXJLZXlzKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgZGVzY3JpcHRvcixcbiAgICAgIGluZGV4OiBtYXRjaGVkLmluZGV4LFxuICAgICAgaW5mbzoge1xuICAgICAgICAuLi5pbmZvLFxuICAgICAgICBzdGFrZXJLZXlzOiBpbmZvLnN0YWtlcktleXMsXG4gICAgICB9LFxuICAgIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqIEZpbmQgYW5kIHBhcnNlIGEgY2Fub25pY2FsIFBvWC01IGRlc2NyaXB0b3IgZm9yIG9uZSBuYXRpdmUgUFNCVCBpbnB1dC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaFBveDVJbnB1dChcbiAgcHNidDogUHNidCxcbiAgaW5wdXRJbmRleDogbnVtYmVyLFxuICBkZXNjcmlwdG9yczogZGVzY3JpcHRvcldhbGxldC5EZXNjcmlwdG9yTWFwXG4pOiBQb3g1SW5wdXRNYXRjaCB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGlucHV0ID0gcHNidC5nZXRJbnB1dHMoKVtpbnB1dEluZGV4XTtcbiAgY29uc3QgbWF0Y2ggPSBpbnB1dCA/IGZpbmRQb3g1RGVzY3JpcHRvckZvcklucHV0KGlucHV0LCBkZXNjcmlwdG9ycykgOiB1bmRlZmluZWQ7XG4gIHJldHVybiBtYXRjaCA/IHsgLi4ubWF0Y2gsIGlucHV0SW5kZXggfSA6IHVuZGVmaW5lZDtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Descriptor, ast } from '@bitgo/wasm-utxo';
|
|
2
|
+
export type Pox5DescriptorInfo = {
|
|
3
|
+
unlockHeight: number;
|
|
4
|
+
stakerCommitment: Buffer;
|
|
5
|
+
earlyExitKey: Buffer;
|
|
6
|
+
stakerKeyStrings: [string, string, string];
|
|
7
|
+
stakerKeys: [Buffer, Buffer, Buffer] | undefined;
|
|
8
|
+
miniscriptNode: ast.MiniscriptNode;
|
|
9
|
+
};
|
|
10
|
+
/** @deprecated Use Pox5DescriptorInfo instead. */
|
|
11
|
+
export type ParsedPox5LockupDescriptor = Pox5DescriptorInfo;
|
|
12
|
+
/**
|
|
13
|
+
* Parse only the canonical PoX-5 descriptor template. Other descriptors return
|
|
14
|
+
* undefined; malformed fields within the template throw so callers cannot finalize
|
|
15
|
+
* a script under an ambiguous policy.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parsePox5LockupDescriptor(descriptor: Descriptor | ast.DescriptorNode): Pox5DescriptorInfo | undefined;
|
|
18
|
+
/** Serialize the canonical 2-of-3 staker subscript for a concrete PoX-5 descriptor. */
|
|
19
|
+
export declare function getPox5UnlockBytes(descriptor: Descriptor): Buffer;
|
|
20
|
+
//# sourceMappingURL=parseDescriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseDescriptor.d.ts","sourceRoot":"","sources":["../../../src/pox5/parseDescriptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,UAAU,EAAE,GAAG,EAAoB,MAAM,kBAAkB,CAAC;AAI5E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACjD,cAAc,EAAE,GAAG,CAAC,cAAc,CAAC;CACpC,CAAC;AAEF,kDAAkD;AAClD,MAAM,MAAM,0BAA0B,GAAG,kBAAkB,CAAC;AA2C5D;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,UAAU,GAAG,GAAG,CAAC,cAAc,GAAG,kBAAkB,GAAG,SAAS,CAmDrH;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAiBjE"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { BIP32, Descriptor, ast, descriptorWallet } from '@bitgo/wasm-utxo';
|
|
2
|
+
const COMPRESSED_KEY = /^(02|03)[0-9a-fA-F]{64}$/;
|
|
3
|
+
const XPUB_WITH_INDEX = /^([1-9A-HJ-NP-Za-km-z]+)\/(\d+)$/;
|
|
4
|
+
function asNumber(value, field) {
|
|
5
|
+
if (typeof value !== 'number') {
|
|
6
|
+
throw new Error(`${field} must be a number`);
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
function asString(value, field) {
|
|
11
|
+
if (typeof value !== 'string') {
|
|
12
|
+
throw new Error(`${field} must be a string`);
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function parseCompressedKey(value, field) {
|
|
17
|
+
if (!COMPRESSED_KEY.test(value)) {
|
|
18
|
+
throw new Error(`${field} must be a compressed public key`);
|
|
19
|
+
}
|
|
20
|
+
return Buffer.from(value, 'hex');
|
|
21
|
+
}
|
|
22
|
+
function resolveStakerKey(value) {
|
|
23
|
+
if (COMPRESSED_KEY.test(value)) {
|
|
24
|
+
return Buffer.from(value, 'hex');
|
|
25
|
+
}
|
|
26
|
+
const match = value.match(XPUB_WITH_INDEX);
|
|
27
|
+
if (!match) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const [, xpub, indexString] = match;
|
|
31
|
+
const index = Number.parseInt(indexString, 10);
|
|
32
|
+
try {
|
|
33
|
+
return Buffer.from(BIP32.fromBase58(xpub).derive(index).publicKey);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse only the canonical PoX-5 descriptor template. Other descriptors return
|
|
41
|
+
* undefined; malformed fields within the template throw so callers cannot finalize
|
|
42
|
+
* a script under an ambiguous policy.
|
|
43
|
+
*/
|
|
44
|
+
export function parsePox5LockupDescriptor(descriptor) {
|
|
45
|
+
const matcher = new descriptorWallet.PatternMatcher();
|
|
46
|
+
const descriptorNode = descriptor instanceof Descriptor ? ast.fromDescriptor(descriptor) : descriptor;
|
|
47
|
+
const matched = matcher.match(descriptorNode, { wsh: { $var: 'miniscript' } });
|
|
48
|
+
if (!matched) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const miniscriptNode = matched.miniscript;
|
|
52
|
+
const pattern = {
|
|
53
|
+
and_v: [
|
|
54
|
+
{
|
|
55
|
+
'v:or_i': [
|
|
56
|
+
{ after: { $var: 'unlockHeight' } },
|
|
57
|
+
{ and_v: [{ 'v:sha256': { $var: 'stakerCommitment' } }, { pk: { $var: 'earlyExitKey' } }] },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{ multi: { $var: 'stakerMulti' } },
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
const fields = matcher.match(miniscriptNode, pattern);
|
|
64
|
+
if (!fields) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const unlockHeight = asNumber(fields.unlockHeight, 'after argument');
|
|
68
|
+
if (!Number.isSafeInteger(unlockHeight) || unlockHeight <= 0 || unlockHeight >= 500000000) {
|
|
69
|
+
throw new Error(`unlockHeight (${unlockHeight}) must be a positive block height below 500000000`);
|
|
70
|
+
}
|
|
71
|
+
const commitmentHex = asString(fields.stakerCommitment, 'sha256 commitment');
|
|
72
|
+
if (!/^[0-9a-fA-F]{64}$/.test(commitmentHex)) {
|
|
73
|
+
throw new Error('stakerCommitment must be 32 bytes');
|
|
74
|
+
}
|
|
75
|
+
const earlyExitKey = parseCompressedKey(asString(fields.earlyExitKey, 'early exit key'), 'earlyExitKey');
|
|
76
|
+
if (!Array.isArray(fields.stakerMulti) || fields.stakerMulti.length !== 4 || fields.stakerMulti[0] !== 2) {
|
|
77
|
+
throw new Error('staker multi must be a 2-of-3 multisig');
|
|
78
|
+
}
|
|
79
|
+
const stakerKeyStrings = fields.stakerMulti.slice(1).map((key, index) => asString(key, `staker key ${index}`));
|
|
80
|
+
const resolvedKeys = stakerKeyStrings.map(resolveStakerKey);
|
|
81
|
+
return {
|
|
82
|
+
unlockHeight,
|
|
83
|
+
stakerCommitment: Buffer.from(commitmentHex, 'hex'),
|
|
84
|
+
earlyExitKey,
|
|
85
|
+
stakerKeyStrings: [stakerKeyStrings[0], stakerKeyStrings[1], stakerKeyStrings[2]],
|
|
86
|
+
stakerKeys: resolvedKeys.every((key) => key !== undefined)
|
|
87
|
+
? [resolvedKeys[0], resolvedKeys[1], resolvedKeys[2]]
|
|
88
|
+
: undefined,
|
|
89
|
+
miniscriptNode,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** Serialize the canonical 2-of-3 staker subscript for a concrete PoX-5 descriptor. */
|
|
93
|
+
export function getPox5UnlockBytes(descriptor) {
|
|
94
|
+
const parsed = parsePox5LockupDescriptor(descriptor);
|
|
95
|
+
if (!parsed) {
|
|
96
|
+
throw new Error('Descriptor is not a canonical PoX-5 lockup descriptor');
|
|
97
|
+
}
|
|
98
|
+
if (!parsed.stakerKeys) {
|
|
99
|
+
throw new Error('PoX-5 descriptor keys must be concrete before deriving unlockBytes');
|
|
100
|
+
}
|
|
101
|
+
const keyPushes = parsed.stakerKeys.map((key, index) => {
|
|
102
|
+
if (key.length !== 33 || (key[0] !== 0x02 && key[0] !== 0x03)) {
|
|
103
|
+
throw new Error(`PoX-5 staker key ${index} must be a 33-byte compressed public key`);
|
|
104
|
+
}
|
|
105
|
+
return Buffer.concat([Buffer.of(key.length), key]);
|
|
106
|
+
});
|
|
107
|
+
return Buffer.concat([Buffer.of(0x52), ...keyPushes, Buffer.of(0x53, 0xae)]);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VEZXNjcmlwdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3BveDUvcGFyc2VEZXNjcmlwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBZ0I1RSxNQUFNLGNBQWMsR0FBRywwQkFBMEIsQ0FBQztBQUNsRCxNQUFNLGVBQWUsR0FBRyxrQ0FBa0MsQ0FBQztBQUUzRCxTQUFTLFFBQVEsQ0FBQyxLQUFjLEVBQUUsS0FBYTtJQUM3QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLG1CQUFtQixDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVELFNBQVMsUUFBUSxDQUFDLEtBQWMsRUFBRSxLQUFhO0lBQzdDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDOUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssbUJBQW1CLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBRUQsU0FBUyxrQkFBa0IsQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUN0RCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLGtDQUFrQyxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDbkMsQ0FBQztBQUVELFNBQVMsZ0JBQWdCLENBQUMsS0FBYTtJQUNyQyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxD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V2FsbGV0IH0gZnJvbSAnQGJpdGdvL3dhc20tdXR4byc7XG5cbnR5cGUgUGF0dGVybiA9IGRlc2NyaXB0b3JXYWxsZXQuUGF0dGVybjtcblxuZXhwb3J0IHR5cGUgUG94NURlc2NyaXB0b3JJbmZvID0ge1xuICB1bmxvY2tIZWlnaHQ6IG51bWJlcjtcbiAgc3Rha2VyQ29tbWl0bWVudDogQnVmZmVyO1xuICBlYXJseUV4aXRLZXk6IEJ1ZmZlcjtcbiAgc3Rha2VyS2V5U3RyaW5nczogW3N0cmluZywgc3RyaW5nLCBzdHJpbmddO1xuICBzdGFrZXJLZXlzOiBbQnVmZmVyLCBCdWZmZXIsIEJ1ZmZlcl0gfCB1bmRlZmluZWQ7XG4gIG1pbmlzY3JpcHROb2RlOiBhc3QuTWluaXNjcmlwdE5vZGU7XG59O1xuXG4vKiogQGRlcHJlY2F0ZWQgVXNlIFBveDVEZXNjcmlwdG9ySW5mbyBpbnN0ZWFkLiAqL1xuZXhwb3J0IHR5cGUgUGFyc2VkUG94NUxvY2t1cERlc2NyaXB0b3IgPSBQb3g1RGVzY3JpcHRvckluZm87XG5cbmNvbnN0IENPTVBSRVNTRURfS0VZID0gL14oMDJ8MDMpWzAtOWEtZkEtRl17NjR9JC87XG5jb25zdCBYUFVCX1dJVEhfSU5ERVggPSAvXihbMS05QS1ISi1OUC1aYS1rbS16XSspXFwvKFxcZCspJC87XG5cbmZ1bmN0aW9uIGFzTnVtYmVyKHZhbHVlOiB1bmtub3duLCBmaWVsZDogc3RyaW5nKTogbnVtYmVyIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZmllbGR9IG11c3QgYmUgYSBudW1iZXJgKTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIGFzU3RyaW5nKHZhbHVlOiB1bmtub3duLCBmaWVsZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZmllbGR9IG11c3QgYmUgYSBzdHJpbmdgKTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIHBhcnNlQ29tcHJlc3NlZEtleSh2YWx1ZTogc3RyaW5nLCBmaWVsZDogc3RyaW5nKTogQnVmZmVyIHtcbiAgaWYgKCFDT01QUkVTU0VEX0tFWS50ZXN0KHZhbHVlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtmaWVsZH0gbXVzdCBiZSBhIGNvbXByZXNzZWQgcHVibGljIGtleWApO1xuICB9XG4gIHJldHVybiBCdWZmZXIuZnJvbSh2YWx1ZSwgJ2hleCcpO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3Rha2VyS2V5KHZhbHVlOiBzdHJpbmcpOiBCdWZmZXIgfCB1bmRlZmluZWQge1xuICBpZiAoQ09NUFJFU1NFRF9LRVkudGVzdCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20odmFsdWUsICdoZXgnKTtcbiAgfVxuICBjb25zdCBtYXRjaCA9IHZhbHVlLm1hdGNoKFhQVUJfV0lUSF9JTkRFWCk7XG4gIGlmICghbWF0Y2gpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGNvbnN0IFssIHhwdWIsIGluZGV4U3RyaW5nXSA9IG1hdGNoO1xuICBjb25zdCBpbmRleCA9IE51bWJlci5wYXJzZUludChpbmRleFN0cmluZywgMTApO1xuICB0cnkge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShCSVAzMi5mcm9tQmFzZTU4KHhwdWIpLmRlcml2ZShpbmRleCkucHVibGljS2V5KTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIFBhcnNlIG9ubHkgdGhlIGNhbm9uaWNhbCBQb1gtNSBkZXNjcmlwdG9yIHRlbXBsYXRlLiBPdGhlciBkZXNjcmlwdG9ycyByZXR1cm5cbiAqIHVuZGVmaW5lZDsgbWFsZm9ybWVkIGZpZWxkcyB3aXRoaW4gdGhlIHRlbXBsYXRlIHRocm93IHNvIGNhbGxlcnMgY2Fubm90IGZpbmFsaXplXG4gKiBhIHNjcmlwdCB1bmRlciBhbiBhbWJpZ3VvdXMgcG9saWN5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VQb3g1TG9ja3VwRGVzY3JpcHRvcihkZXNjcmlwdG9yOiBEZXNjcmlwdG9yIHwgYXN0LkRlc2NyaXB0b3JOb2RlKTogUG94NURlc2NyaXB0b3JJbmZvIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgbWF0Y2hlciA9IG5ldyBkZXNjcmlwdG9yV2FsbGV0LlBhdHRlcm5NYXRjaGVyKCk7XG4gIGNvbnN0IGRlc2NyaXB0b3JOb2RlID0gZGVzY3JpcHRvciBpbnN0YW5jZW9mIERlc2NyaXB0b3IgPyBhc3QuZnJvbURlc2NyaXB0b3IoZGVzY3JpcHRvcikgOiBkZXNjcmlwdG9yO1xuICBjb25zdCBtYXRjaGVkID0gbWF0Y2hlci5tYXRjaChkZXNjcmlwdG9yTm9kZSwgeyB3c2g6IHsgJHZhcjogJ21pbmlzY3JpcHQnIH0gfSk7XG4gIGlmICghbWF0Y2hlZCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBtaW5pc2NyaXB0Tm9kZSA9IG1hdGNoZWQubWluaXNjcmlwdCBhcyBhc3QuTWluaXNjcmlwdE5vZGU7XG4gIGNvbnN0IHBhdHRlcm46IFBhdHRlcm4gPSB7XG4gICAgYW5kX3Y6IFtcbiAgICAgIHtcbiAgICAgICAgJ3Y6b3JfaSc6IFtcbiAgICAgICAgICB7IGFmdGVyOiB7ICR2YXI6ICd1bmxvY2tIZWlnaHQnIH0gfSxcbiAgICAgICAgICB7IGFuZF92OiBbeyAndjpzaGEyNTYnOiB7ICR2YXI6ICdzdGFrZXJDb21taXRtZW50JyB9IH0sIHsgcGs6IHsgJHZhcjogJ2Vhcmx5RXhpdEtleScgfSB9XSB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICAgIHsgbXVsdGk6IHsgJHZhcjogJ3N0YWtlck11bHRpJyB9IH0sXG4gICAgXSxcbiAgfTtcbiAgY29uc3QgZmllbGRzID0gbWF0Y2hlci5tYXRjaChtaW5pc2NyaXB0Tm9kZSwgcGF0dGVybik7XG4gIGlmICghZmllbGRzKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IHVubG9ja0hlaWdodCA9IGFzTnVtYmVyKGZpZWxkcy51bmxvY2tIZWlnaHQsICdhZnRlciBhcmd1bWVudCcpO1xuICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKHVubG9ja0hlaWdodCkgfHwgdW5sb2NrSGVpZ2h0IDw9IDAgfHwgdW5sb2NrSGVpZ2h0ID49IDUwMF8wMDBfMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGB1bmxvY2tIZWlnaHQgKCR7dW5sb2NrSGVpZ2h0fSkgbXVzdCBiZSBhIHBvc2l0aXZlIGJsb2NrIGhlaWdodCBiZWxvdyA1MDAwMDAwMDBgKTtcbiAgfVxuICBjb25zdCBjb21taXRtZW50SGV4ID0gYXNTdHJpbmcoZmllbGRzLnN0YWtlckNvbW1pdG1lbnQsICdzaGEyNTYgY29tbWl0bWVudCcpO1xuICBpZiAoIS9eWzAtOWEtZkEtRl17NjR9JC8udGVzdChjb21taXRtZW50SGV4KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignc3Rha2VyQ29tbWl0bWVudCBtdXN0IGJlIDMyIGJ5dGVzJyk7XG4gIH1cbiAgY29uc3QgZWFybHlFeGl0S2V5ID0gcGFyc2VDb21wcmVzc2VkS2V5KGFzU3RyaW5nKGZpZWxkcy5lYXJseUV4aXRLZXksICdlYXJseSBleGl0IGtleScpLCAnZWFybHlFeGl0S2V5Jyk7XG5cbiAgaWYgKCFBcnJheS5pc0FycmF5KGZpZWxkcy5zdGFrZXJNdWx0aSkgfHwgZmllbGRzLnN0YWtlck11bHRpLmxlbmd0aCAhPT0gNCB8fCBmaWVsZHMuc3Rha2VyTXVsdGlbMF0gIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0YWtlciBtdWx0aSBtdXN0IGJlIGEgMi1vZi0zIG11bHRpc2lnJyk7XG4gIH1cbiAgY29uc3Qgc3Rha2VyS2V5U3RyaW5ncyA9IGZpZWxkcy5zdGFrZXJNdWx0aS5zbGljZSgxKS5tYXAoKGtleSwgaW5kZXgpID0+IGFzU3RyaW5nKGtleSwgYHN0YWtlciBrZXkgJHtpbmRleH1gKSk7XG4gIGNvbnN0IHJlc29sdmVkS2V5cyA9IHN0YWtlcktleVN0cmluZ3MubWFwKHJlc29sdmVTdGFrZXJLZXkpO1xuXG4gIHJldHVybiB7XG4gICAgdW5sb2NrSGVpZ2h0LFxuICAgIHN0YWtlckNvbW1pdG1lbnQ6IEJ1ZmZlci5mcm9tKGNvbW1pdG1lbnRIZXgsICdoZXgnKSxcbiAgICBlYXJseUV4aXRLZXksXG4gICAgc3Rha2VyS2V5U3RyaW5nczogW3N0YWtlcktleVN0cmluZ3NbMF0sIHN0YWtlcktleVN0cmluZ3NbMV0sIHN0YWtlcktleVN0cmluZ3NbMl1dLFxuICAgIHN0YWtlcktleXM6IHJlc29sdmVkS2V5cy5ldmVyeSgoa2V5KToga2V5IGlzIEJ1ZmZlciA9PiBrZXkgIT09IHVuZGVmaW5lZClcbiAgICAgID8gW3Jlc29sdmVkS2V5c1swXSwgcmVzb2x2ZWRLZXlzWzFdLCByZXNvbHZlZEtleXNbMl1dXG4gICAgICA6IHVuZGVmaW5lZCxcbiAgICBtaW5pc2NyaXB0Tm9kZSxcbiAgfTtcbn1cblxuLyoqIFNlcmlhbGl6ZSB0aGUgY2Fub25pY2FsIDItb2YtMyBzdGFrZXIgc3Vic2NyaXB0IGZvciBhIGNvbmNyZXRlIFBvWC01IGRlc2NyaXB0b3IuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UG94NVVubG9ja0J5dGVzKGRlc2NyaXB0b3I6IERlc2NyaXB0b3IpOiBCdWZmZXIge1xuICBjb25zdCBwYXJzZWQgPSBwYXJzZVBveDVMb2NrdXBEZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICBpZiAoIXBhcnNlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRGVzY3JpcHRvciBpcyBub3QgYSBjYW5vbmljYWwgUG9YLTUgbG9ja3VwIGRlc2NyaXB0b3InKTtcbiAgfVxuICBpZiAoIXBhcnNlZC5zdGFrZXJLZXlzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQb1gtNSBkZXNjcmlwdG9yIGtleXMgbXVzdCBiZSBjb25jcmV0ZSBiZWZvcmUgZGVyaXZpbmcgdW5sb2NrQnl0ZXMnKTtcbiAgfVxuXG4gIGNvbnN0IGtleVB1c2hlcyA9IHBhcnNlZC5zdGFrZXJLZXlzLm1hcCgoa2V5LCBpbmRleCkgPT4ge1xuICAgIGlmIChrZXkubGVuZ3RoICE9PSAzMyB8fCAoa2V5WzBdICE9PSAweDAyICYmIGtleVswXSAhPT0gMHgwMykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUG9YLTUgc3Rha2VyIGtleSAke2luZGV4fSBtdXN0IGJlIGEgMzMtYnl0ZSBjb21wcmVzc2VkIHB1YmxpYyBrZXlgKTtcbiAgICB9XG4gICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5vZihrZXkubGVuZ3RoKSwga2V5XSk7XG4gIH0pO1xuXG4gIHJldHVybiBCdWZmZXIuY29uY2F0KFtCdWZmZXIub2YoMHg1MiksIC4uLmtleVB1c2hlcywgQnVmZmVyLm9mKDB4NTMsIDB4YWUpXSk7XG59XG4iXX0=
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Psbt } from '@bitgo/wasm-utxo';
|
|
2
|
+
import type { Pox5InputMatch } from './input';
|
|
3
|
+
export declare const POX5_MAX_UNLOCK_HEIGHT = 500000000;
|
|
4
|
+
/** Validate the post-CLTV policy for all canonical PoX-5 inputs in a recovery PSBT. */
|
|
5
|
+
export declare function assertPox5LocktimeSpend(psbt: Psbt, inputs: readonly Pox5InputMatch[]): void;
|
|
6
|
+
/** Validate that a canonical PoX-5 input can use the principal-preimage branch. */
|
|
7
|
+
export declare function assertPox5EarlyExitSpend(psbt: Psbt, input: Pox5InputMatch): void;
|
|
8
|
+
export type Pox5SpendBranch = 'locktime' | 'early-exit';
|
|
9
|
+
/** Classify a PoX-5 spend from native principal-preimage metadata. */
|
|
10
|
+
export declare function classifyPox5Spend(psbt: Psbt, input: Pox5InputMatch): Pox5SpendBranch;
|
|
11
|
+
/** Add validated principal-preimage metadata for an early-exit spend. */
|
|
12
|
+
export declare function preparePox5EarlyExit(psbt: Psbt, inputIndex: number, input: Pox5InputMatch, principalPreimage: Uint8Array): void;
|
|
13
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../src/pox5/recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAe,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C,eAAO,MAAM,sBAAsB,YAAc,CAAC;AA4BlD,uFAAuF;AACvF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAqB3F;AAED,mFAAmF;AACnF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,CAEhF;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,YAAY,CAAC;AAExD,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,GAAG,eAAe,CAMpF;AAED,yEAAyE;AACzE,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,cAAc,EACrB,iBAAiB,EAAE,UAAU,GAC5B,IAAI,CAON"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Transaction } from '@bitgo/wasm-utxo';
|
|
2
|
+
import { assertPox5PrincipalPreimage } from './validation';
|
|
3
|
+
export const POX5_MAX_UNLOCK_HEIGHT = 500000000;
|
|
4
|
+
function assertPox5UnlockHeight(unlockHeight) {
|
|
5
|
+
if (!Number.isSafeInteger(unlockHeight) || unlockHeight <= 0 || unlockHeight >= POX5_MAX_UNLOCK_HEIGHT) {
|
|
6
|
+
throw new Error(`PoX-5 unlock height must be a positive block height below ${POX5_MAX_UNLOCK_HEIGHT}`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function assertPox5BlockHeightLocktime(lockTime) {
|
|
10
|
+
if (!Number.isSafeInteger(lockTime) || lockTime < 0 || lockTime >= POX5_MAX_UNLOCK_HEIGHT) {
|
|
11
|
+
throw new Error(`PoX-5 nLockTime must be a block height below ${POX5_MAX_UNLOCK_HEIGHT}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function getMatchedTransactionInput(psbt, match) {
|
|
15
|
+
const psbtInput = psbt.getInputs()[match.inputIndex];
|
|
16
|
+
const transactionInput = Transaction.fromBytes(psbt.getUnsignedTx()).getInputs()[match.inputIndex];
|
|
17
|
+
const descriptorScript = Buffer.from(match.descriptor.scriptPubkey());
|
|
18
|
+
if (!psbtInput?.witnessUtxo ||
|
|
19
|
+
!transactionInput ||
|
|
20
|
+
!Buffer.from(psbtInput.witnessUtxo.script).equals(descriptorScript)) {
|
|
21
|
+
throw new Error(`PoX-5 descriptor match does not match PSBT input ${match.inputIndex}`);
|
|
22
|
+
}
|
|
23
|
+
return transactionInput;
|
|
24
|
+
}
|
|
25
|
+
/** Validate the post-CLTV policy for all canonical PoX-5 inputs in a recovery PSBT. */
|
|
26
|
+
export function assertPox5LocktimeSpend(psbt, inputs) {
|
|
27
|
+
if (inputs.length === 0) {
|
|
28
|
+
throw new Error('PoX-5 lockup descriptor match is required');
|
|
29
|
+
}
|
|
30
|
+
const unlockHeights = inputs.map((input) => {
|
|
31
|
+
const { unlockHeight } = input.info;
|
|
32
|
+
assertPox5UnlockHeight(unlockHeight);
|
|
33
|
+
return unlockHeight;
|
|
34
|
+
});
|
|
35
|
+
const lockTime = psbt.lockTime();
|
|
36
|
+
assertPox5BlockHeightLocktime(lockTime);
|
|
37
|
+
const requiredLockTime = Math.max(...unlockHeights);
|
|
38
|
+
if (lockTime < requiredLockTime) {
|
|
39
|
+
throw new Error(`PoX-5 nLockTime must be at least ${requiredLockTime}`);
|
|
40
|
+
}
|
|
41
|
+
for (const input of inputs) {
|
|
42
|
+
if (getMatchedTransactionInput(psbt, input).sequence === 0xffffffff) {
|
|
43
|
+
throw new Error(`PoX-5 locktime spend input ${input.inputIndex} must use a non-final sequence`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Validate that a canonical PoX-5 input can use the principal-preimage branch. */
|
|
48
|
+
export function assertPox5EarlyExitSpend(psbt, input) {
|
|
49
|
+
getMatchedTransactionInput(psbt, input);
|
|
50
|
+
}
|
|
51
|
+
/** Classify a PoX-5 spend from native principal-preimage metadata. */
|
|
52
|
+
export function classifyPox5Spend(psbt, input) {
|
|
53
|
+
getMatchedTransactionInput(psbt, input);
|
|
54
|
+
const hasPrincipalPreimage = psbt
|
|
55
|
+
.getInputKeyValues(input.inputIndex)
|
|
56
|
+
.some((record) => record.type === 'known' && record.key === 'PSBT_IN_SHA256');
|
|
57
|
+
return hasPrincipalPreimage ? 'early-exit' : 'locktime';
|
|
58
|
+
}
|
|
59
|
+
/** Add validated principal-preimage metadata for an early-exit spend. */
|
|
60
|
+
export function preparePox5EarlyExit(psbt, inputIndex, input, principalPreimage) {
|
|
61
|
+
if (inputIndex !== input.inputIndex) {
|
|
62
|
+
throw new Error(`PoX-5 descriptor match belongs to PSBT input ${input.inputIndex}, not ${inputIndex}`);
|
|
63
|
+
}
|
|
64
|
+
assertPox5EarlyExitSpend(psbt, input);
|
|
65
|
+
assertPox5PrincipalPreimage(input.info, principalPreimage);
|
|
66
|
+
psbt.addSha256Preimage(inputIndex, principalPreimage);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3ZlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcG94NS9yZWNvdmVyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQVEsV0FBVyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFHckQsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRTNELE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLFNBQVcsQ0FBQztBQUVsRCxTQUFTLHNCQUFzQixDQUFDLFlBQW9CO0lBQ2xELElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxJQUFJLFlBQVksSUFBSSxDQUFDLElBQUksWUFBWSxJQUFJLHNCQUFzQixFQUFFLENBQUM7UUFDdkcsTUFBTSxJQUFJLEtBQUssQ0FBQyw2REFBNkQsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO0lBQ3pHLENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyw2QkFBNkIsQ0FBQyxRQUFnQjtJQUNyRCxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsSUFBSSxRQUFRLEdBQUcsQ0FBQyxJQUFJLFFBQVEsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO1FBQzFGLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELHNCQUFzQixFQUFFLENBQUMsQ0FBQztJQUM1RixDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsMEJBQTBCLENBQUMsSUFBVSxFQUFFLEtBQXFCO0lBQ25FLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDckQsTUFBTSxnQkFBZ0IsR0FBRyxXQUFXLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNuRyxNQUFNLGdCQUFnQixHQUFHLE1BQU0s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LEtBQUssQ0FBQyxDQUFDO0lBQ3RDLDJCQUEyQixDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUMzRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsVUFBVSxFQUFFLGlCQUFpQixDQUFDLENBQUM7QUFDeEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBzYnQsIFRyYW5zYWN0aW9uIH0gZnJvbSAnQGJpdGdvL3dhc20tdXR4byc7XG5cbmltcG9ydCB0eXBlIHsgUG94NUlucHV0TWF0Y2ggfSBmcm9tICcuL2lucHV0JztcbmltcG9ydCB7IGFzc2VydFBveDVQcmluY2lwYWxQcmVpbWFnZSB9IGZyb20gJy4vdmFsaWRhdGlvbic7XG5cbmV4cG9ydCBjb25zdCBQT1g1X01BWF9VTkxPQ0tfSEVJR0hUID0gNTAwXzAwMF8wMDA7XG5cbmZ1bmN0aW9uIGFzc2VydFBveDVVbmxvY2tIZWlnaHQodW5sb2NrSGVpZ2h0OiBudW1iZXIpOiB2b2lkIHtcbiAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih1bmxvY2tIZWlnaHQpIHx8IHVubG9ja0hlaWdodCA8PSAwIHx8IHVubG9ja0hlaWdodCA+PSBQT1g1X01BWF9VTkxPQ0tfSEVJR0hUKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBQb1gtNSB1bmxvY2sgaGVpZ2h0IG11c3QgYmUgYSBwb3NpdGl2ZSBibG9jayBoZWlnaHQgYmVsb3cgJHtQT1g1X01BWF9VTkxPQ0tfSEVJR0hUfWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGFzc2VydFBveDVCbG9ja0hlaWdodExvY2t0aW1lKGxvY2tUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihsb2NrVGltZSkgfHwgbG9ja1RpbWUgPCAwIHx8IGxvY2tUaW1lID49IFBPWDVfTUFYX1VOTE9DS19IRUlHSFQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFBvWC01IG5Mb2NrVGltZSBtdXN0IGJlIGEgYmxvY2sgaGVpZ2h0IGJlbG93ICR7UE9YNV9NQVhfVU5MT0NLX0hFSUdIVH1gKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRNYXRjaGVkVHJhbnNhY3Rpb25JbnB1dChwc2J0OiBQc2J0LCBtYXRjaDogUG94NUlucHV0TWF0Y2gpIHtcbiAgY29uc3QgcHNidElucHV0ID0gcHNidC5nZXRJbnB1dHMoKVttYXRjaC5pbnB1dEluZGV4XTtcbiAgY29uc3QgdHJhbnNhY3Rpb25JbnB1dCA9IFRyYW5zYWN0aW9uLmZyb21CeXRlcyhwc2J0LmdldFVuc2lnbmVkVHgoKSkuZ2V0SW5wdXRzKClbbWF0Y2guaW5wdXRJbmRleF07XG4gIGNvbnN0IGRlc2NyaXB0b3JTY3JpcHQgPSBCdWZmZXIuZnJvbShtYXRjaC5kZXNjcmlwdG9yLnNjcmlwdFB1YmtleSgpKTtcbiAgaWYgKFxuICAgICFwc2J0SW5wdXQ/LndpdG5lc3NVdHhvIHx8XG4gICAgIXRyYW5zYWN0aW9uSW5wdXQgfHxcbiAgICAhQnVmZmVyLmZyb20ocHNidElucHV0LndpdG5lc3NVdHhvLnNjcmlwdCkuZXF1YWxzKGRlc2NyaXB0b3JTY3JpcHQpXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcihgUG9YLTUgZGVzY3JpcHRvciBtYXRjaCBkb2VzIG5vdCBtYXRjaCBQU0JUIGlucHV0ICR7bWF0Y2guaW5wdXRJbmRleH1gKTtcbiAgfVxuICByZXR1cm4gdHJhbnNhY3Rpb25JbnB1dDtcbn1cblxuLyoqIFZhbGlkYXRlIHRoZSBwb3N0LUNMVFYgcG9saWN5IGZvciBhbGwgY2Fub25pY2FsIFBvWC01IGlucHV0cyBpbiBhIHJlY292ZXJ5IFBTQlQuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0UG94NUxvY2t0aW1lU3BlbmQocHNidDogUHNidCwgaW5wdXRzOiByZWFkb25seSBQb3g1SW5wdXRNYXRjaFtdKTogdm9pZCB7XG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQb1gtNSBsb2NrdXAgZGVzY3JpcHRvciBtYXRjaCBpcyByZXF1aXJlZCcpO1xuICB9XG5cbiAgY29uc3QgdW5sb2NrSGVpZ2h0cyA9IGlucHV0cy5tYXAoKGlucHV0KSA9PiB7XG4gICAgY29uc3QgeyB1bmxvY2tIZWlnaHQgfSA9IGlucHV0LmluZm87XG4gICAgYXNzZXJ0UG94NVVubG9ja0hlaWdodCh1bmxvY2tIZWlnaHQpO1xuICAgIHJldHVybiB1bmxvY2tIZWlnaHQ7XG4gIH0pO1xuICBjb25zdCBsb2NrVGltZSA9IHBzYnQubG9ja1RpbWUoKTtcbiAgYXNzZXJ0UG94NUJsb2NrSGVpZ2h0TG9ja3RpbWUobG9ja1RpbWUpO1xuICBjb25zdCByZXF1aXJlZExvY2tUaW1lID0gTWF0aC5tYXgoLi4udW5sb2NrSGVpZ2h0cyk7XG4gIGlmIChsb2NrVGltZSA8IHJlcXVpcmVkTG9ja1RpbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFBvWC01IG5Mb2NrVGltZSBtdXN0IGJlIGF0IGxlYXN0ICR7cmVxdWlyZWRMb2NrVGltZX1gKTtcbiAgfVxuICBmb3IgKGNvbnN0IGlucHV0IG9mIGlucHV0cykge1xuICAgIGlmIChnZXRNYXRjaGVkVHJhbnNhY3Rpb25JbnB1dChwc2J0LCBpbnB1dCkuc2VxdWVuY2UgPT09IDB4ZmZmZmZmZmYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUG9YLTUgbG9ja3RpbWUgc3BlbmQgaW5wdXQgJHtpbnB1dC5pbnB1dEluZGV4fSBtdXN0IHVzZSBhIG5vbi1maW5hbCBzZXF1ZW5jZWApO1xuICAgIH1cbiAgfVxufVxuXG4vKiogVmFsaWRhdGUgdGhhdCBhIGNhbm9uaWNhbCBQb1gtNSBpbnB1dCBjYW4gdXNlIHRoZSBwcmluY2lwYWwtcHJlaW1hZ2UgYnJhbmNoLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydFBveDVFYXJseUV4aXRTcGVuZChwc2J0OiBQc2J0LCBpbnB1dDogUG94NUlucHV0TWF0Y2gpOiB2b2lkIHtcbiAgZ2V0TWF0Y2hlZFRyYW5zYWN0aW9uSW5wdXQocHNidCwgaW5wdXQpO1xufVxuXG5leHBvcnQgdHlwZSBQb3g1U3BlbmRCcmFuY2ggPSAnbG9ja3RpbWUnIHwgJ2Vhcmx5LWV4aXQnO1xuXG4vKiogQ2xhc3NpZnkgYSBQb1gtNSBzcGVuZCBmcm9tIG5hdGl2ZSBwcmluY2lwYWwtcHJlaW1hZ2UgbWV0YWRhdGEuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhc3NpZnlQb3g1U3BlbmQocHNidDogUHNidCwgaW5wdXQ6IFBveDVJbnB1dE1hdGNoKTogUG94NVNwZW5kQnJhbmNoIHtcbiAgZ2V0TWF0Y2hlZFRyYW5zYWN0aW9uSW5wdXQocHNidCwgaW5wdXQpO1xuICBjb25zdCBoYXNQcmluY2lwYWxQcmVpbWFnZSA9IHBzYnRcbiAgICAuZ2V0SW5wdXRLZXlWYWx1ZXMoaW5wdXQuaW5wdXRJbmRleClcbiAgICAuc29tZSgocmVjb3JkKSA9PiByZWNvcmQudHlwZSA9PT0gJ2tub3duJyAmJiByZWNvcmQua2V5ID09PSAnUFNCVF9JTl9TSEEyNTYnKTtcbiAgcmV0dXJuIGhhc1ByaW5jaXBhbFByZWltYWdlID8gJ2Vhcmx5LWV4aXQnIDogJ2xvY2t0aW1lJztcbn1cblxuLyoqIEFkZCB2YWxpZGF0ZWQgcHJpbmNpcGFsLXByZWltYWdlIG1ldGFkYXRhIGZvciBhbiBlYXJseS1leGl0IHNwZW5kLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVQb3g1RWFybHlFeGl0KFxuICBwc2J0OiBQc2J0LFxuICBpbnB1dEluZGV4OiBudW1iZXIsXG4gIGlucHV0OiBQb3g1SW5wdXRNYXRjaCxcbiAgcHJpbmNpcGFsUHJlaW1hZ2U6IFVpbnQ4QXJyYXlcbik6IHZvaWQge1xuICBpZiAoaW5wdXRJbmRleCAhPT0gaW5wdXQuaW5wdXRJbmRleCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgUG9YLTUgZGVzY3JpcHRvciBtYXRjaCBiZWxvbmdzIHRvIFBTQlQgaW5wdXQgJHtpbnB1dC5pbnB1dEluZGV4fSwgbm90ICR7aW5wdXRJbmRleH1gKTtcbiAgfVxuICBhc3NlcnRQb3g1RWFybHlFeGl0U3BlbmQocHNidCwgaW5wdXQpO1xuICBhc3NlcnRQb3g1UHJpbmNpcGFsUHJlaW1hZ2UoaW5wdXQuaW5mbywgcHJpbmNpcGFsUHJlaW1hZ2UpO1xuICBwc2J0LmFkZFNoYTI1NlByZWltYWdlKGlucHV0SW5kZXgsIHByaW5jaXBhbFByZWltYWdlKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Psbt, type Descriptor } from '@bitgo/wasm-utxo';
|
|
2
|
+
import { Pox5DescriptorInfo } from './parseDescriptor';
|
|
3
|
+
/**
|
|
4
|
+
* Read the principal preimage committed by a canonical PoX-5 descriptor from a
|
|
5
|
+
* native PSBT input. The PSBT_IN_SHA256 key data is the descriptor commitment.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getPox5PrincipalPreimage(psbt: Psbt, inputIndex: number, descriptor: Pox5DescriptorInfo | Descriptor | import('@bitgo/wasm-utxo').ast.DescriptorNode): Buffer;
|
|
8
|
+
/** Verify that a principal preimage is committed by a canonical PoX-5 descriptor. */
|
|
9
|
+
export declare function assertPox5PrincipalPreimage(descriptor: Pox5DescriptorInfo | Descriptor | import('@bitgo/wasm-utxo').ast.DescriptorNode, principalPreimage: Uint8Array): void;
|
|
10
|
+
/** Alias for callers that prefer validation terminology. */
|
|
11
|
+
export declare function validatePox5PrincipalPreimage(descriptor: Pox5DescriptorInfo | Descriptor | import('@bitgo/wasm-utxo').ast.DescriptorNode, principalPreimage: Uint8Array): void;
|
|
12
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/pox5/validation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,KAAK,UAAU,EAA0B,MAAM,kBAAkB,CAAC;AAEjF,OAAO,EAAE,kBAAkB,EAA6B,MAAM,mBAAmB,CAAC;AAUlF;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,GAAG,UAAU,GAAG,OAAO,kBAAkB,EAAE,GAAG,CAAC,cAAc,GAC1F,MAAM,CA0BR;AAwBD,qFAAqF;AACrF,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,kBAAkB,GAAG,UAAU,GAAG,OAAO,kBAAkB,EAAE,GAAG,CAAC,cAAc,EAC3F,iBAAiB,EAAE,UAAU,GAC5B,IAAI,CASN;AAED,4DAA4D;AAC5D,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,kBAAkB,GAAG,UAAU,GAAG,OAAO,kBAAkB,EAAE,GAAG,CAAC,cAAc,EAC3F,iBAAiB,EAAE,UAAU,GAC5B,IAAI,CAEN"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { parsePox5LockupDescriptor } from './parseDescriptor';
|
|
3
|
+
const SHA256_INPUT_KEY = 'PSBT_IN_SHA256';
|
|
4
|
+
function isSha256InputKeyValue(keyValue) {
|
|
5
|
+
return keyValue.type === 'known' && keyValue.key === SHA256_INPUT_KEY;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Read the principal preimage committed by a canonical PoX-5 descriptor from a
|
|
9
|
+
* native PSBT input. The PSBT_IN_SHA256 key data is the descriptor commitment.
|
|
10
|
+
*/
|
|
11
|
+
export function getPox5PrincipalPreimage(psbt, inputIndex, descriptor) {
|
|
12
|
+
const info = getPox5DescriptorInfo(descriptor);
|
|
13
|
+
const records = psbt
|
|
14
|
+
.getInputKeyValues(inputIndex)
|
|
15
|
+
.filter(isSha256InputKeyValue)
|
|
16
|
+
.filter((record) => Buffer.from(record.keyData).equals(info.stakerCommitment));
|
|
17
|
+
if (records.length !== 1) {
|
|
18
|
+
throw new Error(`expected exactly one ${SHA256_INPUT_KEY} record matching the descriptor commitment, found ${records.length}`);
|
|
19
|
+
}
|
|
20
|
+
const [record] = records;
|
|
21
|
+
if (record.keyData.length !== 32) {
|
|
22
|
+
throw new Error(`${SHA256_INPUT_KEY} digest must be 32 bytes`);
|
|
23
|
+
}
|
|
24
|
+
if (record.value.length !== 32) {
|
|
25
|
+
throw new Error(`${SHA256_INPUT_KEY} preimage must be 32 bytes`);
|
|
26
|
+
}
|
|
27
|
+
const preimage = Buffer.from(record.value);
|
|
28
|
+
const digest = createHash('sha256').update(preimage).digest();
|
|
29
|
+
if (!digest.equals(Buffer.from(record.keyData))) {
|
|
30
|
+
throw new Error(`${SHA256_INPUT_KEY} digest does not match its preimage`);
|
|
31
|
+
}
|
|
32
|
+
return preimage;
|
|
33
|
+
}
|
|
34
|
+
function isPox5DescriptorInfo(value) {
|
|
35
|
+
return (value !== null &&
|
|
36
|
+
typeof value === 'object' &&
|
|
37
|
+
'stakerCommitment' in value &&
|
|
38
|
+
Buffer.isBuffer(value.stakerCommitment));
|
|
39
|
+
}
|
|
40
|
+
function getPox5DescriptorInfo(descriptor) {
|
|
41
|
+
if (isPox5DescriptorInfo(descriptor)) {
|
|
42
|
+
return descriptor;
|
|
43
|
+
}
|
|
44
|
+
const info = parsePox5LockupDescriptor(descriptor);
|
|
45
|
+
if (!info) {
|
|
46
|
+
throw new Error('descriptor is not a canonical PoX-5 lockup descriptor');
|
|
47
|
+
}
|
|
48
|
+
return info;
|
|
49
|
+
}
|
|
50
|
+
/** Verify that a principal preimage is committed by a canonical PoX-5 descriptor. */
|
|
51
|
+
export function assertPox5PrincipalPreimage(descriptor, principalPreimage) {
|
|
52
|
+
if (principalPreimage.length !== 32) {
|
|
53
|
+
throw new Error('principalPreimage must be 32 bytes');
|
|
54
|
+
}
|
|
55
|
+
const info = getPox5DescriptorInfo(descriptor);
|
|
56
|
+
const digest = createHash('sha256').update(principalPreimage).digest();
|
|
57
|
+
if (!digest.equals(info.stakerCommitment)) {
|
|
58
|
+
throw new Error('principalPreimage does not match the descriptor stakerCommitment');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Alias for callers that prefer validation terminology. */
|
|
62
|
+
export function validatePox5PrincipalPreimage(descriptor, principalPreimage) {
|
|
63
|
+
assertPox5PrincipalPreimage(descriptor, principalPreimage);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wb3g1L3ZhbGlkYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUlwQyxPQUFPLEVBQXNCLHlCQUF5QixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbEYsTUFBTSxnQkFBZ0IsR0FBRyxnQkFBZ0IsQ0FBQztBQUkxQyxTQUFTLHFCQUFxQixDQUFDLFFBQTJCO0lBQ3hELE9BQU8sUUFBUSxDQUFDLElBQUksS0FBSyxPQUFPLElBQUksUUFBUSxDQUFDLEdBQUcsS0FBSyxnQkFBZ0IsQ0FBQztBQUN4RSxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLHdCQUF3QixDQUN0QyxJQUFVLEVBQ1YsVUFBa0IsRUFDbEIsVUFBMkY7SUFFM0YsTUFBTSxJQUFJLEdBQUcscUJBQXFCLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDL0MsTUFBTSxPQUFPLEdBQUcsSUFBSTtTQUNqQixpQkFBaUIsQ0FBQyxVQUFVLENBQUM7U0FDN0IsTUFBTSxDQUFDLHFCQUFxQixDQUFDO1NBQzdCLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7SUFDakYsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sSUFBSSxLQUFLLENBQ2Isd0JBQXdCLGdCQUFnQixxREFBcUQsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUM5RyxDQUFDO0lBQ0osQ0FBQztJQUVELE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxPQUFPLENBQUM7SUFDekIsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNqQyxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsZ0JBQWdCLDBCQUEwQixDQUFDLENBQUM7SUFDakUsQ0FBQztJQUNELElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLGdCQUFnQiw0QkFBNEIsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMzQyxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQzlELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNoRCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsZ0JBQWdCLHFDQUFxQyxDQUFDLENBQUM7SUFDNUUsQ0FBQztJQUNELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxTQUFTLG9CQUFvQixDQUFDLEtBQWM7SUFDMUMsT0FBTyxDQUNMLEtBQUssS0FBSyxJQUFJO1FBQ2QsT0FBTyxLQUFLLEtBQUssUUFBUTtRQUN6QixrQkFBa0IsSUFBSSxLQUFLO1FBQzNCLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQ3hDLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxxQkFBcUIsQ0FDNUIsVUFBMkY7SUFFM0YsSUFBSSxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ3JDLE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFDRCxNQUFNLElBQUksR0FBRyx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNuRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDVixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVELHFGQUFxRjtBQUNyRixNQUFNLFVBQVUsMkJBQTJCLENBQ3pDLFVBQTJGLEVBQzNGLGlCQUE2QjtJQUU3QixJQUFJLGlCQUFpQixDQUFDLE1BQU0sS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNwQyxNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUNELE1BQU0sSUFBSSxHQUFHLHFCQUFxQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN2RSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO1FBQzFDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0VBQWtFLENBQUMsQ0FBQztJQUN0RixDQUFDO0FBQ0gsQ0FBQztBQUVELDREQUE0RDtBQUM1RCxNQUFNLFVBQVUsNkJBQTZCLENBQzNDLFVBQTJGLEVBQzNGLGlCQUE2QjtJQUU3QiwyQkFBMkIsQ0FBQyxVQUFVLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztBQUM3RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5cbmltcG9ydCB7IFBzYnQsIHR5cGUgRGVzY3JpcHRvciwgdHlwZSBQc2J0SW5wdXRLZXlWYWx1ZSB9IGZyb20gJ0BiaXRnby93YXNtLXV0eG8nO1xuXG5pbXBvcnQgeyBQb3g1RGVzY3JpcHRvckluZm8sIHBhcnNlUG94NUxvY2t1cERlc2NyaXB0b3IgfSBmcm9tICcuL3BhcnNlRGVzY3JpcHRvcic7XG5cbmNvbnN0IFNIQTI1Nl9JTlBVVF9LRVkgPSAnUFNCVF9JTl9TSEEyNTYnO1xuXG50eXBlIFNoYTI1NklucHV0S2V5VmFsdWUgPSBFeHRyYWN0PFBzYnRJbnB1dEtleVZhbHVlLCB7IHR5cGU6ICdrbm93bicgfT47XG5cbmZ1bmN0aW9uIGlzU2hhMjU2SW5wdXRLZXlWYWx1ZShrZXlWYWx1ZTogUHNidElucHV0S2V5VmFsdWUpOiBrZXlWYWx1ZSBpcyBTaGEyNTZJbnB1dEtleVZhbHVlIHtcbiAgcmV0dXJuIGtleVZhbHVlLnR5cGUgPT09ICdrbm93bicgJiYga2V5VmFsdWUua2V5ID09PSBTSEEyNTZfSU5QVVRfS0VZO1xufVxuXG4vKipcbiAqIFJlYWQgdGhlIHByaW5jaXBhbCBwcmVpbWFnZSBjb21taXR0ZWQgYnkgYSBjYW5vbmljYWwgUG9YLTUgZGVzY3JpcHRvciBmcm9tIGFcbiAqIG5hdGl2ZSBQU0JUIGlucHV0LiBUaGUgUFNCVF9JTl9TSEEyNTYga2V5IGRhdGEgaXMgdGhlIGRlc2NyaXB0b3IgY29tbWl0bWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFBveDVQcmluY2lwYWxQcmVpbWFnZShcbiAgcHNidDogUHNidCxcbiAgaW5wdXRJbmRleDogbnVtYmVyLFxuICBkZXNjcmlwdG9yOiBQb3g1RGVzY3JpcHRvckluZm8gfCBEZXNjcmlwdG9yIHwgaW1wb3J0KCdAYml0Z28vd2FzbS11dHhvJykuYXN0LkRlc2NyaXB0b3JOb2RlXG4pOiBCdWZmZXIge1xuICBjb25zdCBpbmZvID0gZ2V0UG94NURlc2NyaXB0b3JJbmZvKGRlc2NyaXB0b3IpO1xuICBjb25zdCByZWNvcmRzID0gcHNidFxuICAgIC5nZXRJbnB1dEtleVZhbHVlcyhpbnB1dEluZGV4KVxuICAgIC5maWx0ZXIoaXNTaGEyNTZJbnB1dEtleVZhbHVlKVxuICAgIC5maWx0ZXIoKHJlY29yZCkgPT4gQnVmZmVyLmZyb20ocmVjb3JkLmtleURhdGEpLmVxdWFscyhpbmZvLnN0YWtlckNvbW1pdG1lbnQpKTtcbiAgaWYgKHJlY29yZHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYGV4cGVjdGVkIGV4YWN0bHkgb25lICR7U0hBMjU2X0lOUFVUX0tFWX0gcmVjb3JkIG1hdGNoaW5nIHRoZSBkZXNjcmlwdG9yIGNvbW1pdG1lbnQsIGZvdW5kICR7cmVjb3Jkcy5sZW5ndGh9YFxuICAgICk7XG4gIH1cblxuICBjb25zdCBbcmVjb3JkXSA9IHJlY29yZHM7XG4gIGlmIChyZWNvcmQua2V5RGF0YS5sZW5ndGggIT09IDMyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke1NIQTI1Nl9JTlBVVF9LRVl9IGRpZ2VzdCBtdXN0IGJlIDMyIGJ5dGVzYCk7XG4gIH1cbiAgaWYgKHJlY29yZC52YWx1ZS5sZW5ndGggIT09IDMyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke1NIQTI1Nl9JTlBVVF9LRVl9IHByZWltYWdlIG11c3QgYmUgMzIgYnl0ZXNgKTtcbiAgfVxuXG4gIGNvbnN0IHByZWltYWdlID0gQnVmZmVyLmZyb20ocmVjb3JkLnZhbHVlKTtcbiAgY29uc3QgZGlnZXN0ID0gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHByZWltYWdlKS5kaWdlc3QoKTtcbiAgaWYgKCFkaWdlc3QuZXF1YWxzKEJ1ZmZlci5mcm9tKHJlY29yZC5rZXlEYXRhKSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7U0hBMjU2X0lOUFVUX0tFWX0gZGlnZXN0IGRvZXMgbm90IG1hdGNoIGl0cyBwcmVpbWFnZWApO1xuICB9XG4gIHJldHVybiBwcmVpbWFnZTtcbn1cblxuZnVuY3Rpb24gaXNQb3g1RGVzY3JpcHRvckluZm8odmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBQb3g1RGVzY3JpcHRvckluZm8ge1xuICByZXR1cm4gKFxuICAgIHZhbHVlICE9PSBudWxsICYmXG4gICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICdzdGFrZXJDb21taXRtZW50JyBpbiB2YWx1ZSAmJlxuICAgIEJ1ZmZlci5pc0J1ZmZlcih2YWx1ZS5zdGFrZXJDb21taXRtZW50KVxuICApO1xufVxuXG5mdW5jdGlvbiBnZXRQb3g1RGVzY3JpcHRvckluZm8oXG4gIGRlc2NyaXB0b3I6IFBveDVEZXNjcmlwdG9ySW5mbyB8IERlc2NyaXB0b3IgfCBpbXBvcnQoJ0BiaXRnby93YXNtLXV0eG8nKS5hc3QuRGVzY3JpcHRvck5vZGVcbik6IFBveDVEZXNjcmlwdG9ySW5mbyB7XG4gIGlmIChpc1BveDVEZXNjcmlwdG9ySW5mbyhkZXNjcmlwdG9yKSkge1xuICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICB9XG4gIGNvbnN0IGluZm8gPSBwYXJzZVBveDVMb2NrdXBEZXNjcmlwdG9yKGRlc2NyaXB0b3IpO1xuICBpZiAoIWluZm8pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2Rlc2NyaXB0b3IgaXMgbm90IGEgY2Fub25pY2FsIFBvWC01IGxvY2t1cCBkZXNjcmlwdG9yJyk7XG4gIH1cbiAgcmV0dXJuIGluZm87XG59XG5cbi8qKiBWZXJpZnkgdGhhdCBhIHByaW5jaXBhbCBwcmVpbWFnZSBpcyBjb21taXR0ZWQgYnkgYSBjYW5vbmljYWwgUG9YLTUgZGVzY3JpcHRvci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRQb3g1UHJpbmNpcGFsUHJlaW1hZ2UoXG4gIGRlc2NyaXB0b3I6IFBveDVEZXNjcmlwdG9ySW5mbyB8IERlc2NyaXB0b3IgfCBpbXBvcnQoJ0BiaXRnby93YXNtLXV0eG8nKS5hc3QuRGVzY3JpcHRvck5vZGUsXG4gIHByaW5jaXBhbFByZWltYWdlOiBVaW50OEFycmF5XG4pOiB2b2lkIHtcbiAgaWYgKHByaW5jaXBhbFByZWltYWdlLmxlbmd0aCAhPT0gMzIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3ByaW5jaXBhbFByZWltYWdlIG11c3QgYmUgMzIgYnl0ZXMnKTtcbiAgfVxuICBjb25zdCBpbmZvID0gZ2V0UG94NURlc2NyaXB0b3JJbmZvKGRlc2NyaXB0b3IpO1xuICBjb25zdCBkaWdlc3QgPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUocHJpbmNpcGFsUHJlaW1hZ2UpLmRpZ2VzdCgpO1xuICBpZiAoIWRpZ2VzdC5lcXVhbHMoaW5mby5zdGFrZXJDb21taXRtZW50KSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJpbmNpcGFsUHJlaW1hZ2UgZG9lcyBub3QgbWF0Y2ggdGhlIGRlc2NyaXB0b3Igc3Rha2VyQ29tbWl0bWVudCcpO1xuICB9XG59XG5cbi8qKiBBbGlhcyBmb3IgY2FsbGVycyB0aGF0IHByZWZlciB2YWxpZGF0aW9uIHRlcm1pbm9sb2d5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUG94NVByaW5jaXBhbFByZWltYWdlKFxuICBkZXNjcmlwdG9yOiBQb3g1RGVzY3JpcHRvckluZm8gfCBEZXNjcmlwdG9yIHwgaW1wb3J0KCdAYml0Z28vd2FzbS11dHhvJykuYXN0LkRlc2NyaXB0b3JOb2RlLFxuICBwcmluY2lwYWxQcmVpbWFnZTogVWludDhBcnJheVxuKTogdm9pZCB7XG4gIGFzc2VydFBveDVQcmluY2lwYWxQcmVpbWFnZShkZXNjcmlwdG9yLCBwcmluY2lwYWxQcmVpbWFnZSk7XG59XG4iXX0=
|
|
@@ -30,6 +30,14 @@ export type ParsedSbtcDepositDescriptor = {
|
|
|
30
30
|
depositMiniscriptNode: ast.MiniscriptNode;
|
|
31
31
|
/** Raw miniscript AST for the reclaim leaf (second tap-tree leaf). */
|
|
32
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];
|
|
33
41
|
};
|
|
34
42
|
/**
|
|
35
43
|
* Parse an sBTC peg-in deposit descriptor and return its components.
|