2018-08-16 08:46:07 -06:00
//! The `rpc` module implements the Solana RPC interface.
2018-08-10 17:05:23 -06:00
2018-09-26 17:33:18 -06:00
use bank ::{ Bank , BankError } ;
2018-08-22 11:53:24 -06:00
use bincode ::deserialize ;
2018-08-10 17:05:23 -06:00
use bs58 ;
2018-10-10 14:51:43 -06:00
use cluster_info ::FULLNODE_PORT_RANGE ;
2018-08-13 13:59:04 -06:00
use jsonrpc_core ::* ;
2018-08-14 18:03:48 -06:00
use jsonrpc_http_server ::* ;
2018-10-10 14:51:43 -06:00
use jsonrpc_macros ::pubsub ::Sink ;
use netutil ::find_available_port_in_range ;
2018-10-12 08:17:28 -07:00
use rpc_pubsub ::{ PubSubService , SubscriptionResponse } ;
2018-09-10 22:41:44 -07:00
use service ::Service ;
2018-10-10 14:51:43 -06:00
use signature ::{ Keypair , KeypairUtil , Signature } ;
2018-09-27 07:49:26 -07:00
use solana_program_interface ::account ::Account ;
use solana_program_interface ::pubkey ::Pubkey ;
2018-08-10 17:05:23 -06:00
use std ::mem ;
2018-08-22 11:53:24 -06:00
use std ::net ::{ SocketAddr , UdpSocket } ;
2018-09-26 15:57:34 -06:00
use std ::result ;
2018-09-10 22:41:44 -07:00
use std ::sync ::atomic ::{ AtomicBool , Ordering } ;
2018-08-14 18:03:48 -06:00
use std ::sync ::Arc ;
2018-09-10 22:41:44 -07:00
use std ::thread ::{ self , sleep , Builder , JoinHandle } ;
2018-08-22 12:25:21 -06:00
use std ::time ::Duration ;
use std ::time ::Instant ;
2018-08-22 11:53:24 -06:00
use transaction ::Transaction ;
use wallet ::request_airdrop ;
2018-08-10 17:05:23 -06:00
pub const RPC_PORT : u16 = 8899 ;
2018-08-14 18:03:48 -06:00
pub struct JsonRpcService {
2018-09-10 22:41:44 -07:00
thread_hdl : JoinHandle < ( ) > ,
2018-08-14 18:03:48 -06:00
}
impl JsonRpcService {
2018-08-22 11:53:24 -06:00
pub fn new (
2018-08-22 16:44:26 -06:00
bank : & Arc < Bank > ,
2018-08-22 11:53:24 -06:00
transactions_addr : SocketAddr ,
2018-08-22 11:54:37 -06:00
drone_addr : SocketAddr ,
2018-08-22 11:53:24 -06:00
rpc_addr : SocketAddr ,
2018-09-10 22:41:44 -07:00
exit : Arc < AtomicBool > ,
2018-08-22 11:53:24 -06:00
) -> Self {
2018-08-22 16:44:26 -06:00
let request_processor = JsonRpcRequestProcessor ::new ( bank . clone ( ) ) ;
2018-10-10 14:51:43 -06:00
let exit_pubsub = exit . clone ( ) ;
2018-09-10 22:41:44 -07:00
let thread_hdl = Builder ::new ( )
. name ( " solana-jsonrpc " . to_string ( ) )
. spawn ( move | | {
let mut io = MetaIoHandler ::default ( ) ;
let rpc = RpcSolImpl ;
io . extend_with ( rpc . to_delegate ( ) ) ;
2018-08-15 12:41:39 -06:00
2018-09-10 22:41:44 -07:00
let server =
2018-09-28 08:20:26 -06:00
ServerBuilder ::with_meta_extractor ( io , move | _req : & hyper ::Request < hyper ::Body > | Meta {
2018-09-10 22:41:44 -07:00
request_processor : request_processor . clone ( ) ,
transactions_addr ,
drone_addr ,
2018-10-10 14:51:43 -06:00
rpc_addr ,
exit : exit_pubsub . clone ( ) ,
2018-09-10 22:41:44 -07:00
} ) . threads ( 4 )
. cors ( DomainsValidation ::AllowOnly ( vec! [
AccessControlAllowOrigin ::Any ,
] ) )
. start_http ( & rpc_addr ) ;
if server . is_err ( ) {
warn! ( " JSON RPC service unavailable: unable to bind to RPC port {}. \n Make sure this port is not already in use by another application " , rpc_addr . port ( ) ) ;
return ;
}
loop {
if exit . load ( Ordering ::Relaxed ) {
server . unwrap ( ) . close ( ) ;
break ;
}
sleep ( Duration ::from_millis ( 100 ) ) ;
}
( )
} )
. unwrap ( ) ;
JsonRpcService { thread_hdl }
}
}
2018-08-14 18:03:48 -06:00
2018-09-10 22:41:44 -07:00
impl Service for JsonRpcService {
2018-09-13 14:00:17 -07:00
type JoinReturnType = ( ) ;
2018-08-14 18:03:48 -06:00
2018-09-10 22:41:44 -07:00
fn join ( self ) -> thread ::Result < ( ) > {
2018-09-15 23:46:16 -07:00
self . thread_hdl . join ( )
2018-08-14 18:03:48 -06:00
}
}
2018-08-10 17:05:23 -06:00
#[ derive(Clone) ]
pub struct Meta {
2018-08-15 10:37:02 -06:00
pub request_processor : JsonRpcRequestProcessor ,
2018-08-22 11:53:24 -06:00
pub transactions_addr : SocketAddr ,
2018-08-22 11:54:37 -06:00
pub drone_addr : SocketAddr ,
2018-10-10 14:51:43 -06:00
pub rpc_addr : SocketAddr ,
pub exit : Arc < AtomicBool > ,
2018-08-10 17:05:23 -06:00
}
impl Metadata for Meta { }
2018-10-10 14:51:43 -06:00
#[ derive(Copy, Clone, PartialEq, Serialize, Debug) ]
2018-09-26 17:12:40 -07:00
pub enum RpcSignatureStatus {
Confirmed ,
SignatureNotFound ,
ProgramRuntimeError ,
GenericFailure ,
}
2018-08-10 17:05:23 -06:00
build_rpc_trait! {
pub trait RpcSol {
type Metadata ;
2018-08-15 11:34:17 -06:00
#[ rpc(meta, name = " confirmTransaction " ) ]
2018-08-10 17:05:23 -06:00
fn confirm_transaction ( & self , Self ::Metadata , String ) -> Result < bool > ;
2018-09-20 23:27:06 -06:00
#[ rpc(meta, name = " getAccountInfo " ) ]
fn get_account_info ( & self , Self ::Metadata , String ) -> Result < Account > ;
2018-08-15 11:34:17 -06:00
#[ rpc(meta, name = " getBalance " ) ]
2018-08-20 14:20:20 -07:00
fn get_balance ( & self , Self ::Metadata , String ) -> Result < i64 > ;
2018-08-14 18:03:48 -06:00
2018-08-15 11:34:17 -06:00
#[ rpc(meta, name = " getFinality " ) ]
2018-08-14 18:03:48 -06:00
fn get_finality ( & self , Self ::Metadata ) -> Result < usize > ;
2018-08-10 17:05:23 -06:00
2018-08-15 11:34:17 -06:00
#[ rpc(meta, name = " getLastId " ) ]
2018-08-13 12:52:37 -06:00
fn get_last_id ( & self , Self ::Metadata ) -> Result < String > ;
2018-09-26 17:12:40 -07:00
#[ rpc(meta, name = " getSignatureStatus " ) ]
fn get_signature_status ( & self , Self ::Metadata , String ) -> Result < RpcSignatureStatus > ;
2018-08-15 11:34:17 -06:00
#[ rpc(meta, name = " getTransactionCount " ) ]
2018-08-10 17:05:23 -06:00
fn get_transaction_count ( & self , Self ::Metadata ) -> Result < u64 > ;
2018-08-22 11:54:37 -06:00
#[ rpc(meta, name= " requestAirdrop " ) ]
2018-08-26 22:32:51 -06:00
fn request_airdrop ( & self , Self ::Metadata , String , u64 ) -> Result < String > ;
2018-08-22 11:54:37 -06:00
2018-08-22 11:53:24 -06:00
#[ rpc(meta, name = " sendTransaction " ) ]
fn send_transaction ( & self , Self ::Metadata , Vec < u8 > ) -> Result < String > ;
2018-10-10 14:51:43 -06:00
#[ rpc(meta, name = " startSubscriptionChannel " ) ]
fn start_subscription_channel ( & self , Self ::Metadata ) -> Result < SubscriptionResponse > ;
2018-08-10 17:05:23 -06:00
}
}
pub struct RpcSolImpl ;
impl RpcSol for RpcSolImpl {
type Metadata = Meta ;
fn confirm_transaction ( & self , meta : Self ::Metadata , id : String ) -> Result < bool > {
2018-09-26 17:12:40 -07:00
self . get_signature_status ( meta , id )
. map ( | status | status = = RpcSignatureStatus ::Confirmed )
2018-08-10 17:05:23 -06:00
}
2018-09-26 17:12:40 -07:00
2018-09-20 23:27:06 -06:00
fn get_account_info ( & self , meta : Self ::Metadata , id : String ) -> Result < Account > {
let pubkey_vec = bs58 ::decode ( id )
. into_vec ( )
. map_err ( | _ | Error ::invalid_request ( ) ) ? ;
if pubkey_vec . len ( ) ! = mem ::size_of ::< Pubkey > ( ) {
return Err ( Error ::invalid_request ( ) ) ;
}
let pubkey = Pubkey ::new ( & pubkey_vec ) ;
meta . request_processor . get_account_info ( pubkey )
}
2018-08-20 14:20:20 -07:00
fn get_balance ( & self , meta : Self ::Metadata , id : String ) -> Result < i64 > {
let pubkey_vec = bs58 ::decode ( id )
. into_vec ( )
. map_err ( | _ | Error ::invalid_request ( ) ) ? ;
2018-08-10 17:05:23 -06:00
if pubkey_vec . len ( ) ! = mem ::size_of ::< Pubkey > ( ) {
2018-08-15 11:44:00 -06:00
return Err ( Error ::invalid_request ( ) ) ;
}
let pubkey = Pubkey ::new ( & pubkey_vec ) ;
2018-08-15 12:41:39 -06:00
meta . request_processor . get_balance ( pubkey )
2018-08-10 17:05:23 -06:00
}
2018-08-14 18:03:48 -06:00
fn get_finality ( & self , meta : Self ::Metadata ) -> Result < usize > {
2018-08-15 12:41:39 -06:00
meta . request_processor . get_finality ( )
2018-08-14 18:03:48 -06:00
}
2018-08-13 12:52:37 -06:00
fn get_last_id ( & self , meta : Self ::Metadata ) -> Result < String > {
2018-08-15 12:41:39 -06:00
meta . request_processor . get_last_id ( )
2018-08-13 12:52:37 -06:00
}
2018-09-26 17:12:40 -07:00
fn get_signature_status ( & self , meta : Self ::Metadata , id : String ) -> Result < RpcSignatureStatus > {
let signature_vec = bs58 ::decode ( id )
. into_vec ( )
. map_err ( | _ | Error ::invalid_request ( ) ) ? ;
if signature_vec . len ( ) ! = mem ::size_of ::< Signature > ( ) {
return Err ( Error ::invalid_request ( ) ) ;
}
let signature = Signature ::new ( & signature_vec ) ;
Ok (
match meta . request_processor . get_signature_status ( signature ) {
Ok ( _ ) = > RpcSignatureStatus ::Confirmed ,
2018-09-28 16:16:35 -07:00
Err ( BankError ::ProgramRuntimeError ( _ ) ) = > RpcSignatureStatus ::ProgramRuntimeError ,
2018-09-26 17:12:40 -07:00
Err ( BankError ::SignatureNotFound ) = > RpcSignatureStatus ::SignatureNotFound ,
2018-09-26 19:23:27 -07:00
Err ( err ) = > {
trace! ( " mapping {:?} to GenericFailure " , err ) ;
RpcSignatureStatus ::GenericFailure
}
2018-09-26 17:12:40 -07:00
} ,
)
}
2018-08-10 17:05:23 -06:00
fn get_transaction_count ( & self , meta : Self ::Metadata ) -> Result < u64 > {
2018-08-15 12:41:39 -06:00
meta . request_processor . get_transaction_count ( )
2018-08-14 18:03:48 -06:00
}
2018-08-26 22:32:51 -06:00
fn request_airdrop ( & self , meta : Self ::Metadata , id : String , tokens : u64 ) -> Result < String > {
2018-08-22 11:54:37 -06:00
let pubkey_vec = bs58 ::decode ( id )
. into_vec ( )
. map_err ( | _ | Error ::invalid_request ( ) ) ? ;
if pubkey_vec . len ( ) ! = mem ::size_of ::< Pubkey > ( ) {
return Err ( Error ::invalid_request ( ) ) ;
}
let pubkey = Pubkey ::new ( & pubkey_vec ) ;
2018-08-26 22:32:51 -06:00
let signature = request_airdrop ( & meta . drone_addr , & pubkey , tokens )
2018-08-22 11:54:37 -06:00
. map_err ( | _ | Error ::internal_error ( ) ) ? ;
2018-08-22 12:25:21 -06:00
let now = Instant ::now ( ) ;
2018-08-26 22:32:51 -06:00
let mut signature_status ;
2018-08-22 12:25:21 -06:00
loop {
2018-09-26 17:12:40 -07:00
signature_status = meta . request_processor . get_signature_status ( signature ) ;
2018-08-26 22:32:51 -06:00
2018-09-26 15:57:34 -06:00
if signature_status . is_ok ( ) {
2018-08-26 22:32:51 -06:00
return Ok ( bs58 ::encode ( signature ) . into_string ( ) ) ;
2018-08-22 12:25:21 -06:00
} else if now . elapsed ( ) . as_secs ( ) > 5 {
return Err ( Error ::internal_error ( ) ) ;
}
sleep ( Duration ::from_millis ( 100 ) ) ;
}
2018-08-22 11:54:37 -06:00
}
2018-08-22 11:53:24 -06:00
fn send_transaction ( & self , meta : Self ::Metadata , data : Vec < u8 > ) -> Result < String > {
2018-09-18 11:31:21 -07:00
let tx : Transaction = deserialize ( & data ) . map_err ( | err | {
debug! ( " send_transaction: deserialize error: {:?} " , err ) ;
Error ::invalid_request ( )
} ) ? ;
2018-08-22 11:53:24 -06:00
let transactions_socket = UdpSocket ::bind ( " 0.0.0.0:0 " ) . unwrap ( ) ;
transactions_socket
. send_to ( & data , & meta . transactions_addr )
2018-09-18 11:31:21 -07:00
. map_err ( | err | {
debug! ( " send_transaction: send_to error: {:?} " , err ) ;
Error ::internal_error ( )
} ) ? ;
2018-09-26 11:17:45 -06:00
Ok ( bs58 ::encode ( tx . signature ) . into_string ( ) )
2018-08-22 11:53:24 -06:00
}
2018-10-10 14:51:43 -06:00
fn start_subscription_channel ( & self , meta : Self ::Metadata ) -> Result < SubscriptionResponse > {
let port : u16 = find_available_port_in_range ( FULLNODE_PORT_RANGE ) . map_err ( | _ | Error {
code : ErrorCode ::InternalError ,
message : " No available port in range " . into ( ) ,
data : None ,
} ) ? ;
let mut pubsub_addr = meta . rpc_addr ;
pubsub_addr . set_port ( port ) ;
let pubkey = Keypair ::new ( ) . pubkey ( ) ;
let _pubsub_service =
PubSubService ::new ( & meta . request_processor . bank , pubsub_addr , pubkey , meta . exit ) ;
Ok ( SubscriptionResponse {
port ,
path : pubkey . to_string ( ) ,
} )
}
2018-08-14 18:03:48 -06:00
}
#[ derive(Clone) ]
pub struct JsonRpcRequestProcessor {
bank : Arc < Bank > ,
}
impl JsonRpcRequestProcessor {
/// Create a new request processor that wraps the given Bank.
pub fn new ( bank : Arc < Bank > ) -> Self {
JsonRpcRequestProcessor { bank }
2018-08-10 17:05:23 -06:00
}
2018-08-15 12:41:39 -06:00
/// Process JSON-RPC request items sent via JSON-RPC.
2018-10-10 14:51:43 -06:00
pub fn get_account_info ( & self , pubkey : Pubkey ) -> Result < Account > {
2018-09-20 23:27:06 -06:00
self . bank
. get_account ( & pubkey )
2018-09-24 13:26:47 -06:00
. ok_or_else ( Error ::invalid_request )
2018-09-20 23:27:06 -06:00
}
2018-08-20 14:20:20 -07:00
fn get_balance ( & self , pubkey : Pubkey ) -> Result < i64 > {
2018-08-15 12:41:39 -06:00
let val = self . bank . get_balance ( & pubkey ) ;
2018-08-20 14:20:20 -07:00
Ok ( val )
2018-08-15 12:41:39 -06:00
}
fn get_finality ( & self ) -> Result < usize > {
Ok ( self . bank . finality ( ) )
}
fn get_last_id ( & self ) -> Result < String > {
let id = self . bank . last_id ( ) ;
Ok ( bs58 ::encode ( id ) . into_string ( ) )
}
2018-10-10 14:51:43 -06:00
pub fn get_signature_status ( & self , signature : Signature ) -> result ::Result < ( ) , BankError > {
2018-09-26 17:12:40 -07:00
self . bank . get_signature_status ( & signature )
2018-08-15 12:41:39 -06:00
}
fn get_transaction_count ( & self ) -> Result < u64 > {
Ok ( self . bank . transaction_count ( ) as u64 )
2018-08-10 17:05:23 -06:00
}
2018-10-10 14:51:43 -06:00
pub fn add_account_subscription (
& self ,
bank_sub_id : Pubkey ,
pubkey : Pubkey ,
sink : Sink < Account > ,
) {
self . bank
. add_account_subscription ( bank_sub_id , pubkey , sink ) ;
}
pub fn remove_account_subscription ( & self , bank_sub_id : & Pubkey , pubkey : & Pubkey ) {
self . bank . remove_account_subscription ( bank_sub_id , pubkey ) ;
}
pub fn add_signature_subscription (
& self ,
bank_sub_id : Pubkey ,
signature : Signature ,
sink : Sink < RpcSignatureStatus > ,
) {
self . bank
. add_signature_subscription ( bank_sub_id , signature , sink ) ;
}
pub fn remove_signature_subscription ( & self , bank_sub_id : & Pubkey , signature : & Signature ) {
self . bank
. remove_signature_subscription ( bank_sub_id , signature ) ;
}
2018-08-10 17:05:23 -06:00
}
2018-08-13 11:24:39 -06:00
#[ cfg(test) ]
mod tests {
use super ::* ;
use bank ::Bank ;
2018-08-13 13:59:04 -06:00
use jsonrpc_core ::Response ;
2018-08-13 11:24:39 -06:00
use mint ::Mint ;
use signature ::{ Keypair , KeypairUtil } ;
2018-08-22 11:54:37 -06:00
use std ::net ::{ IpAddr , Ipv4Addr , SocketAddr } ;
2018-08-13 11:24:39 -06:00
use std ::sync ::Arc ;
2018-09-26 10:07:53 -06:00
use system_transaction ::SystemTransaction ;
use transaction ::Transaction ;
2018-08-13 11:24:39 -06:00
#[ test ]
fn test_rpc_request ( ) {
let alice = Mint ::new ( 10_000 ) ;
let bob_pubkey = Keypair ::new ( ) . pubkey ( ) ;
2018-08-14 18:03:48 -06:00
let bank = Bank ::new ( & alice ) ;
let last_id = bank . last_id ( ) ;
2018-09-17 13:36:31 -07:00
let tx = Transaction ::system_move ( & alice . keypair ( ) , bob_pubkey , 20 , last_id , 0 ) ;
2018-08-14 18:03:48 -06:00
bank . process_transaction ( & tx ) . expect ( " process transaction " ) ;
let request_processor = JsonRpcRequestProcessor ::new ( Arc ::new ( bank ) ) ;
2018-08-22 11:53:24 -06:00
let transactions_addr = SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ;
2018-08-22 11:54:37 -06:00
let drone_addr = SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ;
2018-10-10 14:51:43 -06:00
let rpc_addr = SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ;
let exit = Arc ::new ( AtomicBool ::new ( false ) ) ;
2018-08-13 11:24:39 -06:00
let mut io = MetaIoHandler ::default ( ) ;
let rpc = RpcSolImpl ;
io . extend_with ( rpc . to_delegate ( ) ) ;
2018-08-22 11:54:37 -06:00
let meta = Meta {
request_processor ,
transactions_addr ,
drone_addr ,
2018-10-10 14:51:43 -06:00
rpc_addr ,
exit ,
2018-08-22 11:54:37 -06:00
} ;
2018-08-14 18:03:48 -06:00
2018-08-13 11:24:39 -06:00
let req = format! (
2018-08-15 12:41:39 -06:00
r # "{{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["{}"]}}"# ,
2018-08-13 11:24:39 -06:00
bob_pubkey
) ;
let res = io . handle_request_sync ( & req , meta . clone ( ) ) ;
2018-08-20 14:20:20 -07:00
let expected = format! ( r # "{{"jsonrpc":"2.0","result":20,"id":1}}"# ) ;
2018-08-13 11:24:39 -06:00
let expected : Response =
2018-08-14 18:03:48 -06:00
serde_json ::from_str ( & expected ) . expect ( " expected response deserialization " ) ;
2018-08-13 11:24:39 -06:00
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
assert_eq! ( expected , result ) ;
2018-08-15 12:41:39 -06:00
let req = format! ( r # "{{"jsonrpc":"2.0","id":1,"method":"getTransactionCount"}}"# ) ;
2018-08-14 18:03:48 -06:00
let res = io . handle_request_sync ( & req , meta . clone ( ) ) ;
let expected = format! ( r # "{{"jsonrpc":"2.0","result":1,"id":1}}"# ) ;
let expected : Response =
serde_json ::from_str ( & expected ) . expect ( " expected response deserialization " ) ;
2018-08-13 11:24:39 -06:00
2018-08-14 18:03:48 -06:00
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
2018-08-13 11:24:39 -06:00
. expect ( " actual response deserialization " ) ;
2018-08-14 18:03:48 -06:00
assert_eq! ( expected , result ) ;
2018-09-20 13:20:37 -07:00
let req = format! (
2018-09-20 14:51:17 -07:00
r # "{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}"]}}"# ,
2018-09-20 13:20:37 -07:00
bob_pubkey
) ;
let res = io . handle_request_sync ( & req , meta . clone ( ) ) ;
let expected = r #" {
" jsonrpc " :" 2.0 " ,
" result " :{
2018-09-20 20:17:37 -06:00
" program_id " : [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
2018-09-20 13:20:37 -07:00
" tokens " : 20 ,
" userdata " : [ ]
} ,
" id " :1 }
" #;
let expected : Response =
serde_json ::from_str ( & expected ) . expect ( " expected response deserialization " ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
assert_eq! ( expected , result ) ;
2018-08-13 11:24:39 -06:00
}
#[ test ]
fn test_rpc_request_bad_parameter_type ( ) {
2018-08-15 10:37:02 -06:00
let alice = Mint ::new ( 10_000 ) ;
let bank = Bank ::new ( & alice ) ;
2018-08-13 11:24:39 -06:00
let mut io = MetaIoHandler ::default ( ) ;
let rpc = RpcSolImpl ;
io . extend_with ( rpc . to_delegate ( ) ) ;
2018-08-15 12:41:39 -06:00
let req = r # "{"jsonrpc":"2.0","id":1,"method":"confirmTransaction","params":[1234567890]}"# ;
2018-08-13 11:24:39 -06:00
let meta = Meta {
2018-08-15 10:37:02 -06:00
request_processor : JsonRpcRequestProcessor ::new ( Arc ::new ( bank ) ) ,
2018-08-22 11:53:24 -06:00
transactions_addr : SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ,
2018-08-22 11:54:37 -06:00
drone_addr : SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ,
2018-10-10 14:51:43 -06:00
rpc_addr : SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ,
exit : Arc ::new ( AtomicBool ::new ( false ) ) ,
2018-08-13 11:24:39 -06:00
} ;
let res = io . handle_request_sync ( req , meta ) ;
let expected = r # "{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: invalid type: integer `1234567890`, expected a string."},"id":1}"# ;
let expected : Response =
serde_json ::from_str ( expected ) . expect ( " expected response deserialization " ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
assert_eq! ( expected , result ) ;
}
#[ test ]
2018-08-14 18:03:48 -06:00
fn test_rpc_request_bad_signature ( ) {
2018-08-15 10:37:02 -06:00
let alice = Mint ::new ( 10_000 ) ;
let bank = Bank ::new ( & alice ) ;
2018-08-13 11:24:39 -06:00
let mut io = MetaIoHandler ::default ( ) ;
let rpc = RpcSolImpl ;
io . extend_with ( rpc . to_delegate ( ) ) ;
let req =
2018-08-15 12:41:39 -06:00
r # "{"jsonrpc":"2.0","id":1,"method":"confirmTransaction","params":["a1b2c3d4e5"]}"# ;
2018-08-13 11:24:39 -06:00
let meta = Meta {
2018-08-15 10:37:02 -06:00
request_processor : JsonRpcRequestProcessor ::new ( Arc ::new ( bank ) ) ,
2018-08-22 11:53:24 -06:00
transactions_addr : SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ,
2018-08-22 11:54:37 -06:00
drone_addr : SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ,
2018-10-10 14:51:43 -06:00
rpc_addr : SocketAddr ::new ( IpAddr ::V4 ( Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ,
exit : Arc ::new ( AtomicBool ::new ( false ) ) ,
2018-08-13 11:24:39 -06:00
} ;
let res = io . handle_request_sync ( req , meta ) ;
let expected =
r # "{"jsonrpc":"2.0","error":{"code":-32600,"message":"Invalid request"},"id":1}"# ;
let expected : Response =
serde_json ::from_str ( expected ) . expect ( " expected response deserialization " ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
assert_eq! ( expected , result ) ;
}
}