@@ -189,7 +189,7 @@ impl Connection {
189
189
. chain_err ( || "discovery is disabled" ) ?;
190
190
191
191
let features = params
192
- . get ( 0 )
192
+ . first ( )
193
193
. chain_err ( || "missing features param" ) ?
194
194
. clone ( ) ;
195
195
let features = serde_json:: from_value ( features) . chain_err ( || "invalid features" ) ?;
@@ -203,7 +203,7 @@ impl Connection {
203
203
}
204
204
205
205
fn blockchain_block_header ( & self , params : & [ Value ] ) -> Result < Value > {
206
- let height = usize_from_value ( params. get ( 0 ) , "height" ) ?;
206
+ let height = usize_from_value ( params. first ( ) , "height" ) ?;
207
207
let cp_height = usize_from_value_or ( params. get ( 1 ) , "cp_height" , 0 ) ?;
208
208
209
209
let raw_header_hex: String = self
@@ -226,7 +226,7 @@ impl Connection {
226
226
}
227
227
228
228
fn blockchain_block_headers ( & self , params : & [ Value ] ) -> Result < Value > {
229
- let start_height = usize_from_value ( params. get ( 0 ) , "start_height" ) ?;
229
+ let start_height = usize_from_value ( params. first ( ) , "start_height" ) ?;
230
230
let count = MAX_HEADERS . min ( usize_from_value ( params. get ( 1 ) , "count" ) ?) ;
231
231
let cp_height = usize_from_value_or ( params. get ( 2 ) , "cp_height" , 0 ) ?;
232
232
let heights: Vec < usize > = ( start_height..( start_height + count) ) . collect ( ) ;
@@ -261,7 +261,7 @@ impl Connection {
261
261
}
262
262
263
263
fn blockchain_estimatefee ( & self , params : & [ Value ] ) -> Result < Value > {
264
- let conf_target = usize_from_value ( params. get ( 0 ) , "blocks_count" ) ?;
264
+ let conf_target = usize_from_value ( params. first ( ) , "blocks_count" ) ?;
265
265
let fee_rate = self
266
266
. query
267
267
. estimate_fee ( conf_target as u16 )
@@ -277,7 +277,7 @@ impl Connection {
277
277
}
278
278
279
279
fn blockchain_scripthash_subscribe ( & mut self , params : & [ Value ] ) -> Result < Value > {
280
- let script_hash = hash_from_value ( params. get ( 0 ) ) . chain_err ( || "bad script_hash" ) ?;
280
+ let script_hash = hash_from_value ( params. first ( ) ) . chain_err ( || "bad script_hash" ) ?;
281
281
282
282
let history_txids = get_history ( & self . query , & script_hash[ ..] , self . txs_limit ) ?;
283
283
let status_hash = get_status_hash ( history_txids, & self . query )
@@ -295,7 +295,7 @@ impl Connection {
295
295
296
296
#[ cfg( not( feature = "liquid" ) ) ]
297
297
fn blockchain_scripthash_get_balance ( & self , params : & [ Value ] ) -> Result < Value > {
298
- let script_hash = hash_from_value ( params. get ( 0 ) ) . chain_err ( || "bad script_hash" ) ?;
298
+ let script_hash = hash_from_value ( params. first ( ) ) . chain_err ( || "bad script_hash" ) ?;
299
299
let ( chain_stats, mempool_stats) = self . query . stats ( & script_hash[ ..] ) ;
300
300
301
301
Ok ( json ! ( {
@@ -305,7 +305,7 @@ impl Connection {
305
305
}
306
306
307
307
fn blockchain_scripthash_get_history ( & self , params : & [ Value ] ) -> Result < Value > {
308
- let script_hash = hash_from_value ( params. get ( 0 ) ) . chain_err ( || "bad script_hash" ) ?;
308
+ let script_hash = hash_from_value ( params. first ( ) ) . chain_err ( || "bad script_hash" ) ?;
309
309
let history_txids = get_history ( & self . query , & script_hash[ ..] , self . txs_limit ) ?;
310
310
311
311
Ok ( json ! ( history_txids
@@ -323,7 +323,7 @@ impl Connection {
323
323
}
324
324
325
325
fn blockchain_scripthash_listunspent ( & self , params : & [ Value ] ) -> Result < Value > {
326
- let script_hash = hash_from_value ( params. get ( 0 ) ) . chain_err ( || "bad script_hash" ) ?;
326
+ let script_hash = hash_from_value ( params. first ( ) ) . chain_err ( || "bad script_hash" ) ?;
327
327
let utxos = self . query . utxo ( & script_hash[ ..] ) ?;
328
328
329
329
let to_json = |utxo : Utxo | {
@@ -351,7 +351,7 @@ impl Connection {
351
351
}
352
352
353
353
fn blockchain_transaction_broadcast ( & self , params : & [ Value ] ) -> Result < Value > {
354
- let tx = params. get ( 0 ) . chain_err ( || "missing tx" ) ?;
354
+ let tx = params. first ( ) . chain_err ( || "missing tx" ) ?;
355
355
let tx = tx. as_str ( ) . chain_err ( || "non-string tx" ) ?. to_string ( ) ;
356
356
let txid = self . query . broadcast_raw ( & tx) ?;
357
357
if let Err ( e) = self . chan . sender ( ) . try_send ( Message :: PeriodicUpdate ) {
@@ -361,7 +361,7 @@ impl Connection {
361
361
}
362
362
363
363
fn blockchain_transaction_get ( & self , params : & [ Value ] ) -> Result < Value > {
364
- let tx_hash = Txid :: from ( hash_from_value ( params. get ( 0 ) ) . chain_err ( || "bad tx_hash" ) ?) ;
364
+ let tx_hash = Txid :: from ( hash_from_value ( params. first ( ) ) . chain_err ( || "bad tx_hash" ) ?) ;
365
365
let verbose = match params. get ( 1 ) {
366
366
Some ( value) => value. as_bool ( ) . chain_err ( || "non-bool verbose value" ) ?,
367
367
None => false ,
@@ -380,7 +380,7 @@ impl Connection {
380
380
}
381
381
382
382
fn blockchain_transaction_get_merkle ( & self , params : & [ Value ] ) -> Result < Value > {
383
- let txid = Txid :: from ( hash_from_value ( params. get ( 0 ) ) . chain_err ( || "bad tx_hash" ) ?) ;
383
+ let txid = Txid :: from ( hash_from_value ( params. first ( ) ) . chain_err ( || "bad tx_hash" ) ?) ;
384
384
let height = usize_from_value ( params. get ( 1 ) , "height" ) ?;
385
385
let blockid = self
386
386
. query
@@ -399,7 +399,7 @@ impl Connection {
399
399
}
400
400
401
401
fn blockchain_transaction_id_from_pos ( & self , params : & [ Value ] ) -> Result < Value > {
402
- let height = usize_from_value ( params. get ( 0 ) , "height" ) ?;
402
+ let height = usize_from_value ( params. first ( ) , "height" ) ?;
403
403
let tx_pos = usize_from_value ( params. get ( 1 ) , "tx_pos" ) ?;
404
404
let want_merkle = bool_from_value_or ( params. get ( 2 ) , "merkle" , false ) ?;
405
405
@@ -513,26 +513,15 @@ impl Connection {
513
513
}
514
514
515
515
fn handle_replies ( & mut self , shutdown : crossbeam_channel:: Receiver < ( ) > ) -> Result < ( ) > {
516
- let empty_params = json ! ( [ ] ) ;
517
516
loop {
518
517
crossbeam_channel:: select! {
519
518
recv( self . chan. receiver( ) ) -> msg => {
520
519
let msg = msg. chain_err( || "channel closed" ) ?;
521
520
trace!( "RPC {:?}" , msg) ;
522
521
match msg {
523
522
Message :: Request ( line) => {
524
- let cmd: Value = from_str( & line) . chain_err( || "invalid JSON format" ) ?;
525
- let reply = match (
526
- cmd. get( "method" ) ,
527
- cmd. get( "params" ) . unwrap_or( & empty_params) ,
528
- cmd. get( "id" ) ,
529
- ) {
530
- ( Some ( Value :: String ( method) ) , Value :: Array ( params) , Some ( id) ) => {
531
- self . handle_command( method, params, id) ?
532
- }
533
- _ => bail!( "invalid command: {}" , cmd) ,
534
- } ;
535
- self . send_values( & [ reply] ) ?
523
+ let result = self . handle_line( & line) ;
524
+ self . send_values( & [ result] ) ?
536
525
}
537
526
Message :: PeriodicUpdate => {
538
527
let values = self
@@ -554,6 +543,48 @@ impl Connection {
554
543
}
555
544
}
556
545
546
+ #[ inline]
547
+ fn handle_line ( & mut self , line : & String ) -> Value {
548
+ if let Ok ( json_value) = from_str ( line) {
549
+ match json_value {
550
+ Value :: Array ( mut arr) => {
551
+ for cmd in & mut arr {
552
+ // Replace each cmd with its response in-memory.
553
+ * cmd = self . handle_value ( cmd) ;
554
+ }
555
+ Value :: Array ( arr)
556
+ }
557
+ cmd => self . handle_value ( & cmd) ,
558
+ }
559
+ } else {
560
+ // serde_json was unable to parse
561
+ invalid_json_rpc ( line)
562
+ }
563
+ }
564
+
565
+ #[ inline]
566
+ fn handle_value ( & mut self , value : & Value ) -> Value {
567
+ match (
568
+ value. get ( "method" ) ,
569
+ value. get ( "params" ) . unwrap_or ( & json ! ( [ ] ) ) ,
570
+ value. get ( "id" ) ,
571
+ ) {
572
+ ( Some ( Value :: String ( method) ) , Value :: Array ( params) , Some ( id) ) => self
573
+ . handle_command ( method, params, id)
574
+ . unwrap_or_else ( |err| {
575
+ json ! ( {
576
+ "error" : {
577
+ "code" : 1 ,
578
+ "message" : format!( "{method} RPC error: {err}" )
579
+ } ,
580
+ "id" : id,
581
+ "jsonrpc" : "2.0"
582
+ } )
583
+ } ) ,
584
+ _ => invalid_json_rpc ( value) ,
585
+ }
586
+ }
587
+
557
588
fn handle_requests (
558
589
mut reader : BufReader < ConnectionStream > ,
559
590
tx : crossbeam_channel:: Sender < Message > ,
@@ -629,6 +660,18 @@ impl Connection {
629
660
}
630
661
}
631
662
663
+ #[ inline]
664
+ fn invalid_json_rpc ( input : impl core:: fmt:: Display ) -> Value {
665
+ json ! ( {
666
+ "error" : {
667
+ "code" : -32600 ,
668
+ "message" : format!( "invalid request: {input}" )
669
+ } ,
670
+ "id" : null,
671
+ "jsonrpc" : "2.0"
672
+ } )
673
+ }
674
+
632
675
fn get_history (
633
676
query : & Query ,
634
677
scripthash : & [ u8 ] ,
0 commit comments