1- use bitcoind:: bitcoincore_rpc:: RpcApi ;
1+ use bitcoin:: hashes:: { sha256, Hash } ;
2+ use bitcoind:: bitcoincore_rpc:: { self , RpcApi } ;
23use serde_json:: Value ;
34use std:: collections:: HashSet ;
45
@@ -24,23 +25,8 @@ fn test_rest() -> Result<()> {
2425 . into_string ( ) ?)
2526 } ;
2627
27- let newaddress = || -> Result < Address > {
28- let addr = tester. node_client ( ) . call :: < Address > ( "getnewaddress" , & [ ] ) ?;
29- // On Liquid, return the unconfidential address, so that the tests below work
30- // on both Bitcoin and Liquid mode. The Liquid-specific functionality, including
31- // confidentially, is tested separately below.
32- #[ cfg( feature = "liquid" ) ]
33- let addr = {
34- let mut info = tester
35- . node_client ( )
36- . call :: < Value > ( "getaddressinfo" , & [ addr. to_string ( ) . into ( ) ] ) ?;
37- serde_json:: from_value ( info[ "unconfidential" ] . take ( ) ) ?
38- } ;
39- Ok ( addr)
40- } ;
41-
4228 // Send transaction and confirm it
43- let addr1 = newaddress ( ) ?;
29+ let addr1 = newaddress ( tester . node_client ( ) ) ?;
4430 let txid1_confirmed = tester. send ( & addr1, "1.19123 BTC" . parse ( ) . unwrap ( ) ) ?;
4531 tester. mine ( ) ?;
4632
@@ -183,6 +169,171 @@ fn test_rest() -> Result<()> {
183169 tester. mine ( ) ?;
184170 assert_eq ! ( get_json( "/mempool" ) ?[ "count" ] . as_u64( ) , Some ( 0 ) ) ;
185171
172+ // Elements-only tests
173+ #[ cfg( feature = "liquid" ) ]
174+ {
175+ // Test confidential transactions
176+ {
177+ let ( c_addr, uc_addr) = elements_newaddress ( tester. node_client ( ) ) ?;
178+ let txid = tester. send ( & c_addr, "3.5 BTC" . parse ( ) . unwrap ( ) ) ?;
179+ tester. mine ( ) ?;
180+
181+ let tx = get_json ( & format ! ( "/tx/{}" , txid) ) ?;
182+ log:: debug!( "blinded tx = {:#?}" , tx) ;
183+ assert_eq ! ( tx[ "status" ] [ "confirmed" ] . as_bool( ) , Some ( true ) ) ;
184+ let outs = tx[ "vout" ] . as_array ( ) . expect ( "array of outs" ) ;
185+ let vout = outs
186+ . iter ( )
187+ . find ( |vout| vout[ "scriptpubkey_address" ] . as_str ( ) == Some ( & uc_addr. to_string ( ) ) )
188+ . expect ( "our output" ) ;
189+ assert ! ( vout[ "value" ] . is_null( ) ) ;
190+ assert ! ( vout[ "valuecommitment" ] . is_string( ) ) ;
191+ assert ! ( vout[ "assetcommitment" ] . is_string( ) ) ;
192+ }
193+
194+ // Test blinded asset issuance
195+ {
196+ let contract_hash = sha256:: Hash :: hash ( & [ 0x11 , 0x22 , 0x33 , 0x44 ] ) . to_string ( ) ;
197+ let contract_hash = contract_hash. as_str ( ) ;
198+ let issuance = tester. node_client ( ) . call :: < Value > (
199+ "issueasset" ,
200+ & [ 1.5 . into ( ) , 0 . into ( ) , true . into ( ) , contract_hash. into ( ) ] ,
201+ ) ?;
202+ tester. mine ( ) ?;
203+
204+ let assetid = issuance[ "asset" ] . as_str ( ) . expect ( "asset id" ) ;
205+ let issuance_txid = issuance[ "txid" ] . as_str ( ) . expect ( "issuance txid" ) ;
206+
207+ // Test GET /tx/:txid for issuance tx
208+ let asset = get_json ( & format ! ( "/asset/{}" , assetid) ) ?;
209+ let stats = & asset[ "chain_stats" ] ;
210+ assert_eq ! ( asset[ "asset_id" ] . as_str( ) , Some ( assetid) ) ;
211+ assert_eq ! ( asset[ "issuance_txin" ] [ "txid" ] . as_str( ) , Some ( issuance_txid) ) ;
212+ assert_eq ! ( asset[ "contract_hash" ] . as_str( ) , Some ( contract_hash) ) ;
213+ assert_eq ! ( asset[ "status" ] [ "confirmed" ] . as_bool( ) , Some ( true ) ) ;
214+ assert_eq ! ( stats[ "issuance_count" ] . as_u64( ) , Some ( 1 ) ) ;
215+ assert_eq ! ( stats[ "has_blinded_issuances" ] . as_bool( ) , Some ( true ) ) ;
216+ assert_eq ! ( stats[ "issued_amount" ] . as_u64( ) , Some ( 0 ) ) ;
217+
218+ // Test GET /asset/:assetid
219+ let issuance_tx = get_json ( & format ! ( "/tx/{}" , issuance_txid) ) ?;
220+ let issuance_in_index = asset[ "issuance_txin" ] [ "vin" ] . as_u64 ( ) . unwrap ( ) ;
221+ let issuance_in = & issuance_tx[ "vin" ] [ issuance_in_index as usize ] ;
222+ let issuance_data = & issuance_in[ "issuance" ] ;
223+ assert_eq ! ( issuance_data[ "asset_id" ] . as_str( ) , Some ( assetid) ) ;
224+ assert_eq ! ( issuance_data[ "is_reissuance" ] . as_bool( ) , Some ( false ) ) ;
225+ assert_eq ! ( issuance_data[ "contract_hash" ] . as_str( ) , Some ( contract_hash) ) ;
226+ assert ! ( issuance_data[ "assetamount" ] . is_null( ) ) ;
227+ assert ! ( issuance_data[ "assetamountcommitment" ] . is_string( ) ) ;
228+ }
229+
230+ // Test unblinded asset issuance
231+ {
232+ let issuance = tester
233+ . node_client ( )
234+ . call :: < Value > ( "issueasset" , & [ 1.5 . into ( ) , 0 . into ( ) , false . into ( ) ] ) ?;
235+ tester. mine ( ) ?;
236+ let assetid = issuance[ "asset" ] . as_str ( ) . expect ( "asset id" ) ;
237+ let issuance_txid = issuance[ "txid" ] . as_str ( ) . expect ( "issuance txid" ) ;
238+
239+ // Test GET /tx/:txid for issuance tx
240+ let asset = get_json ( & format ! ( "/asset/{}" , assetid) ) ?;
241+ let stats = & asset[ "chain_stats" ] ;
242+ assert_eq ! ( stats[ "has_blinded_issuances" ] . as_bool( ) , Some ( false ) ) ;
243+ assert_eq ! ( stats[ "issued_amount" ] . as_u64( ) , Some ( 150000000 ) ) ;
244+
245+ // Test GET /asset/:assetid
246+ let issuance_tx = get_json ( & format ! ( "/tx/{}" , issuance_txid) ) ?;
247+ let issuance_in_index = asset[ "issuance_txin" ] [ "vin" ] . as_u64 ( ) . unwrap ( ) ;
248+ let issuance_in = & issuance_tx[ "vin" ] [ issuance_in_index as usize ] ;
249+ let issuance_data = & issuance_in[ "issuance" ] ;
250+ assert_eq ! ( issuance_data[ "assetamount" ] . as_u64( ) , Some ( 150000000 ) ) ;
251+ assert ! ( issuance_data[ "assetamountcommitment" ] . is_null( ) ) ;
252+ }
253+
254+ // Test a regular (non-issuance) transaction sending an issued asset
255+ {
256+ let issuance = tester
257+ . node_client ( )
258+ . call :: < Value > ( "issueasset" , & [ 1.5 . into ( ) , 0 . into ( ) , false . into ( ) ] ) ?;
259+ let assetid = issuance[ "asset" ] . as_str ( ) . expect ( "asset id" ) ;
260+ tester. mine ( ) ?;
261+
262+ let ( c_addr, uc_addr) = elements_newaddress ( tester. node_client ( ) ) ?;
263+
264+ // With blinding off
265+ let txid = tester. send_asset (
266+ & uc_addr,
267+ "0.3 BTC" . parse ( ) . unwrap ( ) , // not actually BTC, but this is what Amount expects
268+ assetid. parse ( ) . unwrap ( ) ,
269+ ) ?;
270+ let tx = get_json ( & format ! ( "/tx/{}" , txid) ) ?;
271+ let outs = tx[ "vout" ] . as_array ( ) . expect ( "array of outs" ) ;
272+ let vout = outs
273+ . iter ( )
274+ . find ( |vout| vout[ "scriptpubkey_address" ] . as_str ( ) == Some ( & uc_addr. to_string ( ) ) )
275+ . expect ( "our output" ) ;
276+ assert_eq ! ( vout[ "asset" ] . as_str( ) , Some ( assetid) ) ;
277+ assert_eq ! ( vout[ "value" ] . as_u64( ) , Some ( 30000000 ) ) ;
278+
279+ // With blinding on
280+ let txid = tester. send_asset (
281+ & c_addr,
282+ "0.3 BTC" . parse ( ) . unwrap ( ) ,
283+ assetid. parse ( ) . unwrap ( ) ,
284+ ) ?;
285+ let tx = get_json ( & format ! ( "/tx/{}" , txid) ) ?;
286+ let outs = tx[ "vout" ] . as_array ( ) . expect ( "array of outs" ) ;
287+ let vout = outs
288+ . iter ( )
289+ . find ( |vout| vout[ "scriptpubkey_address" ] . as_str ( ) == Some ( & uc_addr. to_string ( ) ) )
290+ . expect ( "our output" ) ;
291+ assert ! ( vout[ "asset" ] . is_null( ) ) ;
292+ assert ! ( vout[ "value" ] . is_null( ) ) ;
293+ assert ! ( vout[ "assetcommitment" ] . is_string( ) ) ;
294+ assert ! ( vout[ "valuecommitment" ] . is_string( ) ) ;
295+ }
296+
297+ // Test GET /block/:hash
298+ {
299+ let bestblockhash = get_plain ( "/blocks/tip/hash" ) ?;
300+ let block = get_json ( & format ! ( "/block/{}" , bestblockhash) ) ?;
301+
302+ // No PoW-related stuff
303+ assert ! ( block[ "bits" ] . is_null( ) ) ;
304+ assert ! ( block[ "nonce" ] . is_null( ) ) ;
305+ assert ! ( block[ "difficulty" ] . is_null( ) ) ;
306+
307+ // Dynamic Federations (dynafed) fields
308+ assert ! ( block[ "ext" ] [ "current" ] [ "signblockscript" ] . is_string( ) ) ;
309+ assert ! ( block[ "ext" ] [ "current" ] [ "fedpegscript" ] . is_string( ) ) ;
310+ assert ! ( block[ "ext" ] [ "current" ] [ "fedpeg_program" ] . is_string( ) ) ;
311+ assert ! ( block[ "ext" ] [ "current" ] [ "signblock_witness_limit" ] . is_u64( ) ) ;
312+ assert ! ( block[ "ext" ] [ "current" ] [ "extension_space" ] . is_array( ) ) ;
313+ assert ! ( block[ "ext" ] [ "proposed" ] . is_object( ) ) ;
314+ assert ! ( block[ "ext" ] [ "signblock_witness" ] . is_array( ) ) ;
315+ }
316+ }
317+
186318 rest_handle. stop ( ) ;
187319 Ok ( ( ) )
188320}
321+
322+ fn newaddress ( client : & bitcoincore_rpc:: Client ) -> Result < Address > {
323+ #[ cfg( not( feature = "liquid" ) ) ]
324+ return Ok ( client. get_new_address ( None , None ) ?) ;
325+
326+ // Return the unconfidential address on Liquid, so that the tests below work
327+ // on both Bitcoin and Liquid mode. The Liquid-specific functionality, including
328+ // confidentially, is tested separately below.
329+ #[ cfg( feature = "liquid" ) ]
330+ return Ok ( elements_newaddress ( client) ?. 1 ) ;
331+ }
332+
333+ #[ cfg( feature = "liquid" ) ]
334+ fn elements_newaddress ( client : & bitcoincore_rpc:: Client ) -> Result < ( Address , Address ) > {
335+ let c_addr = client. call :: < Address > ( "getnewaddress" , & [ ] ) ?;
336+ let mut info = client. call :: < Value > ( "getaddressinfo" , & [ c_addr. to_string ( ) . into ( ) ] ) ?;
337+ let uc_addr = serde_json:: from_value ( info[ "unconfidential" ] . take ( ) ) ?;
338+ Ok ( ( c_addr, uc_addr) )
339+ }
0 commit comments