Skip to content

Commit e0058a0

Browse files
OttoAllmendingerllm-git
andcommitted
feat(abstract-utxo): add wasm test cases for parsePsbt
Adds new test cases that use WASM implementation for parsing PSBTs in fixedScript/parsePsbt.ts. The code extracts a utility function into a shared util.ts file and reuses it across test files. Issue: BTC-2732 Co-authored-by: llm-git <[email protected]>
1 parent 7ca4628 commit e0058a0

File tree

3 files changed

+87
-52
lines changed

3 files changed

+87
-52
lines changed

modules/abstract-utxo/test/unit/transaction/fixedScript/explainPsbt.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,7 @@ import { fixedScriptWallet, Triple } from '@bitgo/wasm-utxo';
77
import type { TransactionExplanation } from '../../../../src/transaction/fixedScript/explainTransaction';
88
import { explainPsbt, explainPsbtWasm } from '../../../../src/transaction/fixedScript';
99

10-
function hasWasmUtxoSupport(network: utxolib.Network): boolean {
11-
return ![
12-
utxolib.networks.bitcoincash,
13-
utxolib.networks.bitcoingold,
14-
utxolib.networks.ecash,
15-
utxolib.networks.zcash,
16-
].includes(utxolib.getMainnet(network));
17-
}
10+
import { hasWasmUtxoSupport } from './util';
1811

