@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,52 +0,0 @@
1
- import * as assert from "node:assert";
2
- import * as fs from "fs/promises";
3
- import * as utxolib from "@bitgo/utxo-lib";
4
- import { formatNode } from "../js/ast/index.js";
5
- async function assertEqualJSON(path, value) {
6
- try {
7
- const data = JSON.parse(await fs.readFile(path, "utf8"));
8
- assert.deepStrictEqual(data, value);
9
- }
10
- catch (e) {
11
- if (typeof e === "object" && e !== null && "code" in e && e.code === "ENOENT") {
12
- await fs.writeFile(path, JSON.stringify(value, null, 2));
13
- throw new Error("Expected file not found, wrote it instead");
14
- }
15
- throw e;
16
- }
17
- }
18
- export async function assertEqualFixture(path, content) {
19
- await assertEqualJSON(path, content);
20
- }
21
- /** Expand a template with the given root wallet keys and chain code */
22
- function expand(rootWalletKeys, keyIndex, chainCode) {
23
- if (keyIndex !== 0 && keyIndex !== 1 && keyIndex !== 2) {
24
- throw new Error("Invalid key index");
25
- }
26
- const xpub = rootWalletKeys.triple[keyIndex].neutered().toBase58();
27
- const prefix = rootWalletKeys.derivationPrefixes[keyIndex];
28
- return xpub + "/" + prefix + "/" + chainCode + "/*";
29
- }
30
- /**
31
- * Get a standard output descriptor that corresponds to the proprietary HD wallet setup
32
- * used in BitGo wallets.
33
- * Only supports a subset of script types.
34
- */
35
- export function getDescriptorForScriptType(rootWalletKeys, scriptType, scope) {
36
- const chain = scope === "external"
37
- ? utxolib.bitgo.getExternalChainCode(scriptType)
38
- : utxolib.bitgo.getInternalChainCode(scriptType);
39
- const multi = {
40
- multi: [2, ...rootWalletKeys.triple.map((_, i) => expand(rootWalletKeys, i, chain))],
41
- };
42
- switch (scriptType) {
43
- case "p2sh":
44
- return formatNode({ sh: multi });
45
- case "p2shP2wsh":
46
- return formatNode({ sh: { wsh: multi } });
47
- case "p2wsh":
48
- return formatNode({ wsh: multi });
49
- default:
50
- throw new Error(`Unsupported script type ${scriptType}`);
51
- }
52
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,137 +0,0 @@
1
- import * as assert from "assert";
2
- import { ECPair } from "../js/ecpair.js";
3
- describe("WasmECPair", () => {
4
- const testPrivateKey = Buffer.from("1111111111111111111111111111111111111111111111111111111111111111", "hex");
5
- const testWifMainnet = "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn";
6
- const testWifTestnet = "cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA";
7
- it("should create from private key", () => {
8
- const key = ECPair.fromPrivateKey(testPrivateKey);
9
- assert.ok(key.privateKey instanceof Uint8Array);
10
- assert.ok(key.publicKey instanceof Uint8Array);
11
- assert.strictEqual(key.privateKey.length, 32);
12
- assert.strictEqual(key.publicKey.length, 33); // Always compressed
13
- });
14
- it("should create from public key", () => {
15
- const tempKey = ECPair.fromPrivateKey(testPrivateKey);
16
- const publicKey = tempKey.publicKey;
17
- const key = ECPair.fromPublicKey(publicKey);
18
- assert.strictEqual(key.privateKey, undefined);
19
- assert.ok(key.publicKey instanceof Uint8Array);
20
- assert.strictEqual(key.publicKey.length, 33);
21
- });
22
- it("should create from mainnet WIF", () => {
23
- const key = ECPair.fromWIF(testWifMainnet);
24
- assert.ok(key.privateKey instanceof Uint8Array);
25
- assert.ok(key.publicKey instanceof Uint8Array);
26
- assert.strictEqual(key.privateKey.length, 32);
27
- });
28
- it("should create from testnet WIF", () => {
29
- const key = ECPair.fromWIF(testWifTestnet);
30
- assert.ok(key.privateKey instanceof Uint8Array);
31
- assert.ok(key.publicKey instanceof Uint8Array);
32
- assert.strictEqual(key.privateKey.length, 32);
33
- });
34
- it("should create from mainnet WIF using fromWIFMainnet", () => {
35
- const key = ECPair.fromWIFMainnet(testWifMainnet);
36
- assert.ok(key.privateKey instanceof Uint8Array);
37
- assert.ok(key.publicKey instanceof Uint8Array);
38
- });
39
- it("should create from testnet WIF using fromWIFTestnet", () => {
40
- const key = ECPair.fromWIFTestnet(testWifTestnet);
41
- assert.ok(key.privateKey instanceof Uint8Array);
42
- assert.ok(key.publicKey instanceof Uint8Array);
43
- });
44
- it("should fail when using wrong network WIF method", () => {
45
- assert.throws(() => {
46
- ECPair.fromWIFMainnet(testWifTestnet);
47
- });
48
- assert.throws(() => {
49
- ECPair.fromWIFTestnet(testWifMainnet);
50
- });
51
- });
52
- it("should export to WIF mainnet", () => {
53
- const key = ECPair.fromPrivateKey(testPrivateKey);
54
- const wif = key.toWIF();
55
- assert.ok(typeof wif === "string");
56
- assert.ok(wif.length > 0);
57
- assert.ok(wif.startsWith("K") || wif.startsWith("L")); // Mainnet compressed
58
- });
59
- it("should export to WIF testnet", () => {
60
- const key = ECPair.fromPrivateKey(testPrivateKey);
61
- const wif = key.toWIFTestnet();
62
- assert.ok(typeof wif === "string");
63
- assert.ok(wif.length > 0);
64
- assert.ok(wif.startsWith("c")); // Testnet compressed
65
- });
66
- it("should roundtrip WIF mainnet", () => {
67
- const key1 = ECPair.fromPrivateKey(testPrivateKey);
68
- const wif = key1.toWIF();
69
- const key2 = ECPair.fromWIF(wif);
70
- assert.deepStrictEqual(key1.privateKey, key2.privateKey);
71
- assert.deepStrictEqual(key1.publicKey, key2.publicKey);
72
- });
73
- it("should roundtrip WIF testnet", () => {
74
- const key1 = ECPair.fromPrivateKey(testPrivateKey);
75
- const wif = key1.toWIFTestnet();
76
- const key2 = ECPair.fromWIF(wif);
77
- assert.deepStrictEqual(key1.privateKey, key2.privateKey);
78
- assert.deepStrictEqual(key1.publicKey, key2.publicKey);
79
- });
80
- it("should fail to export WIF from public key", () => {
81
- const tempKey = ECPair.fromPrivateKey(testPrivateKey);
82
- const publicKey = tempKey.publicKey;
83
- const key = ECPair.fromPublicKey(publicKey);
84
- assert.throws(() => {
85
- key.toWIF();
86
- });
87
- assert.throws(() => {
88
- key.toWIFMainnet();
89
- });
90
- assert.throws(() => {
91
- key.toWIFTestnet();
92
- });
93
- });
94
- it("should reject invalid private keys", () => {
95
- // All zeros
96
- assert.throws(() => {
97
- ECPair.fromPrivateKey(new Uint8Array(32));
98
- });
99
- // Wrong length
100
- assert.throws(() => {
101
- ECPair.fromPrivateKey(new Uint8Array(31));
102
- });
103
- assert.throws(() => {
104
- ECPair.fromPrivateKey(new Uint8Array(33));
105
- });
106
- });
107
- it("should reject invalid public keys", () => {
108
- // Wrong length
109
- assert.throws(() => {
110
- ECPair.fromPublicKey(new Uint8Array(32));
111
- });
112
- assert.throws(() => {
113
- ECPair.fromPublicKey(new Uint8Array(34));
114
- });
115
- // Invalid format
116
- assert.throws(() => {
117
- const invalidPubkey = new Uint8Array(33);
118
- invalidPubkey[0] = 0x01; // Invalid prefix
119
- ECPair.fromPublicKey(invalidPubkey);
120
- });
121
- });
122
- it("should always produce compressed public keys", () => {
123
- const key1 = ECPair.fromPrivateKey(testPrivateKey);
124
- const key2 = ECPair.fromWIF(testWifMainnet);
125
- // All public keys should be 33 bytes (compressed)
126
- assert.strictEqual(key1.publicKey.length, 33);
127
- assert.strictEqual(key2.publicKey.length, 33);
128
- // All should start with 0x02 or 0x03 (compressed format)
129
- assert.ok(key1.publicKey[0] === 0x02 || key1.publicKey[0] === 0x03);
130
- assert.ok(key2.publicKey[0] === 0x02 || key2.publicKey[0] === 0x03);
131
- });
132
- it("should derive same public key from same private key", () => {
133
- const key1 = ECPair.fromPrivateKey(testPrivateKey);
134
- const key2 = ECPair.fromPrivateKey(testPrivateKey);
135
- assert.deepStrictEqual(key1.publicKey, key2.publicKey);
136
- });
137
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,66 +0,0 @@
1
- import assert from "node:assert";
2
- import * as utxolib from "@bitgo/utxo-lib";
3
- import { fixedScriptWallet } from "../../js/index.js";
4
- function getAddressUtxoLib(keys, chain, index, network, addressFormat) {
5
- if (!utxolib.bitgo.isChainCode(chain)) {
6
- throw new Error(`Invalid chain code: ${chain}`);
7
- }
8
- const derived = keys.deriveForChainAndIndex(chain, index);
9
- const script = utxolib.bitgo.outputScripts.createOutputScript2of3(derived.publicKeys, utxolib.bitgo.outputScripts.scriptTypeForChain(chain));
10
- const address = utxolib.addressFormat.fromOutputScriptWithFormat(script.scriptPubKey, addressFormat, network);
11
- return address;
12
- }
13
- function runTest(network, { derivationPrefixes, addressFormat, } = {}) {
14
- describe(`address for network ${utxolib.getNetworkName(network)}, derivationPrefixes=${Boolean(derivationPrefixes)}`, function () {
15
- const keyTriple = utxolib.testutil.getKeyTriple("wasm");
16
- const rootWalletKeys = new utxolib.bitgo.RootWalletKeys(keyTriple.map((k) => k.neutered()), derivationPrefixes);
17
- const supportedChainCodes = utxolib.bitgo.chainCodes.filter((chainCode) => {
18
- const scriptType = utxolib.bitgo.outputScripts.scriptTypeForChain(chainCode);
19
- return utxolib.bitgo.outputScripts.isSupportedScriptType(network, scriptType);
20
- });
21
- it(`can recreate address from wallet keys for chain codes ${supportedChainCodes.join(", ")}`, function () {
22
- for (const chainCode of supportedChainCodes) {
23
- for (let index = 0; index < 2; index++) {
24
- const utxolibAddress = getAddressUtxoLib(rootWalletKeys, chainCode, index, network, addressFormat ?? "default");
25
- const wasmAddress = fixedScriptWallet.address(rootWalletKeys, chainCode, index, network, addressFormat);
26
- assert.strictEqual(utxolibAddress, wasmAddress);
27
- }
28
- }
29
- });
30
- const unsupportedChainCodes = utxolib.bitgo.chainCodes.filter((chainCode) => {
31
- const scriptType = utxolib.bitgo.outputScripts.scriptTypeForChain(chainCode);
32
- return !utxolib.bitgo.outputScripts.isSupportedScriptType(network, scriptType);
33
- });
34
- if (unsupportedChainCodes.length > 0) {
35
- it(`throws error for unsupported chain codes ${unsupportedChainCodes.join(", ")}`, function () {
36
- for (const chainCode of unsupportedChainCodes) {
37
- const scriptType = utxolib.bitgo.outputScripts.scriptTypeForChain(chainCode);
38
- assert.throws(() => {
39
- fixedScriptWallet.address(rootWalletKeys, chainCode, 0, network, addressFormat);
40
- }, (error) => {
41
- const errorMessage = error.message.toLowerCase();
42
- const isSegwitError = scriptType === "p2shP2wsh" || scriptType === "p2wsh";
43
- const isTaprootError = scriptType === "p2tr" || scriptType === "p2trMusig2";
44
- if (isSegwitError) {
45
- return errorMessage.includes("does not support segwit");
46
- }
47
- else if (isTaprootError) {
48
- return errorMessage.includes("does not support taproot");
49
- }
50
- return false;
51
- }, `Expected error for unsupported script type ${scriptType} on network ${utxolib.getNetworkName(network)}`);
52
- }
53
- });
54
- }
55
- });
56
- }
57
- describe("address for networks", function () {
58
- utxolib.getNetworkList().forEach((network) => {
59
- runTest(network);
60
- runTest(network, { derivationPrefixes: ["m/1/2", "m/0/0", "m/0/0"] });
61
- if (utxolib.getMainnet(network) === utxolib.networks.bitcoincash ||
62
- utxolib.getMainnet(network) === utxolib.networks.ecash) {
63
- runTest(network, { addressFormat: "cashaddr" });
64
- }
65
- });
66
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,66 +0,0 @@
1
- import assert from "node:assert";
2
- import * as utxolib from "@bitgo/utxo-lib";
3
- import { fixedScriptWallet } from "../../js/index.js";
4
- import { loadPsbtFixture, getPsbtBuffer, getExtractedTransactionHex, } from "./fixtureUtil.js";
5
- describe("finalize and extract transaction", function () {
6
- const supportedNetworks = utxolib.getNetworkList().filter((network) => {
7
- return (utxolib.isMainnet(network) &&
8
- network !== utxolib.networks.bitcoincash &&
9
- network !== utxolib.networks.bitcoingold &&
10
- network !== utxolib.networks.bitcoinsv &&
11
- network !== utxolib.networks.ecash &&
12
- network !== utxolib.networks.zcash);
13
- });
14
- supportedNetworks.forEach((network) => {
15
- const networkName = utxolib.getNetworkName(network);
16
- describe(`network: ${networkName}`, function () {
17
- let fullsignedFixture;
18
- let fullsignedPsbtBuffer;
19
- let fullsignedBitgoPsbt;
20
- before(function () {
21
- fullsignedFixture = loadPsbtFixture(networkName, "fullsigned");
22
- fullsignedPsbtBuffer = getPsbtBuffer(fullsignedFixture);
23
- fullsignedBitgoPsbt = fixedScriptWallet.BitGoPsbt.fromBytes(fullsignedPsbtBuffer, networkName);
24
- });
25
- it("should serialize and deserialize PSBT (round-trip)", function () {
26
- const serialized = fullsignedBitgoPsbt.serialize();
27
- // Verify we can deserialize what we serialized (functional round-trip)
28
- const deserialized = fixedScriptWallet.BitGoPsbt.fromBytes(serialized, networkName);
29
- // Verify the deserialized PSBT has the same unsigned txid
30
- assert.strictEqual(deserialized.unsignedTxid(), fullsignedBitgoPsbt.unsignedTxid(), "Deserialized PSBT should have same unsigned txid after round-trip");
31
- // Verify the re-deserialized PSBT can be serialized back to bytes
32
- const reserialized = deserialized.serialize();
33
- // Verify functional equivalence by deserializing again and checking txid
34
- const redeserialized = fixedScriptWallet.BitGoPsbt.fromBytes(reserialized, networkName);
35
- assert.strictEqual(redeserialized.unsignedTxid(), fullsignedBitgoPsbt.unsignedTxid(), "PSBT should maintain consistency through multiple serialize/deserialize cycles");
36
- });
37
- it("should finalize all inputs and be extractable", function () {
38
- // Create a fresh instance for finalization
39
- const psbt = fixedScriptWallet.BitGoPsbt.fromBytes(fullsignedPsbtBuffer, networkName);
40
- // Finalize all inputs
41
- psbt.finalizeAllInputs();
42
- // Serialize the finalized PSBT
43
- const serialized = psbt.serialize();
44
- // Verify we can deserialize the finalized PSBT
45
- const deserialized = fixedScriptWallet.BitGoPsbt.fromBytes(serialized, networkName);
46
- // Verify it can be extracted (which confirms finalization worked)
47
- const extractedTx = deserialized.extractTransaction();
48
- const extractedTxHex = Buffer.from(extractedTx).toString("hex");
49
- const expectedTxHex = getExtractedTransactionHex(fullsignedFixture);
50
- assert.strictEqual(extractedTxHex, expectedTxHex, "Extracted transaction from finalized PSBT should match expected transaction");
51
- });
52
- it("should extract transaction from finalized PSBT", function () {
53
- // Create a fresh instance for extraction
54
- const psbt = fixedScriptWallet.BitGoPsbt.fromBytes(fullsignedPsbtBuffer, networkName);
55
- // Finalize all inputs
56
- psbt.finalizeAllInputs();
57
- // Extract transaction
58
- const extractedTx = psbt.extractTransaction();
59
- const extractedTxHex = Buffer.from(extractedTx).toString("hex");
60
- // Get expected transaction hex from fixture
61
- const expectedTxHex = getExtractedTransactionHex(fullsignedFixture);
62
- assert.strictEqual(extractedTxHex, expectedTxHex, "Extracted transaction should match expected transaction");
63
- });
64
- });
65
- });
66
- });
@@ -1,103 +0,0 @@
1
- import { RootWalletKeys } from "../../js/fixedScriptWallet/RootWalletKeys.js";
2
- import { ECPair } from "../../js/ecpair.js";
3
- import type { BitGoPsbt, NetworkName } from "../../js/fixedScriptWallet/index.js";
4
- export type SignatureState = "unsigned" | "halfsigned" | "fullsigned";
5
- export type Triple<T> = [T, T, T];
6
- export type Bip32Derivation = {
7
- masterFingerprint: string;
8
- pubkey: string;
9
- path: string;
10
- };
11
- export type TapBip32Derivation = Bip32Derivation & {
12
- leafHashes: string[];
13
- };
14
- export type WitnessUtxo = {
15
- value: string;
16
- script: string;
17
- };
18
- export type TapLeafScript = {
19
- controlBlock: string;
20
- script: string;
21
- leafVersion: number;
22
- };
23
- export type PsbtInput = {
24
- type: string;
25
- sighashType: number;
26
- redeemScript?: string;
27
- witnessScript?: string;
28
- bip32Derivation?: Bip32Derivation[];
29
- tapBip32Derivation?: TapBip32Derivation[];
30
- witnessUtxo?: WitnessUtxo;
31
- tapLeafScript?: TapLeafScript[];
32
- tapInternalKey?: string;
33
- tapMerkleRoot?: string;
34
- musig2Participants?: {
35
- tapOutputKey: string;
36
- tapInternalKey: string;
37
- participantPubKeys: string[];
38
- };
39
- unknownKeyVals?: Array<{
40
- key: string;
41
- value: string;
42
- }>;
43
- };
44
- export type Input = {
45
- hash: string;
46
- index: number;
47
- sequence: number;
48
- };
49
- export type Output = {
50
- script: string;
51
- value: string;
52
- address?: string;
53
- };
54
- export type TapTreeLeaf = {
55
- depth: number;
56
- leafVersion: number;
57
- script: string;
58
- };
59
- export type PsbtOutput = {
60
- redeemScript?: string;
61
- witnessScript?: string;
62
- bip32Derivation?: Bip32Derivation[];
63
- tapBip32Derivation?: TapBip32Derivation[];
64
- tapInternalKey?: string;
65
- tapTree?: {
66
- leaves: TapTreeLeaf[];
67
- };
68
- };
69
- export type Fixture = {
70
- walletKeys: [string, string, string];
71
- psbtBase64: string;
72
- psbtBase64Finalized: string | null;
73
- inputs: Input[];
74
- psbtInputs: PsbtInput[];
75
- psbtInputsFinalized: PsbtInput[] | null;
76
- outputs: Output[];
77
- psbtOutputs: PsbtOutput[];
78
- extractedTransaction: string | null;
79
- };
80
- /**
81
- * Get PSBT buffer from a fixture
82
- */
83
- export declare function getPsbtBuffer(fixture: Fixture): Buffer;
84
- /**
85
- * Get BitGoPsbt from a fixture
86
- * @param fixture - The test fixture
87
- * @param networkName - The network name for deserializing the PSBT
88
- * @returns A BitGoPsbt instance
89
- */
90
- export declare function getBitGoPsbt(fixture: Fixture, networkName: NetworkName): BitGoPsbt;
91
- /**
92
- * Load a PSBT fixture from JSON file
93
- */
94
- export declare function loadPsbtFixture(network: string, signatureState: string): Fixture;
95
- /**
96
- * Load wallet keys from fixture
97
- */
98
- export declare function loadWalletKeysFromFixture(fixture: Fixture): RootWalletKeys;
99
- export declare function loadReplayProtectionKeyFromFixture(fixture: Fixture): ECPair;
100
- /**
101
- * Get extracted transaction hex from fixture
102
- */
103
- export declare function getExtractedTransactionHex(fixture: Fixture): string;
@@ -1,65 +0,0 @@
1
- import assert from "node:assert";
2
- import * as fs from "node:fs";
3
- import * as path from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { dirname } from "node:path";
6
- import { BIP32 } from "../../js/bip32.js";
7
- import { RootWalletKeys } from "../../js/fixedScriptWallet/RootWalletKeys.js";
8
- import { ECPair } from "../../js/ecpair.js";
9
- import { fixedScriptWallet } from "../../js/index.js";
10
- const __filename = fileURLToPath(import.meta.url);
11
- const __dirname = dirname(__filename);
12
- /**
13
- * Get PSBT buffer from a fixture
14
- */
15
- export function getPsbtBuffer(fixture) {
16
- return Buffer.from(fixture.psbtBase64, "base64");
17
- }
18
- /**
19
- * Get BitGoPsbt from a fixture
20
- * @param fixture - The test fixture
21
- * @param networkName - The network name for deserializing the PSBT
22
- * @returns A BitGoPsbt instance
23
- */
24
- export function getBitGoPsbt(fixture, networkName) {
25
- return fixedScriptWallet.BitGoPsbt.fromBytes(getPsbtBuffer(fixture), networkName);
26
- }
27
- /**
28
- * Load a PSBT fixture from JSON file
29
- */
30
- export function loadPsbtFixture(network, signatureState) {
31
- const fixturePath = path.join(__dirname, "..", "fixtures", "fixed-script", `psbt-lite.${network}.${signatureState}.json`);
32
- const fixtureContent = fs.readFileSync(fixturePath, "utf-8");
33
- return JSON.parse(fixtureContent);
34
- }
35
- /**
36
- * Load wallet keys from fixture
37
- */
38
- export function loadWalletKeysFromFixture(fixture) {
39
- // Parse xprvs and convert to xpubs
40
- const xpubs = fixture.walletKeys.map((xprv) => {
41
- const key = BIP32.fromBase58(xprv);
42
- return key.neutered();
43
- });
44
- const walletKeysLike = {
45
- triple: xpubs,
46
- derivationPrefixes: ["0/0", "0/0", "0/0"],
47
- };
48
- return RootWalletKeys.from(walletKeysLike);
49
- }
50
- export function loadReplayProtectionKeyFromFixture(fixture) {
51
- // underived user key
52
- const userBip32 = BIP32.fromBase58(fixture.walletKeys[0]);
53
- assert(userBip32.privateKey);
54
- const userECPair = ECPair.fromPrivateKey(Buffer.from(userBip32.privateKey));
55
- return userECPair;
56
- }
57
- /**
58
- * Get extracted transaction hex from fixture
59
- */
60
- export function getExtractedTransactionHex(fixture) {
61
- if (fixture.extractedTransaction === null) {
62
- throw new Error("Fixture does not have an extracted transaction");
63
- }
64
- return fixture.extractedTransaction;
65
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,77 +0,0 @@
1
- import assert from "assert";
2
- import { BIP32 } from "../../js/bip32.js";
3
- import { loadPsbtFixture, getBitGoPsbt } from "./fixtureUtil.js";
4
- describe("MuSig2 nonce management", function () {
5
- describe("Bitcoin mainnet", function () {
6
- const networkName = "bitcoin";
7
- let fixture;
8
- let userKey;
9
- let backupKey;
10
- let bitgoKey;
11
- before(function () {
12
- fixture = loadPsbtFixture(networkName, "unsigned");
13
- userKey = BIP32.fromBase58(fixture.walletKeys[0]);
14
- backupKey = BIP32.fromBase58(fixture.walletKeys[1]);
15
- bitgoKey = BIP32.fromBase58(fixture.walletKeys[2]);
16
- });
17
- it("should generate nonces for MuSig2 inputs with auto-generated session ID", function () {
18
- const unsignedBitgoPsbt = getBitGoPsbt(fixture, networkName);
19
- // Generate nonces with auto-generated session ID (no second parameter)
20
- assert.doesNotThrow(() => {
21
- unsignedBitgoPsbt.generateMusig2Nonces(userKey);
22
- });
23
- // Verify nonces were stored by serializing and deserializing
24
- const serializedWithUserNonces = unsignedBitgoPsbt.serialize();
25
- assert.ok(serializedWithUserNonces.length > getBitGoPsbt(fixture, networkName).serialize().length);
26
- assert.doesNotThrow(() => {
27
- unsignedBitgoPsbt.generateMusig2Nonces(bitgoKey);
28
- });
29
- const serializedWithBitgoNonces = unsignedBitgoPsbt.serialize();
30
- assert.ok(serializedWithBitgoNonces.length > serializedWithUserNonces.length);
31
- assert.throws(() => {
32
- unsignedBitgoPsbt.generateMusig2Nonces(backupKey);
33
- }, "Should throw error when generating nonces for backup key");
34
- });
35
- it("implements combineMusig2Nonces", function () {
36
- const unsignedBitgoPsbtWithUserNonces = getBitGoPsbt(fixture, networkName);
37
- unsignedBitgoPsbtWithUserNonces.generateMusig2Nonces(userKey);
38
- const unsignedBitgoPsbtWithBitgoNonces = getBitGoPsbt(fixture, networkName);
39
- unsignedBitgoPsbtWithBitgoNonces.generateMusig2Nonces(bitgoKey);
40
- const unsignedBitgoPsbtWithBothNonces = getBitGoPsbt(fixture, networkName);
41
- unsignedBitgoPsbtWithBothNonces.combineMusig2Nonces(unsignedBitgoPsbtWithUserNonces);
42
- unsignedBitgoPsbtWithBothNonces.combineMusig2Nonces(unsignedBitgoPsbtWithBitgoNonces);
43
- {
44
- const psbt = getBitGoPsbt(fixture, networkName);
45
- psbt.combineMusig2Nonces(unsignedBitgoPsbtWithUserNonces);
46
- assert.strictEqual(psbt.serialize().length, unsignedBitgoPsbtWithUserNonces.serialize().length);
47
- }
48
- {
49
- const psbt = getBitGoPsbt(fixture, networkName);
50
- psbt.combineMusig2Nonces(unsignedBitgoPsbtWithBitgoNonces);
51
- assert.strictEqual(psbt.serialize().length, unsignedBitgoPsbtWithBitgoNonces.serialize().length);
52
- }
53
- {
54
- const psbt = getBitGoPsbt(fixture, networkName);
55
- psbt.combineMusig2Nonces(unsignedBitgoPsbtWithUserNonces);
56
- psbt.combineMusig2Nonces(unsignedBitgoPsbtWithBitgoNonces);
57
- assert.strictEqual(psbt.serialize().length, unsignedBitgoPsbtWithBothNonces.serialize().length);
58
- }
59
- });
60
- it("should reject invalid session ID length", function () {
61
- const unsignedBitgoPsbt = getBitGoPsbt(fixture, networkName);
62
- // Invalid session ID (wrong length)
63
- const invalidSessionId = new Uint8Array(16); // Should be 32 bytes
64
- assert.throws(() => {
65
- unsignedBitgoPsbt.generateMusig2Nonces(userKey, invalidSessionId);
66
- }, "Should throw error for invalid session ID length");
67
- });
68
- it("should reject custom session ID on mainnet (security)", function () {
69
- const unsignedBitgoPsbt = getBitGoPsbt(fixture, "bitcoin");
70
- // Custom session ID should be rejected on mainnet for security
71
- const customSessionId = new Uint8Array(32).fill(1);
72
- assert.throws(() => {
73
- unsignedBitgoPsbt.generateMusig2Nonces(userKey, customSessionId);
74
- }, /Custom session_id is only allowed on testnets/, "Should throw error when providing custom session_id on mainnet");
75
- });
76
- });
77
- });