Skip to content

Commit 68861ee

Browse files
OttoAllmendingerllm-git
andcommitted
feat(abstract-utxo): replace utxo-lib with wasm-utxo in tests
Port Bitcoin test implementation to use wasm-utxo library instead of utxo-lib. This includes implementing utility functions to create PSBTs and maintaining the same test behavior with the new implementation. Issue: BTC-2650 Co-authored-by: llm-git <llm-git@ttll.de>
1 parent 839372c commit 68861ee

1 file changed

Lines changed: 75 additions & 36 deletions

File tree

  • modules/abstract-utxo/test/unit/impl/btc/unit

modules/abstract-utxo/test/unit/impl/btc/unit/btc.ts

Lines changed: 75 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,45 @@ import assert from 'assert';
33

44
import { type TestBitGoAPI, TestBitGo } from '@bitgo/sdk-test';
55
import { BitGoAPI, encrypt } from '@bitgo/sdk-api';
6-
import * as utxolib from '@bitgo/utxo-lib';
6+
import { fixedScriptWallet, type CoinName } from '@bitgo/wasm-utxo';
7+
import * as testutils from '@bitgo/wasm-utxo/testutils';
78
import { Wallet } from '@bitgo/sdk-core';
89

910
import { Tbtc } from '../../../../../src/impl/btc';
1011

1112
import { btcBackupKey } from './fixtures';
1213