1912
function describeTransactionWith(acidTest: testutil.AcidTest) {
2013
describe(`${acidTest.name}`, function () {

modules/abstract-utxo/test/unit/transaction/fixedScript/parsePsbt.ts

Lines changed: 76 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,23 @@ import assert from 'node:assert/strict';
22

33
import * as sinon from 'sinon';
44
import * as utxolib from '@bitgo/utxo-lib';
5-
import { Wallet, VerificationOptions, ITransactionRecipient } from '@bitgo/sdk-core';
5+
import { Wallet, VerificationOptions, ITransactionRecipient, Triple } from '@bitgo/sdk-core';
6+
import { fixedScriptWallet } from '@bitgo/wasm-utxo';
67

78
import { parseTransaction } from '../../../../src/transaction/fixedScript/parseTransaction';
89
import { ParsedTransaction } from '../../../../src/transaction/types';
910
import { UtxoWallet } from '../../../../src/wallet';
1011
import { getUtxoCoin } from '../../util';
11-
import { explainLegacyTx, explainPsbt } from '../../../../src/transaction/fixedScript';
12+
import { explainLegacyTx, explainPsbt, explainPsbtWasm } from '../../../../src/transaction/fixedScript';
1213
import type {
1314
TransactionExplanation,
1415
ChangeAddressInfo,
1516
} from '../../../../src/transaction/fixedScript/explainTransaction';
1617
import { getChainFromNetwork } from '../../../../src/names';
1718
import { TransactionPrebuild } from '../../../../src/abstractUtxoCoin';
1819

20+
import { hasWasmUtxoSupport } from './util';
21+
1922
function getTxParamsFromExplanation(
2023
explanation: TransactionExplanation,
2124
{ externalCustomChangeAddress }: { externalCustomChangeAddress: boolean }
@@ -78,6 +81,7 @@ function getChangeInfoFromPsbt(psbt: utxolib.bitgo.UtxoPsbt): ChangeAddressInfo[
7881
function describeParseTransactionWith(
7982
acidTest: utxolib.testutil.AcidTest,
8083
label: string,
84+
backend: 'utxolib' | 'wasm',
8185
{
8286
txParams,
8387
externalCustomChangeAddress = false,
@@ -116,9 +120,27 @@ function describeParseTransactionWith(
116120

117121
let explanation: TransactionExplanation;
118122
if (txFormat === 'psbt') {
119-
explanation = explainPsbt(psbt, { pubs: acidTest.rootWalletKeys }, acidTest.network, {
120-
strict: true,
121-
});
123+
if (backend === 'utxolib') {
124+
explanation = explainPsbt(psbt, { pubs: acidTest.rootWalletKeys }, acidTest.network, {
125+
strict: true,
126+
});
127+
} else if (backend === 'wasm') {
128+
const wasmPsbt = fixedScriptWallet.BitGoPsbt.fromBytes(
129+
psbt.toBuffer(),
130+
utxolib.getNetworkName(acidTest.network)!
131+
);
132+
explanation = explainPsbtWasm(
133+
wasmPsbt,
134+
acidTest.rootWalletKeys.triple.map((k) => k.neutered().toBase58()) as Triple<string>,
135+
{
136+
replayProtection: {
137+
outputScripts: [acidTest.getReplayProtectionOutputScript()],
138+
},
139+
}
140+
);
141+
} else {
142+
throw new Error(`Invalid backend: ${backend}`);
143+
}
122144
} else if (txFormat === 'legacy') {
123145
const pubs = acidTest.rootWalletKeys.triple.map((k) => k.neutered().toBase58());
124146
// Extract change info from PSBT to pass to explainLegacyTx
@@ -240,48 +262,58 @@ function describeParseTransactionWith(
240262
});
241263
}
242264

243-
describe('parseTransaction', function () {
244-
utxolib.testutil.AcidTest.suite().forEach((test) => {
245-
// Default case: psbt format, infer recipients from explanation
246-
describeParseTransactionWith(test, 'default', {
247-
txParams: 'inferFromExplanation',
248-
expectedExplicitExternalSpendAmount: 1800n,
249-
expectedImplicitExternalSpendAmount: 0n,
250-
});
265+
function describeTransaction(
266+
backend: 'utxolib' | 'wasm',
267+
filter: (test: utxolib.testutil.AcidTest) => boolean = () => true
268+
) {
269+
describe(`parseTransaction (${backend})`, function () {
270+
utxolib.testutil.AcidTest.suite()
271+
.filter(filter)
272+
.forEach((test) => {
273+
// Default case: psbt format, infer recipients from explanation
274+
describeParseTransactionWith(test, 'default', backend, {
275+
txParams: 'inferFromExplanation',
276+
expectedExplicitExternalSpendAmount: 1800n,
277+
expectedImplicitExternalSpendAmount: 0n,
278+
});
251279

252-
if (test.network !== utxolib.networks.bitcoin) {
253-
return;
254-
}
255-
// extended test suite for bitcoin
280+
if (test.network !== utxolib.networks.bitcoin) {
281+
return;
282+
}
283+
// extended test suite for bitcoin
256284

257-
describeParseTransactionWith(test, 'legacy', {
258-
txFormat: 'legacy',
259-
txParams: 'inferFromExplanation',
260-
expectedExplicitExternalSpendAmount: 1800n,
261-
expectedImplicitExternalSpendAmount: 0n,
262-
});
285+
describeParseTransactionWith(test, 'legacy', backend, {
286+
txFormat: 'legacy',
287+
txParams: 'inferFromExplanation',
288+
expectedExplicitExternalSpendAmount: 1800n,
289+
expectedImplicitExternalSpendAmount: 0n,
290+
});
263291

264-
describeParseTransactionWith(test, 'empty recipients', {
265-
txParams: {
266-
recipients: [],
267-
},
268-
expectedExplicitExternalSpendAmount: 0n,
269-
expectedImplicitExternalSpendAmount: 1800n,
270-
});
292+
describeParseTransactionWith(test, 'empty recipients', backend, {
293+
txParams: {
294+
recipients: [],
295+
},
296+
expectedExplicitExternalSpendAmount: 0n,
297+
expectedImplicitExternalSpendAmount: 1800n,
298+
});
271299

272-
describeParseTransactionWith(test, 'rbf', {
273-
txParams: {
274-
rbfTxIds: ['PLACEHOLDER'],
275-
},
276-
expectedExplicitExternalSpendAmount: 1800n,
277-
expectedImplicitExternalSpendAmount: 0n,
278-
});
300+
describeParseTransactionWith(test, 'rbf', backend, {
301+
txParams: {
302+
rbfTxIds: ['PLACEHOLDER'],
303+
},
304+
expectedExplicitExternalSpendAmount: 1800n,
305+
expectedImplicitExternalSpendAmount: 0n,
306+
});
279307

280-
describeParseTransactionWith(test, 'allowExternalChangeAddress', {
281-
txParams: 'inferFromExplanation',
282-
externalCustomChangeAddress: true,
283-
expectedExplicitExternalSpendAmount: 1800n,
284-
expectedImplicitExternalSpendAmount: 0n,
285-
});
308+
describeParseTransactionWith(test, 'allowExternalChangeAddress', backend, {
309+
txParams: 'inferFromExplanation',
310+
externalCustomChangeAddress: true,
311+
expectedExplicitExternalSpendAmount: 1800n,
312+
expectedImplicitExternalSpendAmount: 0n,
313+
});
314+
});
286315
});
287-
});
316+
}
317+
318+
describeTransaction('utxolib');
319+
describeTransaction('wasm', (test) => hasWasmUtxoSupport(test.network));
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as utxolib from '@bitgo/utxo-lib';
2+
3+
export function hasWasmUtxoSupport(network: utxolib.Network): boolean {
4+
return ![
5+
utxolib.networks.bitcoincash,
6+
utxolib.networks.bitcoingold,
7+
utxolib.networks.ecash,
8+
utxolib.networks.zcash,
9+
].includes(utxolib.getMainnet(network));
10+
}

0 commit comments

Comments
 (0)