@@ -53,19 +53,19 @@ export function TestOnLocalnet () {
5353 // Empty program, always passes:
5454 TestProgram ( "unit program" , 'fn main () {}' , {
5555 p2tr : 'ert1p9jcvyzkdwdqtf49kta4xpc5g35xkfcexwfsl8v70w2gwttelncyspjlnrz' ,
56- cmr : 'c40a10263f7436b4160acbef1c36fba4be4d95df181a968afeab5eac247adff7' ,
57- fee : 2.7e-7 } ) ,
56+ fee : 2.7e-7
57+ } ) ,
5858 // Correct assertion, always passes:
5959 TestProgram ( "assert true" , 'fn main () { assert!(true) }' , {
6060 p2tr : 'ert1per0vg2wvc4ua2rsndm8j6062r7z7ys7q6wcvwumepgz8t5m6hfhsrd8d8q' ,
61- cmr : '633f62f67589423aafcd3ce0a4dc41f6192403c4aeb61997f438dbd7b96c5cf7' ,
62- fee : 2.7e-7 } ) ,
61+ fee : 2.7e-7
62+ } ) ,
6363 // Incorrect assertion, always fails:
6464 TestProgram ( "assert false fails" , 'fn main () { assert!(false) }' , {
6565 shouldFail : true ,
6666 p2tr : 'ert1p7p4rgaw5dmhxt6qutf2v3rtuy6afghfgktmmedkpju5uamxdz5js3hdug9' ,
67- cmr : 'd3c6b9ecfc2876ec72f0099c6f454b7b34645d08c1f220c05ae80e77eed4bdf3' ,
68- fee : 2.7e-7 } ) ,
67+ fee : 2.7e-7
68+ } ) ,
6969 // Test basic language features. Guards against general failure of all jets
7070 // (Symptom of mislinked WASM, see other mentions in README and/or comments.)
7171 TestProgram ( "basic jets work" , `fn main () {
@@ -75,14 +75,12 @@ export function TestOnLocalnet () {
7575 assert!(jet::eq_8(ab, 0b10111101));
7676 }` , {
7777 p2tr : 'ert1pmy9edmq0yfrc477jvcc835umyajlgjsnyujplt8nppr45zrwl7qs02gj3x' ,
78- cmr : 'b8b3509f12177723609e3995101ff589e504361ce32ec4d417bba3b37bbb7fac' ,
7978 fee : 2.7e-7 , } ) ,
8079 // Witness signing:
8180 TestProgram ( "pay to pubkey" , `fn main () {
8281 jet::bip_0340_verify((param::PK, jet::sig_all_hash()), witness::SIG)
8382 }` , {
8483 p2tr : 'ert1pa69jdawgz5wu5uc8ce2cv7lcqf64kadyl4wsrddparl25erfj2vq9824m9' ,
85- cmr : 'b1b4447ce3082324635798876f1ae6c9aec9a228eb6e21e3cb991f8970986965' ,
8684 argTypes : { PK : "u256" } ,
8785 witTypes : { SIG : "[u8; 64]" } ,
8886 provideArgs : ( ) => ( {
@@ -106,8 +104,7 @@ export function TestOnTestnet () {
106104 TestSend ( ) , // Test the basic transaction primitive
107105 Test ( 'Programs' ,
108106 TestProgram ( "unit program" , 'fn main () {}' , {
109- p2tr : 'ert1p9jcvyzkdwdqtf49kta4xpc5g35xkfcexwfsl8v70w2gwttelncyspjlnrz' ,
110- cmr : 'c40a10263f7436b4160acbef1c36fba4be4d95df181a968afeab5eac247adff7' ,
107+ p2tr : 'tex1p9jcvyzkdwdqtf49kta4xpc5g35xkfcexwfsl8v70w2gwttelncyshxjk56' ,
111108 fee : 2.7e-7 } ) ) ,
112109 ) ;
113110}
@@ -122,7 +119,9 @@ function TestProgram (name: string, src: string, {
122119 cmr = null as null | string ,
123120 /** Expected pay-to-taproot address of program. */
124121 p2tr = null as null | string ,
122+ /** Expected compile-time signature of program. */
125123 argTypes = { } as Record < string , string > ,
124+ /** Expected runtime signature of program. */
126125 witTypes = { } as Record < string , string > ,
127126 /** Function that provides parameter data. */
128127 provideArgs = null as null | Fn . Returns < Async < SimplicityHL . Args > > ,
@@ -136,7 +135,7 @@ function TestProgram (name: string, src: string, {
136135
137136 // Test the SimplicityHL program specified above on the given chain.
138137 async function testProgram ( chain : Btc ) {
139-
138+ const debug = ( chain . debug ?? console . debug ) || ( ( ) => { } ) ;
140139 // Compile this program with these arguments for this chain.
141140 const program = await SimplicityHL . Program ( src , {
142141 // Expected program address, optional. Makes it safer.
@@ -155,35 +154,52 @@ function TestProgram (name: string, src: string, {
155154 // Check against expected program address, if provided.
156155 if ( p2tr ) equal ( program . p2tr , p2tr ) ;
157156
158- // Fund program from deployer:
159- const commitSource = await chain . getUtxo ( chain . P2WPKH ( keypair1 . publicKey ( ) ) . address ) ;
160- const commitAmount = BigInt ( Math . floor ( commitSource . amount / 100 ) * 1e8 ) - BigInt ( fee * 1e8 ) ;
157+ // UTXO helpers. TODO move to Bitcoin lib.
158+ const toUtxo = ( x : Btc . Utxo ) : Btc . Utxo & { amount : bigint } => Object . assign ( x , {
159+ amount : toSat ( x . amount )
160+ } ) ;
161+
162+ const toSat = ( x : unknown ) : bigint => {
163+ if ( typeof x === 'bigint' ) return x ;
164+ if ( typeof x === 'number' ) return BigInt ( Math . round ( x * 1e8 ) ) ;
165+ throw new Error ( `expected BigInt(100000001)sat or Number(1.00000001)btc, got: ${ x } ` ) ;
166+ } ;
161167
162- const commitTxid = await SimplicityHL . Spend ( ) // TODO wrap as program.commit() ?
168+ // Fund program from deployer:
169+ const commitSource = toUtxo ( await chain . getUtxo ( chain . P2WPKH ( keypair1 . publicKey ( ) ) . address ) ) ;
170+ const commitFee = toSat ( fee ?? 1e-4 ) ;
171+ const commitAmount = ( toSat ( commitSource . amount ) / 10n ) - commitFee ;
172+ const commitTxid = await SimplicityHL . Spend ( ) // TODO wrap as program.commit() ?
163173 . asset ( commitSource . asset )
164174 . input ( commitSource , keypair1 )
165175 . output ( program . p2tr , commitAmount )
166- . fee ( fee )
176+ . fee ( commitFee )
167177 . broadcast ( chain ) ;
178+ debug ( 'Commit TX:' , commitTxid ) ;
168179
169180 // Note current recipient balance:
170181 const recipient = chain . P2WPKH ( keypair1 . publicKey ( ) ) . address ;
171182 const recipientBalance = async ( asset = 'bitcoin' ) =>
172- BigInt ( Math . round ( ( await chain . getBalance ( recipient , 0 ) ) [ asset ] * 1e8 ) ) ;
183+ toSat ( ( await chain . getBalance ( recipient , 0 ) ) [ asset ] ?? 0 ) ;
173184 const balance = await recipientBalance ( ) ;
174185
175186 // Find commit (deploy) output = redeem (spend) input:
187+ // This is a tad different across RPC vs Esplora, TODO move to lib too:
176188 const asset = commitSource . asset ;
177189 const prev = await chain . getTxInfo ( commitTxid ) ;
178190 const txid = prev . txid ;
179- const vout = prev . vout . filter ( x => x . scriptPubKey . address === p2tr ) [ 0 ] ;
191+ debug ( 'Redeem from:' , prev ) ;
192+ const toSPKA = ( x : Btc . Utxo ) => x . scriptpubkey_address || x . scriptPubKey ?. address ;
193+ const finder = ( x : Btc . Utxo ) => toSPKA ( x ) === p2tr ;
194+ const vout = prev . vout . find ( finder ) ;
180195 if ( ! vout ) throw new Error ( 'no corresponding vout found' ) ;
181- const utxos = [ { txid, asset, vout : vout . n , address : vout . scriptPubKey . address , amount : vout . value } ] ;
196+ const redeemSource = toUtxo ( { txid, asset, vout : vout . n , address : toSPKA ( vout ) , amount : vout . value } ) ;
197+ debug ( 'Redeem UTXO:' , redeemSource ) ;
182198
183199 // To get SIGHASH_ALL for signing, first the rest of the transaction must be specified:
184- const redeemFee = 1e-4 ;
185- const redeemAmount = commitAmount - BigInt ( redeemFee * 1e8 ) ;
186- const sighashOpts = { asset, utxos, recipient, amount : redeemAmount , fee : redeemFee } ;
200+ const redeemFee = 10000n ;
201+ const redeemAmount = commitAmount - 10000n ;
202+ const sighashOpts = { asset, utxos : [ redeemSource ] , recipient, amount : redeemAmount , fee : redeemFee } ;
187203 const sighash = program . redeemSighash ( sighashOpts ) ;
188204 ok ( sighash instanceof Uint8Array , 'sighash expected to be returned from WASM as Uint8Array' )
189205 ok ( Base16 . encode ( sighash ) , 'sighash expected to be base16-encodable' ) ;
0 commit comments