@@ -396,65 +396,58 @@ impl Rpc {
396
396
}
397
397
398
398
pub fn handle_requests ( & self , client : & mut Client , lines : & [ String ] ) -> Vec < String > {
399
- lines
399
+ let parsed : Vec < Result < Calls , Value > > = lines
400
400
. iter ( )
401
- . map ( |line| self . handle_request ( client, & line) )
401
+ . map ( |line| {
402
+ parse_requests ( & line)
403
+ . map ( Calls :: parse)
404
+ . map_err ( error_msg_no_id)
405
+ } )
406
+ . collect ( ) ;
407
+
408
+ parsed
409
+ . into_iter ( )
410
+ . map ( |calls| self . handle_calls ( client, calls) . to_string ( ) )
402
411
. collect ( )
403
412
}
404
413
405
- fn handle_request ( & self , client : & mut Client , line : & str ) -> String {
406
- let error_msg_no_id = |err| error_msg ( Value :: Null , RpcError :: Standard ( err) ) ;
407
- let response: Value = match serde_json:: from_str ( line) {
408
- // parse JSON from str
409
- Ok ( value) => match serde_json:: from_value ( value) {
410
- // parse RPC from JSON
411
- Ok ( requests) => match requests {
412
- Requests :: Single ( request) => self . call ( client, request) ,
413
- Requests :: Batch ( requests) => json ! ( requests
414
- . into_iter( )
415
- . map( |request| self . call( client, request) )
416
- . collect:: <Vec <Value >>( ) ) ,
417
- } ,
418
- Err ( err) => {
419
- warn ! ( "invalid RPC request ({:?}): {}" , line, err) ;
420
- error_msg_no_id ( StandardError :: InvalidRequest )
421
- }
422
- } ,
423
- Err ( err) => {
424
- warn ! ( "invalid JSON ({:?}): {}" , line, err) ;
425
- error_msg_no_id ( StandardError :: ParseError )
426
- }
427
- } ;
428
- response. to_string ( )
414
+ fn handle_calls ( & self , client : & mut Client , calls : Result < Calls , Value > ) -> Value {
415
+ match calls {
416
+ Ok ( Calls :: Batch ( batch) ) => json ! ( batch
417
+ . into_iter( )
418
+ . map( |call| self . single_call( client, call) )
419
+ . collect:: <Vec <_>>( ) ) ,
420
+ Ok ( Calls :: Single ( call) ) => json ! ( self . single_call( client, call) ) ,
421
+ Err ( response) => response, // JSON parsing may fail - the response does not contain request id
422
+ }
429
423
}
430
424
431
- fn call ( & self , client : & mut Client , request : Request ) -> Value {
432
- let Request { id, method, params } = request;
433
- let call = match Call :: parse ( & method, params) {
425
+ fn single_call ( & self , client : & mut Client , call : Result < Call , Value > ) -> Value {
426
+ let Call { id, method, params } = match call {
434
427
Ok ( call) => call,
435
- Err ( err ) => return error_msg ( id , RpcError :: Standard ( err ) ) ,
428
+ Err ( response ) => return response , // params parsing may fail - the response contains request id
436
429
} ;
437
430
self . rpc_duration . observe_duration ( & method, || {
438
- let result = match call {
439
- Call :: Banner => Ok ( json ! ( self . banner) ) ,
440
- Call :: BlockHeader ( args) => self . block_header ( args) ,
441
- Call :: BlockHeaders ( args) => self . block_headers ( args) ,
442
- Call :: Donation => Ok ( Value :: Null ) ,
443
- Call :: EstimateFee ( args) => self . estimate_fee ( args) ,
444
- Call :: Features => self . features ( ) ,
445
- Call :: HeadersSubscribe => self . headers_subscribe ( client) ,
446
- Call :: MempoolFeeHistogram => self . get_fee_histogram ( ) ,
447
- Call :: PeersSubscribe => Ok ( json ! ( [ ] ) ) ,
448
- Call :: Ping => Ok ( Value :: Null ) ,
449
- Call :: RelayFee => self . relayfee ( ) ,
450
- Call :: ScriptHashGetBalance ( args) => self . scripthash_get_balance ( client, args) ,
451
- Call :: ScriptHashGetHistory ( args) => self . scripthash_get_history ( client, args) ,
452
- Call :: ScriptHashListUnspent ( args) => self . scripthash_list_unspent ( client, args) ,
453
- Call :: ScriptHashSubscribe ( args) => self . scripthash_subscribe ( client, args) ,
454
- Call :: TransactionBroadcast ( args) => self . transaction_broadcast ( args) ,
455
- Call :: TransactionGet ( args) => self . transaction_get ( args) ,
456
- Call :: TransactionGetMerkle ( args) => self . transaction_get_merkle ( args) ,
457
- Call :: Version ( args) => self . version ( args) ,
431
+ let result = match params {
432
+ Params :: Banner => Ok ( json ! ( self . banner) ) ,
433
+ Params :: BlockHeader ( args) => self . block_header ( args) ,
434
+ Params :: BlockHeaders ( args) => self . block_headers ( args) ,
435
+ Params :: Donation => Ok ( Value :: Null ) ,
436
+ Params :: EstimateFee ( args) => self . estimate_fee ( args) ,
437
+ Params :: Features => self . features ( ) ,
438
+ Params :: HeadersSubscribe => self . headers_subscribe ( client) ,
439
+ Params :: MempoolFeeHistogram => self . get_fee_histogram ( ) ,
440
+ Params :: PeersSubscribe => Ok ( json ! ( [ ] ) ) ,
441
+ Params :: Ping => Ok ( Value :: Null ) ,
442
+ Params :: RelayFee => self . relayfee ( ) ,
443
+ Params :: ScriptHashGetBalance ( args) => self . scripthash_get_balance ( client, args) ,
444
+ Params :: ScriptHashGetHistory ( args) => self . scripthash_get_history ( client, args) ,
445
+ Params :: ScriptHashListUnspent ( args) => self . scripthash_list_unspent ( client, args) ,
446
+ Params :: ScriptHashSubscribe ( args) => self . scripthash_subscribe ( client, args) ,
447
+ Params :: TransactionBroadcast ( args) => self . transaction_broadcast ( args) ,
448
+ Params :: TransactionGet ( args) => self . transaction_get ( args) ,
449
+ Params :: TransactionGetMerkle ( args) => self . transaction_get_merkle ( args) ,
450
+ Params :: Version ( args) => self . version ( args) ,
458
451
} ;
459
452
match result {
460
453
Ok ( value) => result_msg ( id, value) ,
@@ -474,7 +467,7 @@ impl Rpc {
474
467
}
475
468
476
469
#[ derive( Deserialize ) ]
477
- enum Call {
470
+ enum Params {
478
471
Banner ,
479
472
BlockHeader ( ( usize , ) ) ,
480
473
BlockHeaders ( ( usize , usize ) ) ,
@@ -496,28 +489,28 @@ enum Call {
496
489
Version ( ( String , Version ) ) ,
497
490
}
498
491
499
- impl Call {
500
- fn parse ( method : & str , params : Value ) -> std:: result:: Result < Call , StandardError > {
492
+ impl Params {
493
+ fn parse ( method : & str , params : Value ) -> std:: result:: Result < Params , StandardError > {
501
494
Ok ( match method {
502
- "blockchain.block.header" => Call :: BlockHeader ( convert ( params) ?) ,
503
- "blockchain.block.headers" => Call :: BlockHeaders ( convert ( params) ?) ,
504
- "blockchain.estimatefee" => Call :: EstimateFee ( convert ( params) ?) ,
505
- "blockchain.headers.subscribe" => Call :: HeadersSubscribe ,
506
- "blockchain.relayfee" => Call :: RelayFee ,
507
- "blockchain.scripthash.get_balance" => Call :: ScriptHashGetBalance ( convert ( params) ?) ,
508
- "blockchain.scripthash.get_history" => Call :: ScriptHashGetHistory ( convert ( params) ?) ,
509
- "blockchain.scripthash.listunspent" => Call :: ScriptHashListUnspent ( convert ( params) ?) ,
510
- "blockchain.scripthash.subscribe" => Call :: ScriptHashSubscribe ( convert ( params) ?) ,
511
- "blockchain.transaction.broadcast" => Call :: TransactionBroadcast ( convert ( params) ?) ,
512
- "blockchain.transaction.get" => Call :: TransactionGet ( convert ( params) ?) ,
513
- "blockchain.transaction.get_merkle" => Call :: TransactionGetMerkle ( convert ( params) ?) ,
514
- "mempool.get_fee_histogram" => Call :: MempoolFeeHistogram ,
515
- "server.banner" => Call :: Banner ,
516
- "server.donation_address" => Call :: Donation ,
517
- "server.features" => Call :: Features ,
518
- "server.peers.subscribe" => Call :: PeersSubscribe ,
519
- "server.ping" => Call :: Ping ,
520
- "server.version" => Call :: Version ( convert ( params) ?) ,
495
+ "blockchain.block.header" => Params :: BlockHeader ( convert ( params) ?) ,
496
+ "blockchain.block.headers" => Params :: BlockHeaders ( convert ( params) ?) ,
497
+ "blockchain.estimatefee" => Params :: EstimateFee ( convert ( params) ?) ,
498
+ "blockchain.headers.subscribe" => Params :: HeadersSubscribe ,
499
+ "blockchain.relayfee" => Params :: RelayFee ,
500
+ "blockchain.scripthash.get_balance" => Params :: ScriptHashGetBalance ( convert ( params) ?) ,
501
+ "blockchain.scripthash.get_history" => Params :: ScriptHashGetHistory ( convert ( params) ?) ,
502
+ "blockchain.scripthash.listunspent" => Params :: ScriptHashListUnspent ( convert ( params) ?) ,
503
+ "blockchain.scripthash.subscribe" => Params :: ScriptHashSubscribe ( convert ( params) ?) ,
504
+ "blockchain.transaction.broadcast" => Params :: TransactionBroadcast ( convert ( params) ?) ,
505
+ "blockchain.transaction.get" => Params :: TransactionGet ( convert ( params) ?) ,
506
+ "blockchain.transaction.get_merkle" => Params :: TransactionGetMerkle ( convert ( params) ?) ,
507
+ "mempool.get_fee_histogram" => Params :: MempoolFeeHistogram ,
508
+ "server.banner" => Params :: Banner ,
509
+ "server.donation_address" => Params :: Donation ,
510
+ "server.features" => Params :: Features ,
511
+ "server.peers.subscribe" => Params :: PeersSubscribe ,
512
+ "server.ping" => Params :: Ping ,
513
+ "server.version" => Params :: Version ( convert ( params) ?) ,
521
514
_ => {
522
515
warn ! ( "unknown method {}" , method) ;
523
516
return Err ( StandardError :: MethodNotFound ) ;
@@ -526,6 +519,41 @@ impl Call {
526
519
}
527
520
}
528
521
522
+ struct Call {
523
+ id : Value ,
524
+ method : String ,
525
+ params : Params ,
526
+ }
527
+
528
+ impl Call {
529
+ fn parse ( request : Request ) -> Result < Call , Value > {
530
+ match Params :: parse ( & request. method , request. params ) {
531
+ Ok ( params) => Ok ( Call {
532
+ id : request. id ,
533
+ method : request. method ,
534
+ params,
535
+ } ) ,
536
+ Err ( e) => Err ( error_msg ( request. id , RpcError :: Standard ( e) ) ) ,
537
+ }
538
+ }
539
+ }
540
+
541
+ enum Calls {
542
+ Batch ( Vec < Result < Call , Value > > ) ,
543
+ Single ( Result < Call , Value > ) ,
544
+ }
545
+
546
+ impl Calls {
547
+ fn parse ( requests : Requests ) -> Calls {
548
+ match requests {
549
+ Requests :: Single ( request) => Calls :: Single ( Call :: parse ( request) ) ,
550
+ Requests :: Batch ( batch) => {
551
+ Calls :: Batch ( batch. into_iter ( ) . map ( Call :: parse) . collect :: < Vec < _ > > ( ) )
552
+ }
553
+ }
554
+ }
555
+ }
556
+
529
557
fn convert < T > ( params : Value ) -> std:: result:: Result < T , StandardError >
530
558
where
531
559
T : serde:: de:: DeserializeOwned ,
@@ -548,3 +576,25 @@ fn result_msg(id: Value, result: Value) -> Value {
548
576
fn error_msg ( id : Value , error : RpcError ) -> Value {
549
577
json ! ( { "jsonrpc" : "2.0" , "id" : id, "error" : error. to_value( ) } )
550
578
}
579
+
580
+ fn error_msg_no_id ( err : StandardError ) -> Value {
581
+ error_msg ( Value :: Null , RpcError :: Standard ( err) )
582
+ }
583
+
584
+ fn parse_requests ( line : & str ) -> Result < Requests , StandardError > {
585
+ match serde_json:: from_str ( line) {
586
+ // parse JSON from str
587
+ Ok ( value) => match serde_json:: from_value ( value) {
588
+ // parse RPC from JSON
589
+ Ok ( requests) => Ok ( requests) ,
590
+ Err ( err) => {
591
+ warn ! ( "invalid RPC request ({:?}): {}" , line, err) ;
592
+ Err ( StandardError :: InvalidRequest )
593
+ }
594
+ } ,
595
+ Err ( err) => {
596
+ warn ! ( "invalid JSON ({:?}): {}" , line, err) ;
597
+ Err ( StandardError :: ParseError )
598
+ }
599
+ }
600
+ }
0 commit comments