Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/abstract-utxo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"@bitgo/utxo-core": "^1.32.0",
"@bitgo/utxo-lib": "^11.20.0",
"@bitgo/utxo-ord": "^1.25.0",
"@bitgo/wasm-utxo": "^1.32.0",
"@bitgo/wasm-utxo": "^1.34.0",
"@types/lodash": "^4.14.121",
"@types/superagent": "4.1.15",
"bignumber.js": "^9.0.2",
Expand Down
64 changes: 64 additions & 0 deletions modules/abstract-utxo/test/unit/bip322.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import assert from 'assert';

import * as utxolib from '@bitgo/utxo-lib';
import { bip322 as coreBip322 } from '@bitgo/utxo-core';
import { bip322 as wasmBip322, fixedScriptWallet, BIP32, type Triple } from '@bitgo/wasm-utxo';

import {
Expand Down Expand Up @@ -401,4 +402,67 @@ describe('BIP322', function () {
);
});
});

describe('utxolib verification stack - wasm-utxo respects input.sighashType', function () {
// This test verifies that wasm-utxo correctly respects the input.sighashType field
// when creating musig2 partial signatures.
//
// Previously (before fix), wasm-utxo would always create signatures with SIGHASH_DEFAULT (0)
// regardless of the input.sighashType field, causing validation to fail.
//
// Now (after fix), wasm-utxo reads input.sighashType and creates signatures with the
// correct sighash type, allowing validation to succeed.

it('should validate signatures when wasm-utxo respects input.sighashType', function () {
const seed = 'p2trMusig2_sighash_test';
const { xprivs } = createTestWalletKeys(seed);

// Create utxolib RootWalletKeys for utxo-core PSBT construction
const utxolibRootWalletKeys = new utxolib.bitgo.RootWalletKeys(utxolib.testutil.getKeyTriple(seed));

// p2trMusig2 external chain code
const chain = utxolib.bitgo.getExternalChainCode('p2trMusig2');
const index = 0;
const messageText = 'BIP322 sighash test';

// Create BIP322 PSBT using utxo-core
const psbt = coreBip322.createBaseToSignPsbt(utxolibRootWalletKeys, utxolib.networks.bitcoin);
coreBip322.addBip322InputWithChainAndIndex(psbt, messageText, utxolibRootWalletKeys, { chain, index });

// Note: utxo-core sets sighashType: Transaction.SIGHASH_ALL (1) for BIP322 inputs
const SIGHASH_ALL = 1;
assert.strictEqual(psbt.data.inputs[0].sighashType, SIGHASH_ALL);

// Convert to wasm-utxo PSBT for cosigning
const wasmPsbt = fixedScriptWallet.BitGoPsbt.fromBytes(psbt.toBuffer(), 'btc');

// Generate musig2 nonces and sign with wasm-utxo
// wasm-utxo now respects input.sighashType and creates signatures with SIGHASH_ALL
const userKey = BIP32.fromBase58(xprivs[0]);
const bitgoKey = BIP32.fromBase58(xprivs[2]);

wasmPsbt.generateMusig2Nonces(userKey);
wasmPsbt.generateMusig2Nonces(bitgoKey);
wasmPsbt.sign(0, userKey);
wasmPsbt.sign(0, bitgoKey);

// Convert back to utxolib PSBT for validation
const signedPsbt = utxolib.bitgo.createPsbtFromBuffer(
Buffer.from(wasmPsbt.serialize()),
utxolib.networks.bitcoin
);

// Validation should succeed because wasm-utxo now creates signatures
// with the correct sighash type (SIGHASH_ALL) matching input.sighashType
const validationResult = utxolib.bitgo.getSignatureValidationArrayPsbt(signedPsbt, utxolibRootWalletKeys);

// Verify that both user (index 0) and bitgo (index 2) signatures are valid
assert.strictEqual(validationResult.length, 1);
const [inputIndex, sigValidation] = validationResult[0];
assert.strictEqual(inputIndex, 0);
assert.strictEqual(sigValidation[0], true, 'user signature should be valid');
assert.strictEqual(sigValidation[1], false, 'backup signature should not be present');
assert.strictEqual(sigValidation[2], true, 'bitgo signature should be valid');
});
});
});
2 changes: 1 addition & 1 deletion modules/utxo-bin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@bitgo/unspents": "^0.51.0",
"@bitgo/utxo-core": "^1.32.0",
"@bitgo/utxo-lib": "^11.20.0",
"@bitgo/wasm-utxo": "^1.32.0",
"@bitgo/wasm-utxo": "^1.34.0",
"@noble/curves": "1.8.1",
"archy": "^1.0.0",
"bech32": "^2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion modules/utxo-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"@bitgo/secp256k1": "^1.10.0",
"@bitgo/unspents": "^0.51.0",
"@bitgo/utxo-lib": "^11.20.0",
"@bitgo/wasm-utxo": "^1.32.0",
"@bitgo/wasm-utxo": "^1.34.0",
"bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4",
"fast-sha256": "^1.3.0"
},
Expand Down
2 changes: 1 addition & 1 deletion modules/utxo-ord/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"directory": "modules/utxo-ord"
},
"dependencies": {
"@bitgo/wasm-utxo": "^1.32.0"
"@bitgo/wasm-utxo": "^1.34.0"
},
"devDependencies": {
"@bitgo/utxo-lib": "^11.20.0"
Expand Down
2 changes: 1 addition & 1 deletion modules/utxo-staking/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@bitgo/babylonlabs-io-btc-staking-ts": "^3.4.0",
"@bitgo/utxo-core": "^1.32.0",
"@bitgo/utxo-lib": "^11.20.0",
"@bitgo/wasm-utxo": "^1.32.0",
"@bitgo/wasm-utxo": "^1.34.0",
"bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4",
"bip322-js": "^2.0.0",
"bitcoinjs-lib": "^6.1.7",
Expand Down
16 changes: 8 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -996,10 +996,10 @@
monocle-ts "^2.3.13"
newtype-ts "^0.3.5"

"@bitgo/wasm-utxo@^1.32.0":
version "1.32.0"
resolved "https://registry.npmjs.org/@bitgo/wasm-utxo/-/wasm-utxo-1.32.0.tgz#fc7e7803eb584ba8ad16aeb0a2805d6905d287d3"
integrity sha512-fqUGh8XOrzbPcTxK3lhS9UjqKxx3UaN6L+eS3vocBeWHbQvl6jm9xPPQ+TDkeiUuZdxaj0+7ca4Algt9vyiXHg==
"@bitgo/wasm-utxo@^1.34.0":
version "1.34.0"
resolved "https://registry.npmjs.org/@bitgo/wasm-utxo/-/wasm-utxo-1.34.0.tgz#318bcc0a20acc3f35b9547548ea36506beaab237"
integrity sha512-aJuLQ8fNAWmI213sIwMt9WJfWvsyVAmmyUWnojUdmK2iHwf6tIo4B9gWHoPuWwNYoqc/UJVbK3dDKxnMIUk/bg==

"@brandonblack/musig@^0.0.1-alpha.0":
version "0.0.1-alpha.1"
Expand Down Expand Up @@ -3080,10 +3080,10 @@
resolved "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz"
integrity sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==

"@isaacs/brace-expansion@^5.0.0":
version "5.0.0"
resolved "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz"
integrity sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==
"@isaacs/brace-expansion@5.0.1", "@isaacs/brace-expansion@^5.0.0":
version "5.0.1"
resolved "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz#0ef5a92d91f2fff2a37646ce54da9e5f599f6eff"
integrity sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==
dependencies:
"@isaacs/balanced-match" "^4.0.1"

Expand Down