@bitgo/wasm-utxo 1.8.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/cjs/js/fixedScriptWallet/BitGoPsbt.d.ts +5 -0
  2. package/dist/cjs/js/wasm/wasm_utxo.js +14 -14
  3. package/dist/cjs/js/wasm/wasm_utxo_bg.wasm +0 -0
  4. package/dist/cjs/js/wasm/wasm_utxo_bg.wasm.d.ts +25 -25
  5. package/dist/esm/js/fixedScriptWallet/BitGoPsbt.d.ts +5 -0
  6. package/dist/esm/js/wasm/wasm_utxo_bg.js +14 -14
  7. package/dist/esm/js/wasm/wasm_utxo_bg.wasm +0 -0
  8. package/dist/esm/js/wasm/wasm_utxo_bg.wasm.d.ts +25 -25
  9. package/package.json +3 -3
  10. package/dist/cjs/package.json +0 -1
  11. package/dist/cjs/tsconfig.cjs.tsbuildinfo +0 -1
  12. package/dist/esm/test/address/utxolibCompat.d.ts +0 -1
  13. package/dist/esm/test/address/utxolibCompat.js +0 -107
  14. package/dist/esm/test/ast/formatNode.d.ts +0 -1
  15. package/dist/esm/test/ast/formatNode.js +0 -15
  16. package/dist/esm/test/bip32.d.ts +0 -1
  17. package/dist/esm/test/bip32.js +0 -242
  18. package/dist/esm/test/descriptorFixtures.d.ts +0 -25
  19. package/dist/esm/test/descriptorFixtures.js +0 -605
  20. package/dist/esm/test/descriptorUtil.d.ts +0 -13
  21. package/dist/esm/test/descriptorUtil.js +0 -52
  22. package/dist/esm/test/ecpair.d.ts +0 -1
  23. package/dist/esm/test/ecpair.js +0 -137
  24. package/dist/esm/test/fixedScript/address.d.ts +0 -1
  25. package/dist/esm/test/fixedScript/address.js +0 -66
  26. package/dist/esm/test/fixedScript/finalizeExtract.d.ts +0 -1
  27. package/dist/esm/test/fixedScript/finalizeExtract.js +0 -66
  28. package/dist/esm/test/fixedScript/fixtureUtil.d.ts +0 -103
  29. package/dist/esm/test/fixedScript/fixtureUtil.js +0 -65
  30. package/dist/esm/test/fixedScript/musig2Nonces.d.ts +0 -1
  31. package/dist/esm/test/fixedScript/musig2Nonces.js +0 -77
  32. package/dist/esm/test/fixedScript/parseTransactionWithWalletKeys.d.ts +0 -1
  33. package/dist/esm/test/fixedScript/parseTransactionWithWalletKeys.js +0 -168
  34. package/dist/esm/test/fixedScript/signAndVerifySignature.d.ts +0 -1
  35. package/dist/esm/test/fixedScript/signAndVerifySignature.js +0 -268
  36. package/dist/esm/test/fixedScript/walletKeys.util.d.ts +0 -12
  37. package/dist/esm/test/fixedScript/walletKeys.util.js +0 -17
  38. package/dist/esm/test/fixedScriptToDescriptor.d.ts +0 -1
  39. package/dist/esm/test/fixedScriptToDescriptor.js +0 -93
  40. package/dist/esm/test/fixtures.d.ts +0 -1
  41. package/dist/esm/test/fixtures.js +0 -16
  42. package/dist/esm/test/opdrop.d.ts +0 -1
  43. package/dist/esm/test/opdrop.js +0 -85
  44. package/dist/esm/test/psbt.util.d.ts +0 -8
  45. package/dist/esm/test/psbt.util.js +0 -113
  46. package/dist/esm/test/psbtFixedScriptCompat.d.ts +0 -1
  47. package/dist/esm/test/psbtFixedScriptCompat.js +0 -116
  48. package/dist/esm/test/psbtFixedScriptCompatFixtures.d.ts +0 -10
  49. package/dist/esm/test/psbtFixedScriptCompatFixtures.js +0 -53
  50. package/dist/esm/test/psbtFromDescriptor.d.ts +0 -1
  51. package/dist/esm/test/psbtFromDescriptor.js +0 -104
  52. package/dist/esm/test/psbtFromDescriptor.util.d.ts +0 -63
  53. package/dist/esm/test/psbtFromDescriptor.util.js +0 -101
  54. package/dist/esm/test/test.d.ts +0 -1
  55. package/dist/esm/test/test.js +0 -123
  56. package/dist/esm/tsconfig.tsbuildinfo +0 -1
