@@ -3,13 +3,45 @@ import assert from 'assert';
33
44import { type TestBitGoAPI , TestBitGo } from '@bitgo/sdk-test' ;
55import { 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' ;
78import { Wallet } from '@bitgo/sdk-core' ;
89
910import { Tbtc } from '../../../../../src/impl/btc' ;
1011
1112import { 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+
1345describe ( '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