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-08-14 18:03:48 -06:00
use bank ::Bank ;
2018-08-10 17:05:23 -06:00
use bs58 ;
2018-08-13 13:59:04 -06:00
use jsonrpc_core ::* ;
2018-08-14 18:03:48 -06:00
use jsonrpc_http_server ::* ;
use service ::Service ;
use signature ::{ Pubkey , Signature } ;
2018-08-10 17:05:23 -06:00
use std ::mem ;
2018-08-14 18:03:48 -06:00
use std ::net ::SocketAddr ;
2018-08-15 15:11:38 -06:00
use std ::sync ::atomic ::{ AtomicBool , Ordering } ;
2018-08-14 18:03:48 -06:00
use std ::sync ::Arc ;
use std ::thread ::{ self , Builder , JoinHandle } ;
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 {
thread_hdl : JoinHandle < ( ) > ,
}
impl JsonRpcService {
2018-08-15 15:11:38 -06:00
pub fn new ( bank : Arc < Bank > , rpc_addr : SocketAddr , exit : Arc < AtomicBool > ) -> Self {
2018-08-15 12:41:39 -06:00
let request_processor = JsonRpcRequestProcessor ::new ( bank ) ;
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 ( ) ) ;
let server =
ServerBuilder ::with_meta_extractor ( io , move | _req : & hyper ::Request | Meta {
request_processor : request_processor . clone ( ) ,
} ) . threads ( 4 )
2018-08-15 10:37:02 -06:00
. cors ( DomainsValidation ::AllowOnly ( vec! [
AccessControlAllowOrigin ::Any ,
] ) )
2018-08-21 13:43:48 -06:00
. 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 ;
}
2018-08-15 15:11:38 -06:00
loop {
if exit . load ( Ordering ::Relaxed ) {
2018-08-21 13:43:48 -06:00
server . unwrap ( ) . close ( ) ;
2018-08-15 15:11:38 -06:00
break ;
}
}
2018-08-15 12:41:39 -06:00
( )
} )
. unwrap ( ) ;
2018-08-14 18:03:48 -06:00
JsonRpcService { thread_hdl }
}
}
impl Service for JsonRpcService {
fn thread_hdls ( self ) -> Vec < JoinHandle < ( ) > > {
vec! [ self . thread_hdl ]
}
fn join ( self ) -> thread ::Result < ( ) > {
self . thread_hdl . join ( )
}
}
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-10 17:05:23 -06:00
}
impl Metadata for Meta { }
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-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-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-15 12:41:39 -06:00
// #[rpc(meta, name = "sendTransaction")]
2018-08-14 18:03:48 -06:00
// fn send_transaction(&self, Self::Metadata, String, i64) -> Result<String>;
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-08-20 14:20:20 -07:00
let signature_vec = bs58 ::decode ( id )
. into_vec ( )
. map_err ( | _ | Error ::invalid_request ( ) ) ? ;
2018-08-10 17:05:23 -06:00
if signature_vec . len ( ) ! = mem ::size_of ::< Signature > ( ) {
2018-08-15 11:44:00 -06:00
return Err ( Error ::invalid_request ( ) ) ;
}
let signature = Signature ::new ( & signature_vec ) ;
2018-08-15 12:41:39 -06:00
meta . request_processor . get_signature_status ( signature )
2018-08-10 17:05:23 -06:00
}
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-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
}
// fn send_transaction(&self, meta: Self::Metadata, to: String, tokens: i64) -> Result<String> {
// let client_keypair = read_keypair(&meta.keypair_location.unwrap()).unwrap();
// let mut client = mk_client(&meta.leader.unwrap());
// let last_id = client.get_last_id();
// let to_pubkey_vec = bs58::decode(to)
// .into_vec()
// .expect("base58-encoded public key");
//
// if to_pubkey_vec.len() != mem::size_of::<Pubkey>() {
// Err(Error::invalid_request())
// } else {
// let to_pubkey = Pubkey::new(&to_pubkey_vec);
// let signature = client
// .transfer(tokens, &client_keypair, to_pubkey, &last_id)
// .unwrap();
// Ok(bs58::encode(signature).into_string())
// }
// }
}
#[ 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-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 ( ) )
}
fn get_signature_status ( & self , signature : Signature ) -> Result < bool > {
Ok ( self . bank . has_signature ( & signature ) )
}
fn get_transaction_count ( & self ) -> Result < u64 > {
Ok ( self . bank . transaction_count ( ) as u64 )
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 } ;
use std ::sync ::Arc ;
2018-08-14 18:03:48 -06:00
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 ( ) ;
let tx = Transaction ::new ( & alice . keypair ( ) , bob_pubkey , 20 , last_id ) ;
bank . process_transaction ( & tx ) . expect ( " process transaction " ) ;
let request_processor = JsonRpcRequestProcessor ::new ( Arc ::new ( bank ) ) ;
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 15:11:38 -06:00
let meta = Meta { request_processor } ;
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-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-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-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 ) ;
}
}