@@ -1,85 +0,0 @@
1
- import * as assert from "assert";
2
- import * as utxolib from "@bitgo/utxo-lib";
3
- import { Descriptor } from "../js/index.js";
4
- import { finalizePsbt, updateInputWithDescriptor } from "./psbt.util.js";
5
- import { getFixture } from "./fixtures.js";
6
- const rootWalletKeys = new utxolib.bitgo.RootWalletKeys(utxolib.testutil.getKeyTriple("wasm"));
7
- function getDescriptorOpDropP2ms(locktime, keys) {
8
- const xpubs = keys.map((key) => key.toBase58() + "/*");
9
- // the `r:` prefix is a custom BitGo modification of miniscript to allow OP_DROP
10
- return `wsh(and_v(r:after(${locktime}),multi(2,${xpubs.join(",")})))`;
11
- }
12
- describe("CLV with OP_DROP", function () {
13
- const locktime = 1024;
14
- const descriptor = Descriptor.fromString(getDescriptorOpDropP2ms(locktime, rootWalletKeys.triple), "derivable");
15
- it("has expected AST", () => {
16
- assert.deepStrictEqual(descriptor.node(), {
17
- Wsh: {
18
- Ms: {
19
- AndV: [
20
- {
21
- Drop: {
22
- After: {
23
- absLockTime: 1024,
24
- },
25
- },
26
- },
27
- {
28
- Multi: [
29
- 2,
30
- {
31
- XPub: "xpub661MyMwAqRbcFNusVUbSN3nbanHMtJjLgZGrs1wxH6f77kKQd6Vq4HfkZQNPC1vSbN6RTiBWJJV6FwJtCfBon2SgaT2J3MSkydukstKjwbJ/*",
32
- },
33
- {
34
- XPub: "xpub661MyMwAqRbcFo3t7PUqvbgvAcEuuoeVib5aapsg52inrG6KGF5aNtR5ey1FNCt1zJpMQiNec5XpofQmLNRhHvQRbhkc8UsWwwMwsXW6ogU/*",
35
- },
36
- {
37
- XPub: "xpub661MyMwAqRbcGg7f22Kcg2gy1F4jBjWR3xQTECVeJPHmxvhg5gUAZC6EYFtnyi6aMDQir1kV8HzCqC2FzTowGgEZqRh7rinqUCDeNDdmYzH/*",
38
- },
39
- ],
40
- },
41
- ],
42
- },
43
- },
44
- });
45
- });
46
- it("has expected asm", () => {
47
- assert.deepStrictEqual(descriptor.atDerivationIndex(0).toAsmString().split(" "), [
48
- "OP_PUSHBYTES_2",
49
- "0004",
50
- "OP_CLTV",
51
- "OP_DROP",
52
- "OP_PUSHNUM_2",
53
- "OP_PUSHBYTES_33",
54
- "02ae7c3c0ebc315a33151a1985ebb1fdcae72b3b91c38e3193c40ebabfffe9c343",
55
- "OP_PUSHBYTES_33",
56
- "0260ba2407f7c75d525db9f171e9b2f3cf5ba3f0d7fc6067b20d4b91585432f974",
57
- "OP_PUSHBYTES_33",
58
- "03eadd6e4300dac62f1d4cf1131a06c5e140911f04245c64934c27510e93dbe843",
59
- "OP_PUSHNUM_3",
60
- "OP_CHECKMULTISIG",
61
- ]);
62
- });
63
- it("can be signed", async function () {
64
- const psbt = Object.assign(new utxolib.Psbt({ network: utxolib.networks.bitcoin }), {
65
- locktime,
66
- });
67
- const signers = rootWalletKeys.triple.slice(0, 2);
68
- const descriptorAt0 = descriptor.atDerivationIndex(0);
69
- const script = Buffer.from(descriptorAt0.scriptPubkey());
70
- psbt.addInput({
71
- hash: Buffer.alloc(32),
72
- index: 0,
73
- sequence: 0xfffffffe,
74
- witnessUtxo: { script, value: BigInt(1e8) },
75
- });
76
- psbt.addOutput({ script, value: BigInt(1e8) });
77
- updateInputWithDescriptor(psbt, 0, descriptorAt0);
78
- for (const signer of signers) {
79
- psbt.signAllInputsHD(signer);
80
- }
81
- finalizePsbt(psbt);
82
- const signedTx = psbt.extractTransaction().toBuffer();
83
- assert.strictEqual(signedTx.toString("hex"), await getFixture("test/fixtures/opdrop.json", signedTx.toString("hex")));
84
- });
85
- });
@@ -1,8 +0,0 @@
1
- import * as utxolib from "@bitgo/utxo-lib";
2
- import { Descriptor, Psbt } from "../js/index.js";
3
- export declare function toWrappedPsbt(psbt: utxolib.bitgo.UtxoPsbt | utxolib.Psbt | Buffer | Uint8Array): Psbt;
4
- export declare function toUtxoPsbt(psbt: Psbt | Buffer | Uint8Array): utxolib.bitgo.UtxoPsbt<utxolib.bitgo.UtxoTransaction<bigint>>;
5
- export declare function updateInputWithDescriptor(psbt: utxolib.Psbt, inputIndex: number, descriptor: Descriptor): void;
6
- export declare function updateOutputWithDescriptor(psbt: utxolib.Psbt, outputIndex: number, descriptor: Descriptor): void;
7
- export declare function finalizePsbt(psbt: utxolib.Psbt): void;
8
- export declare function assertEqualPsbt(a: utxolib.Psbt, b: utxolib.Psbt): void;
@@ -1,113 +0,0 @@
1
- import * as assert from "node:assert";
2
- import * as utxolib from "@bitgo/utxo-lib";
3
- import { Psbt } from "../js/index.js";
4
- export function toWrappedPsbt(psbt) {
5
- if (psbt instanceof utxolib.bitgo.UtxoPsbt || psbt instanceof utxolib.Psbt) {
6
- psbt = psbt.toBuffer();
7
- }
8
- if (psbt instanceof Buffer || psbt instanceof Uint8Array) {
9
- return Psbt.deserialize(psbt);
10
- }
11
- throw new Error("Invalid input");
12
- }
13
- export function toUtxoPsbt(psbt) {
14
- if (psbt instanceof Psbt) {
15
- psbt = psbt.serialize();
16
- }
17
- if (psbt instanceof Buffer || psbt instanceof Uint8Array) {
18
- return utxolib.bitgo.UtxoPsbt.fromBuffer(Buffer.from(psbt), {
19
- network: utxolib.networks.bitcoin,
20
- });
21
- }
22
- throw new Error("Invalid input");
23
- }
24
- export function updateInputWithDescriptor(psbt, inputIndex, descriptor) {
25
- const wrappedPsbt = toWrappedPsbt(psbt);
26
- wrappedPsbt.updateInputWithDescriptor(inputIndex, descriptor);
27
- psbt.data.inputs[inputIndex] = toUtxoPsbt(wrappedPsbt).data.inputs[inputIndex];
28
- }
29
- export function updateOutputWithDescriptor(psbt, outputIndex, descriptor) {
30
- const wrappedPsbt = toWrappedPsbt(psbt);
31
- wrappedPsbt.updateOutputWithDescriptor(outputIndex, descriptor);
32
- psbt.data.outputs[outputIndex] = toUtxoPsbt(wrappedPsbt).data.outputs[outputIndex];
33
- }
34
- export function finalizePsbt(psbt) {
35
- const wrappedPsbt = toWrappedPsbt(psbt);
36
- wrappedPsbt.finalize();
37
- const unwrappedPsbt = toUtxoPsbt(wrappedPsbt);
38
- for (let i = 0; i < psbt.data.inputs.length; i++) {
39
- psbt.data.inputs[i] = unwrappedPsbt.data.inputs[i];
40
- }
41
- }
42
- function toEntries(k, v, path) {
43
- if (matchPath(path, ["data", "inputs", any, "sighashType"])) {
44
- return [];
45
- }
46
- if (matchPath(path.slice(-1), ["unknownKeyVals"])) {
47
- if (Array.isArray(v) && v.length === 0) {
48
- return [];
49
- }
50
- }
51
- return [[k, toPlainObject(v, path)]];
52
- }
53
- const any = Symbol("any");
54
- function matchPath(path, pattern) {
55
- if (path.length !== pattern.length) {
56
- return false;
57
- }
58
- for (let i = 0; i < path.length; i++) {
59
- if (pattern[i] !== any && path[i] !== pattern[i]) {
60
- return false;
61
- }
62
- }
63
- return true;
64
- }
65
- function normalizeBip32Derivation(v) {
66
- if (!Array.isArray(v)) {
67
- throw new Error("Expected bip32Derivation to be an array");
68
- }
69
- return v
70
- .map((e) => {
71
- let { path } = e;
72
- if (path.startsWith("m/")) {
73
- path = path.slice(2);
74
- }
75
- return {
76
- ...e,
77
- path,
78
- };
79
- })
80
- .sort((a, b) => a.masterFingerprint.toString().localeCompare(b.masterFingerprint.toString()));
81
- }
82
- function toPlainObject(v, path) {
83
- // psbts have fun getters and other types of irregular properties that we mash into shape here
84
- if (v === null || v === undefined) {
85
- return v;
86
- }
87
- if (matchPath(path, ["data", "inputs", any, "bip32Derivation"]) ||
88
- matchPath(path, ["data", "outputs", any, "bip32Derivation"])) {
89
- v = normalizeBip32Derivation(v);
90
- }
91
- switch (typeof v) {
92
- case "number":
93
- case "bigint":
94
- case "string":
95
- case "boolean":
96
- return v;
97
- case "object":
98
- if (v instanceof Buffer || v instanceof Uint8Array) {
99
- return v.toString("hex");
100
- }
101
- if (Array.isArray(v)) {
102
- return v.map((v, i) => toPlainObject(v, [...path, i]));
103
- }
104
- return Object.fromEntries(Object.entries(v)
105
- .flatMap(([k, v]) => toEntries(k, v, [...path, k]))
106
- .sort(([a], [b]) => a.localeCompare(b)));
107
- default:
108
- throw new Error(`Unsupported type: ${typeof v}`);
109
- }
110
- }
111
- export function assertEqualPsbt(a, b) {
112
- assert.deepStrictEqual(toPlainObject(a, []), toPlainObject(b, []));
113
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,116 +0,0 @@
1
- import * as utxolib from "@bitgo/utxo-lib";
2
- import * as assert from "node:assert";
3
- import { getPsbtFixtures } from "./psbtFixedScriptCompatFixtures.js";
4
- import { Descriptor } from "../js/index.js";
5
- import { getDescriptorForScriptType } from "./descriptorUtil.js";
6
- import { assertEqualPsbt, toUtxoPsbt, toWrappedPsbt, updateInputWithDescriptor, } from "./psbt.util.js";
7
- import { getKey } from "@bitgo/utxo-lib/dist/src/testutil";
8
- const rootWalletKeys = new utxolib.bitgo.RootWalletKeys(utxolib.testutil.getKeyTriple("wasm"));
9
- function assertEqualBuffer(a, b, message) {
10
- assert.strictEqual(Buffer.from(a).toString("hex"), Buffer.from(b).toString("hex"), message);
11
- }
12
- const fixtures = getPsbtFixtures(rootWalletKeys);
13
- function describeUpdateInputWithDescriptor(psbt, scriptType) {
14
- function getFixtureAtStage(stage) {
15
- const f = fixtures.find((f) => f.scriptType === scriptType && f.stage === stage);
16
- if (!f) {
17
- throw new Error(`Could not find fixture for scriptType ${scriptType} and stage ${stage}`);
18
- }
19
- return f;
20
- }
21
- const descriptorStr = getDescriptorForScriptType(rootWalletKeys, scriptType, "internal");
22
- const index = 0;
23
- const descriptor = Descriptor.fromString(descriptorStr, "derivable");
24
- function getWrappedPsbt() {
25
- return toWrappedPsbt(psbt);
26
- }
27
- function getWrappedPsbtWithDescriptorInfo() {
28
- const wrappedPsbt = getWrappedPsbt();
29
- const descriptorAtDerivation = descriptor.atDerivationIndex(index);
30
- wrappedPsbt.updateInputWithDescriptor(0, descriptorAtDerivation);
31
- wrappedPsbt.updateOutputWithDescriptor(0, descriptorAtDerivation);
32
- return wrappedPsbt;
33
- }
34
- describe("Wrapped PSBT updateInputWithDescriptor", function () {
35
- it("should update the input with the descriptor", function () {
36
- const wrappedPsbt = getWrappedPsbtWithDescriptorInfo();
37
- const updatedPsbt = toUtxoPsbt(wrappedPsbt);
38
- assertEqualPsbt(updatedPsbt, getFixtureAtStage("unsigned").psbt);
39
- updatedPsbt.signAllInputsHD(rootWalletKeys.triple[0]);
40
- updatedPsbt.signAllInputsHD(rootWalletKeys.triple[2]);
41
- const wrappedSignedPsbt = toWrappedPsbt(updatedPsbt);
42
- updatedPsbt.finalizeAllInputs();
43
- wrappedSignedPsbt.finalize();
44
- assertEqualBuffer(updatedPsbt.toBuffer(), wrappedSignedPsbt.serialize());
45
- assertEqualBuffer(getFixtureAtStage("fullsigned")
46
- .psbt.clone()
47
- .finalizeAllInputs()
48
- .extractTransaction()
49
- .toBuffer(), updatedPsbt.extractTransaction().toBuffer());
50
- });
51
- });
52
- describe("updateInputWithDescriptor util", function () {
53
- it("should update the input with the descriptor", function () {
54
- const cloned = psbt.clone();
55
- updateInputWithDescriptor(cloned, 0, descriptor.atDerivationIndex(index));
56
- cloned.signAllInputsHD(rootWalletKeys.triple[0]);
57
- cloned.signAllInputsHD(rootWalletKeys.triple[2]);
58
- cloned.finalizeAllInputs();
59
- assertEqualBuffer(getFixtureAtStage("fullsigned")
60
- .psbt.clone()
61
- .finalizeAllInputs()
62
- .extractTransaction()
63
- .toBuffer(), cloned.extractTransaction().toBuffer());
64
- });
65
- });
66
- describe("psbt signWithXprv", function () {
67
- function signWithKey(keys, { checkFinalized = false } = {}) {
68
- it(`signs the input with keys ${keys.join(", ")}`, function () {
69
- const psbt = getWrappedPsbtWithDescriptorInfo();
70
- keys.forEach((keyName) => {
71
- const key = keyName === "unrelated" ? getKey(keyName) : rootWalletKeys[keyName];
72
- const derivationPaths = toUtxoPsbt(psbt).data.inputs[0].bip32Derivation.map((d) => d.path);
73
- assert.ok(derivationPaths.every((p) => p === derivationPaths[0]));
74
- const derived = key.derivePath(derivationPaths[0]);
75
- assert.deepStrictEqual(psbt.signWithXprv(key.toBase58()), {
76
- // map: input index -> pubkey array
77
- 0: { Ecdsa: keyName === "unrelated" ? [] : [derived.publicKey.toString("hex")] },
78
- });
79
- });
80
- if (checkFinalized) {
81
- psbt.finalize();
82
- assertEqualBuffer(toUtxoPsbt(psbt).extractTransaction().toBuffer(), getFixtureAtStage("fullsigned")
83
- .psbt.finalizeAllInputs()
84
- .extractTransaction()
85
- .toBuffer());
86
- }
87
- });
88
- }
89
- signWithKey(["user"]);
90
- signWithKey(["backup"]);
91
- signWithKey(["bitgo"]);
92
- signWithKey(["unrelated"]);
93
- signWithKey(["user", "bitgo"], { checkFinalized: true });
94
- });
95
- }
96
- describe("PSBT fixture", function () {
97
- fixtures.forEach(({ psbt, scriptType, stage }) => {
98
- describe(`PSBT fixture ${scriptType} ${stage}`, function () {
99
- let buf;
100
- let wrappedPsbt;
101
- before(function () {
102
- buf = psbt.toBuffer();
103
- wrappedPsbt = toWrappedPsbt(buf);
104
- });
105
- it("should map to same hex", function () {
106
- assertEqualBuffer(buf, wrappedPsbt.serialize());
107
- });
108
- it("should round-trip utxolib -> ms -> utxolib", function () {
109
- assertEqualBuffer(buf, toUtxoPsbt(wrappedPsbt).toBuffer());
110
- });
111
- if (stage === "bare") {
112
- describeUpdateInputWithDescriptor(psbt, scriptType);
113
- }
114
- });
115
- });
116
- });
@@ -1,10 +0,0 @@
1
- import * as utxolib from "@bitgo/utxo-lib";
2
- import { RootWalletKeys } from "@bitgo/utxo-lib/dist/src/bitgo";
3
- export type PsbtStage = "bare" | "unsigned" | "halfsigned" | "fullsigned";
4
- export declare function toPsbtWithPrevOutOnly(psbt: utxolib.bitgo.UtxoPsbt): utxolib.bitgo.UtxoPsbt<utxolib.bitgo.UtxoTransaction<bigint>>;
5
- export type PsbtFixture = {
6
- psbt: utxolib.bitgo.UtxoPsbt;
7
- scriptType: utxolib.bitgo.outputScripts.ScriptType2Of3;
8
- stage: PsbtStage;
9
- };
10
- export declare function getPsbtFixtures(keys: RootWalletKeys): PsbtFixture[];
@@ -1,53 +0,0 @@
1
- import * as utxolib from "@bitgo/utxo-lib";
2
- export function toPsbtWithPrevOutOnly(psbt) {
3
- const psbtCopy = utxolib.bitgo.UtxoPsbt.createPsbt({
4
- network: utxolib.networks.bitcoin,
5
- });
6
- psbtCopy.setVersion(psbt.version);
7
- psbtCopy.setLocktime(psbt.locktime);
8
- psbt.txInputs.forEach((input, vin) => {
9
- const { witnessUtxo, nonWitnessUtxo } = psbt.data.inputs[vin];
10
- psbtCopy.addInput({
11
- hash: input.hash,
12
- index: input.index,
13
- sequence: input.sequence,
14
- ...(witnessUtxo ? { witnessUtxo } : { nonWitnessUtxo }),
15
- });
16
- });
17
- psbt.txOutputs.forEach((output) => {
18
- psbtCopy.addOutput(output);
19
- });
20
- return psbtCopy;
21
- }
22
- function getPsbtWithScriptTypeAndStage(keys, scriptType, stage) {
23
- if (stage === "bare") {
24
- const psbt = getPsbtWithScriptTypeAndStage(keys, scriptType, "unsigned");
25
- return toPsbtWithPrevOutOnly(psbt);
26
- }
27
- return utxolib.testutil.constructPsbt([
28
- {
29
- scriptType,
30
- value: BigInt(1e8),
31
- },
32
- ], [
33
- {
34
- value: BigInt(1e8 - 1000),
35
- scriptType,
36
- isInternalAddress: true,
37
- },
38
- ], utxolib.networks.bitcoin, keys, stage);
39
- }
40
- export function getPsbtFixtures(keys) {
41
- const testMatrixScriptTypes = ["p2sh", "p2shP2wsh", "p2wsh"];
42
- const testMatrixStages = ["bare", "unsigned", "halfsigned", "fullsigned"];
43
- return testMatrixStages.flatMap((stage) => {
44
- return testMatrixScriptTypes.map((scriptType) => {
45
- return {
46
- psbt: getPsbtWithScriptTypeAndStage(keys, scriptType, stage),
47
- name: `${scriptType}-${stage}`,
48
- scriptType,
49
- stage,
50
- };
51
- });
52
- });
53
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,104 +0,0 @@
1
- import assert from "node:assert";
2
- import { ECPair } from "@bitgo/utxo-lib";
3
- import { getKey } from "@bitgo/utxo-lib/dist/src/testutil";
4
- import { formatNode } from "../js/ast/index.js";
5
- import { mockPsbtDefault } from "./psbtFromDescriptor.util.js";
6
- import { Descriptor } from "../js/index.js";
7
- import { toWrappedPsbt } from "./psbt.util.js";
8
- function toKeyWithPath(k, path = "*") {
9
- return k.neutered().toBase58() + "/" + path;
10
- }
11
- function toECPair(k) {
12
- assert(k.privateKey);
13
- return ECPair.fromPrivateKey(k.privateKey);
14
- }
15
- function toKeyPlainXOnly(k) {
16
- return k.subarray(1).toString("hex");
17
- }
18
- const external = getKey("external");
19
- const a = getKey("a");
20
- const b = getKey("b");
21
- const c = getKey("c");
22
- const keys = { external, a, b, c };
23
- function getKeyName(k) {
24
- const objKeys = Object.keys(keys);
25
- return objKeys.find((key) => keys[key] === k || toECPair(keys[key]).publicKey.equals(k.publicKey));
26
- }
27
- function describeSignDescriptor(name, descriptor, { signBip32 = [], signECPair = [], }) {
28
- describe(`psbt with descriptor ${name}`, function () {
29
- const isTaproot = Object.keys(descriptor.node())[0] === "Tr";
30
- const psbt = mockPsbtDefault({
31
- descriptorSelf: descriptor,
32
- descriptorOther: Descriptor.fromString(formatNode({ wpkh: toKeyWithPath(external) }), "derivable"),
33
- });
34
- function getSigResult(keys) {
35
- return {
36
- [isTaproot ? "Schnorr" : "Ecdsa"]: keys.map((key) => key.publicKey.subarray(isTaproot ? 1 : 0).toString("hex")),
37
- };
38
- }
39
- signBip32.forEach((signSeq) => {
40
- it(`should sign ${signSeq.map((k) => getKeyName(k)).join(", ")} xprv`, function () {
41
- const wrappedPsbt = toWrappedPsbt(psbt);
42
- signSeq.forEach((key) => {
43
- assert.deepStrictEqual(wrappedPsbt.signWithXprv(key.toBase58()), {
44
- 0: getSigResult([key.derive(0)]),
45
- 1: getSigResult([key.derive(1)]),
46
- });
47
- });
48
- wrappedPsbt.finalize();
49
- });
50
- it(`should sign ${signSeq.map((k) => getKeyName(k)).join(", ")} prv buffer`, function () {
51
- const wrappedPsbt = toWrappedPsbt(psbt);
52
- signSeq.forEach((key) => {
53
- assert.deepStrictEqual(wrappedPsbt.signWithPrv(key.derive(0).privateKey), {
54
- // NOTE: signing with a plain derived key does not work for taproot
55
- // see SingleKeySigner implementation in psbt.rs for details
56
- 0: getSigResult(isTaproot ? [] : [key.derive(0)]),
57
- 1: getSigResult([]),
58
- });
59
- });
60
- });
61
- });
62
- signECPair.forEach((signSeq) => {
63
- it(`should sign ${signSeq.map((k) => getKeyName(k)).join(", ")} ec pair`, function () {
64
- const wrappedPsbt = toWrappedPsbt(psbt);
65
- signSeq.forEach((key) => {
66
- assert(key.privateKey);
67
- assert.deepStrictEqual(wrappedPsbt.signWithPrv(key.privateKey), {
68
- 0: getSigResult([key]),
69
- 1: getSigResult([key]),
70
- });
71
- });
72
- wrappedPsbt.finalize();
73
- });
74
- });
75
- });
76
- }
77
- function fromNodes(node, type) {
78
- return Descriptor.fromString(formatNode(node), type);
79
- }
80
- describeSignDescriptor("Wsh2Of3", fromNodes({
81
- wsh: { multi: [2, toKeyWithPath(a), toKeyWithPath(b), toKeyWithPath(c)] },
82
- }, "derivable"), {
83
- signBip32: [
84
- [a, b],
85
- [b, a],
86
- ],
87
- });
88
- describeSignDescriptor("Tr1Of3", fromNodes({
89
- tr: [toKeyWithPath(a), [{ pk: toKeyWithPath(b) }, { pk: toKeyWithPath(c) }]],
90
- }, "derivable"), { signBip32: [[a], [b], [c]] });
91
- describeSignDescriptor("TrWithExternalPlain", fromNodes({
92
- tr: [
93
- toKeyPlainXOnly(external.publicKey),
94
- [
95
- { pk: toKeyPlainXOnly(external.publicKey) },
96
- {
97
- or_b: [
98
- { pk: toKeyPlainXOnly(external.publicKey) },
99
- { "s:pk": toKeyPlainXOnly(a.publicKey) },
100
- ],
101
- },
102
- ],
103
- ],
104
- }, "definite"), { signECPair: [[toECPair(a)]] });
@@ -1,63 +0,0 @@
1
- import * as utxolib from "@bitgo/utxo-lib";
2
- import { Descriptor } from "../js/index.js";
3
- export declare function createScriptPubKeyFromDescriptor(descriptor: Descriptor, index?: number): Buffer;
4
- export type Output = {
5
- script: Buffer;
6
- value: bigint;
7
- };
8
- export type WithDescriptor<T> = T & {
9
- descriptor: Descriptor;
10
- };
11
- export type PrevOutput = {
12
- hash: string;
13
- index: number;
14
- witnessUtxo: Output;
15
- };
16
- export type DescriptorWalletOutput = PrevOutput & {
17
- descriptorName: string;
18
- descriptorIndex: number;
19
- };
20
- export type DerivedDescriptorWalletOutput = WithDescriptor<PrevOutput>;
21
- export declare function toDerivedDescriptorWalletOutput(output: DescriptorWalletOutput, descriptor: Descriptor): DerivedDescriptorWalletOutput;
22
- /**
23
- * Non-Final (Replaceable)
24
- * Reference: https://github.com/bitcoin/bitcoin/blob/v25.1/src/rpc/rawtransaction_util.cpp#L49
25
- * */
26
- export declare const MAX_BIP125_RBF_SEQUENCE: number;
27
- type WithOptDescriptor<T> = T & {
28
- descriptor?: Descriptor;
29
- };
30
- export declare function createPsbt(params: PsbtParams, inputs: DerivedDescriptorWalletOutput[], outputs: WithOptDescriptor<Output>[]): utxolib.bitgo.UtxoPsbt;
31
- type MockOutputIdParams = {
32
- hash?: string;
33
- vout?: number;
34
- };
35
- type BaseMockDescriptorOutputParams = {
36
- id?: MockOutputIdParams;
37
- index?: number;
38
- value?: bigint;
39
- };
40
- export declare function mockDerivedDescriptorWalletOutput(descriptor: Descriptor, outputParams?: BaseMockDescriptorOutputParams): DerivedDescriptorWalletOutput;
41
- type MockInput = BaseMockDescriptorOutputParams & {
42
- index: number;
43
- descriptor: Descriptor;
44
- };
45
- type MockOutput = {
46
- descriptor: Descriptor;
47
- index: number;
48
- value: bigint;
49
- external?: boolean;
50
- };
51
- export declare function mockPsbt(inputs: MockInput[], outputs: MockOutput[], params?: Partial<PsbtParams>): utxolib.bitgo.UtxoPsbt;
52
- export type PsbtParams = {
53
- network: utxolib.Network;
54
- version?: number;
55
- locktime?: number;
56
- sequence?: number;
57
- };
58
- export declare function mockPsbtDefault({ descriptorSelf, descriptorOther, params, }: {
59
- descriptorSelf: Descriptor;
60
- descriptorOther: Descriptor;
61
- params?: Partial<PsbtParams>;
62
- }): utxolib.bitgo.UtxoPsbt;
63
- export {};
@@ -1,101 +0,0 @@
1
- import * as utxolib from "@bitgo/utxo-lib";
2
- import { toUtxoPsbt, toWrappedPsbt } from "./psbt.util.js";
3
- export function createScriptPubKeyFromDescriptor(descriptor, index) {
4
- if (index === undefined) {
5
- return Buffer.from(descriptor.scriptPubkey());
6
- }
7
- return createScriptPubKeyFromDescriptor(descriptor.atDerivationIndex(index));
8
- }
9
- export function toDerivedDescriptorWalletOutput(output, descriptor) {
10
- const derivedDescriptor = descriptor.atDerivationIndex(output.descriptorIndex);
11
- const script = createScriptPubKeyFromDescriptor(derivedDescriptor);
12
- if (!script.equals(output.witnessUtxo.script)) {
13
- throw new Error(`Script mismatch: descriptor ${output.descriptorName} ${descriptor.toString()} script=${script.toString("hex")}`);
14
- }
15
- return {
16
- hash: output.hash,
17
- index: output.index,
18
- witnessUtxo: output.witnessUtxo,
19
- descriptor: descriptor.atDerivationIndex(output.descriptorIndex),
20
- };
21
- }
22
- /**
23
- * Non-Final (Replaceable)
24
- * Reference: https://github.com/bitcoin/bitcoin/blob/v25.1/src/rpc/rawtransaction_util.cpp#L49
25
- * */
26
- export const MAX_BIP125_RBF_SEQUENCE = 0xffffffff - 2;
27
- function updateInputsWithDescriptors(psbt, descriptors) {
28
- if (psbt.txInputs.length !== descriptors.length) {
29
- throw new Error(`Input count mismatch (psbt=${psbt.txInputs.length}, descriptors=${descriptors.length})`);
30
- }
31
- const wrappedPsbt = toWrappedPsbt(psbt);
32
- for (const [inputIndex, descriptor] of descriptors.entries()) {
33
- wrappedPsbt.updateInputWithDescriptor(inputIndex, descriptor);
34
- }
35
- const unwrappedPsbt = toUtxoPsbt(wrappedPsbt);
36
- for (let inputIndex = 0; inputIndex < psbt.txInputs.length; inputIndex++) {
37
- psbt.data.inputs[inputIndex] = unwrappedPsbt.data.inputs[inputIndex];
38
- }
39
- }
40
- function updateOutputsWithDescriptors(psbt, descriptors) {
41
- const wrappedPsbt = toWrappedPsbt(psbt);
42
- for (const [outputIndex, { descriptor }] of descriptors.entries()) {
43
- if (descriptor) {
44
- wrappedPsbt.updateOutputWithDescriptor(outputIndex, descriptor);
45
- }
46
- }
47
- const unwrappedPsbt = toUtxoPsbt(wrappedPsbt);
48
- for (let outputIndex = 0; outputIndex < psbt.txOutputs.length; outputIndex++) {
49
- psbt.data.outputs[outputIndex] = unwrappedPsbt.data.outputs[outputIndex];
50
- }
51
- }
52
- export function createPsbt(params, inputs, outputs) {
53
- const psbt = utxolib.bitgo.UtxoPsbt.createPsbt({ network: params.network });
54
- psbt.setVersion(params.version ?? 2);
55
- psbt.setLocktime(params.locktime ?? 0);
56
- psbt.addInputs(inputs.map((i) => ({ ...i, sequence: params.sequence ?? MAX_BIP125_RBF_SEQUENCE })));
57
- psbt.addOutputs(outputs);
58
- updateInputsWithDescriptors(psbt, inputs.map((i) => i.descriptor));
59
- updateOutputsWithDescriptors(psbt, outputs);
60
- return psbt;
61
- }
62
- function mockOutputId(id) {
63
- const hash = id?.hash ?? Buffer.alloc(32, 1).toString("hex");
64
- const vout = id?.vout ?? 0;
65
- return { hash, vout };
66
- }
67
- export function mockDerivedDescriptorWalletOutput(descriptor, outputParams = {}) {
68
- const { value = BigInt(1e6) } = outputParams;
69
- const { hash, vout } = mockOutputId(outputParams.id);
70
- return {
71
- hash,
72
- index: vout,
73
- witnessUtxo: {
74
- script: createScriptPubKeyFromDescriptor(descriptor),
75
- value,
76
- },
77
- descriptor,
78
- };
79
- }
80
- function deriveIfWildcard(descriptor, index) {
81
- return descriptor.hasWildcard() ? descriptor.atDerivationIndex(index) : descriptor;
82
- }
83
- export function mockPsbt(inputs, outputs, params = {}) {
84
- return createPsbt({ ...params, network: params.network ?? utxolib.networks.bitcoin }, inputs.map((i) => mockDerivedDescriptorWalletOutput(deriveIfWildcard(i.descriptor, i.index), i)), outputs.map((o) => {
85
- const derivedDescriptor = deriveIfWildcard(o.descriptor, o.index);
86
- return {
87
- script: createScriptPubKeyFromDescriptor(derivedDescriptor),
88
- value: o.value,
89
- descriptor: o.external ? undefined : derivedDescriptor,
90
- };
91
- }));
92
- }
93
- export function mockPsbtDefault({ descriptorSelf, descriptorOther, params = {}, }) {
94
- return mockPsbt([
95
- { descriptor: descriptorSelf, index: 0 },
96
- { descriptor: descriptorSelf, index: 1, id: { vout: 1 } },
97
- ], [
98
- { descriptor: descriptorOther, index: 0, value: BigInt(4e5), external: true },
99
- { descriptor: descriptorSelf, index: 0, value: BigInt(4e5) },
100
- ], params);
101
- }
@@ -1 +0,0 @@
1
- export {};