1
- use bitcoind:: bitcoincore_rpc:: RpcApi ;
1
+ use bitcoin:: hashes:: { sha256, Hash } ;
2
+ use bitcoind:: bitcoincore_rpc:: { self , RpcApi } ;
2
3
use serde_json:: Value ;
3
4
use std:: collections:: HashSet ;
4
5
@@ -24,23 +25,8 @@ fn test_rest() -> Result<()> {
24
25
. into_string ( ) ?)
25
26
} ;
26
27
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
-
42
28
// Send transaction and confirm it
43
- let addr1 = newaddress ( ) ?;
29
+ let addr1 = newaddress ( tester . node_client ( ) ) ?;
44
30
let txid1_confirmed = tester. send ( & addr1, "1.19123 BTC" . parse ( ) . unwrap ( ) ) ?;
45
31
tester. mine ( ) ?;
46
32
@@ -183,6 +169,171 @@ fn test_rest() -> Result<()> {
183
169
tester. mine ( ) ?;
184
170
assert_eq ! ( get_json( "/mempool" ) ?[ "count" ] . as_u64( ) , Some ( 0 ) ) ;
185
171
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
+
186
318
rest_handle. stop ( ) ;
187
319
Ok ( ( ) )
188
320
}
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