Skip to content

Commit ae4b976

Browse files
Merge pull request #8000 from BitGo/BTC-2980.bump-wasm-utxo
feat(abstract-utxo): update wasm-utxo and optimize tx signing
2 parents 5fed22e + b3626a7 commit ae4b976

8 files changed

Lines changed: 29 additions & 29 deletions

File tree

modules/abstract-utxo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"@bitgo/utxo-core": "^1.31.0",
6969
"@bitgo/utxo-lib": "^11.19.1",
7070
"@bitgo/utxo-ord": "^1.24.1",
71-
"@bitgo/wasm-utxo": "^1.27.0",
71+
"@bitgo/wasm-utxo": "^1.29.0",
7272
"@types/lodash": "^4.14.121",
7373
"@types/superagent": "4.1.15",
7474
"bignumber.js": "^9.0.2",

modules/abstract-utxo/src/transaction/fixedScript/SigningError.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ export class InputSigningError<TNumber extends number | bigint = number> extends
2828
}
2929
}
3030

31+
export class BulkSigningError extends Error {
32+
constructor(public reason: Error | string) {
33+
const reasonMessage = reason instanceof Error ? reason.message : reason;
34+
super(`bulk signing error: ${reasonMessage}`);
35+
}
36+
}
37+
3138
export class TransactionSigningError<TNumber extends number | bigint = number> extends Error {
3239
constructor(signErrors: InputSigningError<TNumber>[], verifyError: InputSigningError<TNumber>[]) {
3340
super(

modules/abstract-utxo/src/transaction/fixedScript/signPsbtWasm.ts

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import assert from 'assert';
33
import { BIP32Interface } from '@bitgo/utxo-lib';
44
import { BIP32, ECPair, fixedScriptWallet } from '@bitgo/wasm-utxo';
55

6-
import { InputSigningError, TransactionSigningError } from './SigningError';
6+
import { BulkSigningError, InputSigningError, TransactionSigningError } from './SigningError';
77
import { Musig2Participant } from './musig2';
88

99
export type ReplayProtectionKeys = {
@@ -29,6 +29,7 @@ function hasKeyPathSpendInput(
2929

3030
/**
3131
* Sign all inputs of a PSBT and verify signatures after signing.
32+
* Uses bulk signing for performance (signs all matching inputs in one pass).
3233
* Collects and logs signing errors and verification errors, throws error in the end if any of them failed.
3334
*/
3435
export function signAndVerifyPsbtWasm(
@@ -38,32 +39,24 @@ export function signAndVerifyPsbtWasm(
3839
replayProtection: ReplayProtectionKeys
3940
): fixedScriptWallet.BitGoPsbt {
4041
const wasmSigner = toWasmBIP32(signerKeychain);
41-
const parsed = tx.parseTransactionWithWalletKeys(rootWalletKeys, replayProtection);
4242

43-
const signErrors: InputSigningError<bigint>[] = [];
43+
// Bulk sign all wallet inputs (ECDSA + MuSig2) - much faster than per-input signing
44+
try {
45+
tx.sign(wasmSigner);
46+
} catch (e) {
47+
throw new BulkSigningError(e);
48+
}
49+
50+
// Verify signatures for all signed inputs (still per-input for granular error reporting)
51+
const parsed = tx.parseTransactionWithWalletKeys(rootWalletKeys, replayProtection);
4452
const verifyErrors: InputSigningError<bigint>[] = [];
4553

46-
// Sign all inputs (skipping replay protection inputs)
4754
parsed.inputs.forEach((input, inputIndex) => {
4855
if (input.scriptType === 'p2shP2pk') {
4956
// Skip replay protection inputs - they are platform signed only
5057
return;
5158
}
5259

53-
const outputId = `${input.previousOutput.txid}:${input.previousOutput.vout}`;
54-
try {
55-
tx.sign(inputIndex, wasmSigner);
56-
} catch (e) {
57-
signErrors.push(new InputSigningError<bigint>(inputIndex, input.scriptType, { id: outputId }, e));
58-
}
59-
});
60-
61-
// Verify signatures for all signed inputs
62-
parsed.inputs.forEach((input, inputIndex) => {
63-
if (input.scriptType === 'p2shP2pk') {
64-
return;
65-
}
66-
6760
const outputId = `${input.previousOutput.txid}:${input.previousOutput.vout}`;
6861
try {
6962
if (!tx.verifySignature(inputIndex, wasmSigner)) {
@@ -76,8 +69,8 @@ export function signAndVerifyPsbtWasm(
7669
}
7770
});
7871

79-
if (signErrors.length || verifyErrors.length) {
80-
throw new TransactionSigningError(signErrors, verifyErrors);
72+
if (verifyErrors.length) {
73+
throw new TransactionSigningError([], verifyErrors);
8174
}
8275

8376
return tx;

modules/utxo-bin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"@bitgo/unspents": "^0.50.14",
3232
"@bitgo/utxo-core": "^1.31.0",
3333
"@bitgo/utxo-lib": "^11.19.1",
34-
"@bitgo/wasm-utxo": "^1.27.0",
34+
"@bitgo/wasm-utxo": "^1.29.0",
3535
"@noble/curves": "1.8.1",
3636
"archy": "^1.0.0",
3737
"bech32": "^2.0.0",

modules/utxo-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
"@bitgo/secp256k1": "^1.9.0",
8282
"@bitgo/unspents": "^0.50.14",
8383
"@bitgo/utxo-lib": "^11.19.1",
84-
"@bitgo/wasm-utxo": "^1.27.0",
84+
"@bitgo/wasm-utxo": "^1.29.0",
8585
"bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4",
8686
"fast-sha256": "^1.3.0"
8787
},

modules/utxo-ord/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"directory": "modules/utxo-ord"
4646
},
4747
"dependencies": {
48-
"@bitgo/wasm-utxo": "^1.27.0"
48+
"@bitgo/wasm-utxo": "^1.29.0"
4949
},
5050
"devDependencies": {
5151
"@bitgo/utxo-lib": "^11.19.1"

modules/utxo-staking/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"@bitgo/babylonlabs-io-btc-staking-ts": "^3.3.0",
6464
"@bitgo/utxo-core": "^1.31.0",
6565
"@bitgo/utxo-lib": "^11.19.1",
66-
"@bitgo/wasm-utxo": "^1.27.0",
66+
"@bitgo/wasm-utxo": "^1.29.0",
6767
"bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4",
6868
"bip322-js": "^2.0.0",
6969
"bitcoinjs-lib": "^6.1.7",

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -996,10 +996,10 @@
996996
monocle-ts "^2.3.13"
997997
newtype-ts "^0.3.5"
998998

999-
"@bitgo/wasm-utxo@^1.27.0":
1000-
version "1.27.0"
1001-
resolved "https://registry.npmjs.org/@bitgo/wasm-utxo/-/wasm-utxo-1.27.0.tgz#c8ebe108ce8b55d3df70cd3968211a6ef3001bef"
1002-
integrity sha512-gX0YemHbSBOKQ/nKaBsZKI3cJzgkrLXFWuMsPJ7t2oDzE3ggfgVF3ulGFsuaQ8WQT4rOsZ7FZz2f+C9mStXAeA==
999+
"@bitgo/wasm-utxo@^1.29.0":
1000+
version "1.29.0"
1001+
resolved "https://registry.npmjs.org/@bitgo/wasm-utxo/-/wasm-utxo-1.29.0.tgz#75be3668bd972a3ff9aae07aed84916bfceb870d"
1002+
integrity sha512-eWYM7/me8bg+oqw6lEVMdmR1eUVuGzOoyKgSm1QAZUe41qR8IjMyyWjtWI1s5XExfAOXnZuSss/8QJEPOjXhzg==
10031003

10041004
"@brandonblack/musig@^0.0.1-alpha.0":
10051005
version "0.0.1-alpha.1"

0 commit comments

Comments
 (0)