14+
const { BitGoPsbt, ChainCode } = fixedScriptWallet;
15+
16+
type Input = { scriptType: fixedScriptWallet.OutputScriptType; value: bigint };
17+
type Output = { address: string; value: bigint };
18+
type PsbtOptions = { lockTime?: number; sequence?: number };
19+
20+
function constructPsbt(
21+
inputs: Input[],
22+
outputs: Output[],
23+
network: CoinName,
24+
walletKeys: fixedScriptWallet.RootWalletKeys,
25+
options?: PsbtOptions
26+
): fixedScriptWallet.BitGoPsbt {
27+
const psbt = BitGoPsbt.createEmpty(network, walletKeys, { lockTime: options?.lockTime });
28+
29+
inputs.forEach((input, index) => {
30+
const chain = ChainCode.value(input.scriptType, 'external');
31+
psbt.addWalletInput(
32+
{ txid: '00'.repeat(32), vout: index, value: input.value, sequence: options?.sequence },
33+
walletKeys,
34+
{ scriptId: { chain, index }, signPath: { signer: 'user', cosigner: 'bitgo' } }
35+
);
36+
});
37+
38+
outputs.forEach((output) => {
39+
psbt.addOutput(output.address, output.value);
40+
});
41+
42+
return psbt;
43+
}
44+
1345
describe('BTC:', () => {
1446
let bitgo: TestBitGoAPI;
1547

@@ -53,19 +85,30 @@ describe('BTC:', () => {
5385
});
5486

5587
it('should not modify locktime on postProcessPrebuild', async () => {
56-
const txHex =
57-
'0100000001a8ec78f09f7acb0d344622ed3082c1a98e51ba1b1ab65406044f6e0a801609020100000000ffffffff02a0860100000000001976a9149f9a7abd600c0caa03983a77c8c3df8e062cb2fa88acfbf2150000000000220020b922cc1e737e679d24ff2d2b18cfa9fff4e35a733b4fba94282eaa1b7cfe56d200000000';
88+
const walletKeys = testutils.getDefaultWalletKeys();
89+
90+
// Create a PSBT with lockTime=0 and sequence=0xffffffff
91+
const psbt = constructPsbt(
92+
[{ scriptType: 'p2wsh' as const, value: BigInt(100000) }],
93+
[{ address: 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', value: BigInt(90000) }],
94+
'tbtc',
95+
walletKeys,
96+
{ lockTime: 0, sequence: 0xffffffff }
97+
);
98+
99+
const txHex = Buffer.from(psbt.serialize()).toString('hex');
58100
const blockHeight = 100;
59101
const preBuild = { txHex, blockHeight };
60102
const postProcessBuilt = await coin.postProcessPrebuild(preBuild);
61-
const transaction = utxolib.bitgo.createTransactionFromHex(
62-
postProcessBuilt.txHex as string,
63-
utxolib.networks.bitcoin
64-
);
65103

66-
transaction.locktime.should.equal(0);
67-
const inputs = transaction.ins;
68-
for (const input of inputs) {
104+
// Parse result as PSBT
105+
const resultPsbt = BitGoPsbt.fromBytes(Buffer.from(postProcessBuilt.txHex as string, 'hex'), 'tbtc');
106+
107+
resultPsbt.lockTime.should.equal(0);
108+
109+
// Check sequences via parseTransactionWithWalletKeys
110+
const parsed = resultPsbt.parseTransactionWithWalletKeys(walletKeys, { publicKeys: [] });
111+
for (const input of parsed.inputs) {
69112
input.sequence.should.equal(0xffffffff);
70113
}
71114
});
@@ -120,8 +163,8 @@ describe('BTC:', () => {
120163
});
121164

122165
it('should detect hex spoofing in BUILD_SIGN_SEND', async (): Promise<void> => {
123-
const keyTriple = utxolib.testutil.getKeyTriple('default');
124-
const rootWalletKey = new utxolib.bitgo.RootWalletKeys(keyTriple);
166+
const keyTriple = testutils.getKeyTriple('default');
167+
const rootWalletKey = testutils.getDefaultWalletKeys();
125168
const [user] = keyTriple;
126169

127170
const wallet = new Wallet(bitgoTest, coin, {
@@ -130,23 +173,21 @@ describe('BTC:', () => {
130173
keys: ['user', 'backup', 'bitgo'],
131174
});
132175

133-
const originalPsbt = utxolib.testutil.constructPsbt(
176+
// originalPsbt is created to show what the legitimate transaction would look like
177+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
178+
const originalPsbt = constructPsbt(
134179
[{ scriptType: 'p2wsh' as const, value: BigInt(10000) }],
135180
[{ address: 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', value: BigInt(9000) }],
136-
coin.network,
137-
rootWalletKey,
138-
'unsigned' as const
181+
'tbtc',
182+
rootWalletKey
139183
);
140-
utxolib.bitgo.addXpubsToPsbt(originalPsbt, rootWalletKey);
141-
const spoofedPsbt = utxolib.testutil.constructPsbt(
184+
const spoofedPsbt = constructPsbt(
142185
[{ scriptType: 'p2wsh' as const, value: BigInt(10000) }],
143186
[{ address: 'tb1pjgg9ty3s2ztp60v6lhgrw76f7hxydzuk9t9mjsndh3p2gf2ah7gs4850kn', value: BigInt(9000) }],
144-
coin.network,
145-
rootWalletKey,
146-
'unsigned' as const
187+
'tbtc',
188+
rootWalletKey
147189
);
148-
utxolib.bitgo.addXpubsToPsbt(spoofedPsbt, rootWalletKey);
149-
const spoofedHex: string = spoofedPsbt.toHex();
190+
const spoofedHex: string = Buffer.from(spoofedPsbt.serialize()).toString('hex');
150191

151192
const bgUrl: string = (bitgoTest as any)._baseUrl;
152193
const nock = require('nock');
@@ -194,8 +235,8 @@ describe('BTC:', () => {
194235
});
195236

196237
it('should detect hex spoofing in fanout BUILD_SIGN_SEND', async (): Promise<void> => {
197-
const keyTriple = utxolib.testutil.getKeyTriple('default');
198-
const rootWalletKey = new utxolib.bitgo.RootWalletKeys(keyTriple);
238+
const keyTriple = testutils.getKeyTriple('default');
239+
const rootWalletKey = testutils.getDefaultWalletKeys();
199240
const [user] = keyTriple;
200241

201242
const wallet = new Wallet(bitgoTest, coin, {
@@ -204,24 +245,22 @@ describe('BTC:', () => {
204245
keys: ['user', 'backup', 'bitgo'],
205246
});
206247

207-
const originalPsbt = utxolib.testutil.constructPsbt(
248+
// originalPsbt is created to show what the legitimate transaction would look like
249+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
250+
const originalPsbt = constructPsbt(
208251
[{ scriptType: 'p2wsh' as const, value: BigInt(10000) }],
209252
[{ address: 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', value: BigInt(9000) }],
210-
coin.network,
211-
rootWalletKey,
212-
'unsigned' as const
253+
'tbtc',
254+
rootWalletKey
213255
);
214-
utxolib.bitgo.addXpubsToPsbt(originalPsbt, rootWalletKey);
215256

216-
const spoofedPsbt = utxolib.testutil.constructPsbt(
257+
const spoofedPsbt = constructPsbt(
217258
[{ scriptType: 'p2wsh' as const, value: BigInt(10000) }],
218259
[{ address: 'tb1pjgg9ty3s2ztp60v6lhgrw76f7hxydzuk9t9mjsndh3p2gf2ah7gs4850kn', value: BigInt(9000) }],
219-
coin.network,
220-
rootWalletKey,
221-
'unsigned' as const
260+
'tbtc',
261+
rootWalletKey
222262
);
223-
utxolib.bitgo.addXpubsToPsbt(spoofedPsbt, rootWalletKey);
224-
const spoofedHex: string = spoofedPsbt.toHex();
263+
const spoofedHex: string = Buffer.from(spoofedPsbt.serialize()).toString('hex');
225264

226265
const bgUrl: string = (bitgoTest as any)._baseUrl;
227266
const nock = require('nock');

0 commit comments

Comments
 (0)