2018-11-30 15:07:08 -08:00
//! The `rpc` module implements the Vote signing service RPC interface.
2019-02-04 17:00:10 -07:00
use jsonrpc_core ::{ Error , MetaIoHandler , Metadata , Result } ;
use jsonrpc_derive ::rpc ;
use jsonrpc_http_server ::{ hyper , AccessControlAllowOrigin , DomainsValidation , ServerBuilder } ;
2018-11-30 15:07:08 -08:00
use solana_sdk ::pubkey ::Pubkey ;
2018-12-04 11:10:57 -08:00
use solana_sdk ::signature ::{ Keypair , KeypairUtil , Signature } ;
use std ::collections ::HashMap ;
2018-11-30 15:07:08 -08:00
use std ::net ::SocketAddr ;
use std ::sync ::atomic ::{ AtomicBool , Ordering } ;
2018-12-04 11:10:57 -08:00
use std ::sync ::{ Arc , RwLock } ;
2018-11-30 15:07:08 -08:00
use std ::thread ::{ self , sleep , Builder , JoinHandle } ;
use std ::time ::Duration ;
pub struct VoteSignerRpcService {
thread_hdl : JoinHandle < ( ) > ,
exit : Arc < AtomicBool > ,
}
impl VoteSignerRpcService {
2019-01-05 12:57:52 -08:00
pub fn new ( rpc_addr : SocketAddr , exit : Arc < AtomicBool > ) -> Self {
2019-01-11 12:58:31 -08:00
let request_processor = LocalVoteSigner ::default ( ) ;
2018-11-30 15:07:08 -08:00
let exit_ = exit . clone ( ) ;
let thread_hdl = Builder ::new ( )
. name ( " solana-vote-signer-jsonrpc " . to_string ( ) )
. spawn ( move | | {
let mut io = MetaIoHandler ::default ( ) ;
let rpc = VoteSignerRpcImpl ;
io . extend_with ( rpc . to_delegate ( ) ) ;
let server =
ServerBuilder ::with_meta_extractor ( io , move | _req : & hyper ::Request < hyper ::Body > | Meta {
request_processor : request_processor . clone ( ) ,
} ) . 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 ;
}
while ! exit_ . load ( Ordering ::Relaxed ) {
sleep ( Duration ::from_millis ( 100 ) ) ;
}
server . unwrap ( ) . close ( ) ;
} )
. unwrap ( ) ;
2018-12-07 20:01:28 -07:00
Self { thread_hdl , exit }
2018-11-30 15:07:08 -08:00
}
pub fn exit ( & self ) {
self . exit . store ( true , Ordering ::Relaxed ) ;
}
pub fn close ( self ) -> thread ::Result < ( ) > {
self . exit ( ) ;
self . join ( )
}
pub fn join ( self ) -> thread ::Result < ( ) > {
self . thread_hdl . join ( )
}
}
#[ derive(Clone) ]
pub struct Meta {
2019-01-11 12:58:31 -08:00
pub request_processor : LocalVoteSigner ,
2018-11-30 15:07:08 -08:00
}
impl Metadata for Meta { }
2019-02-04 17:00:10 -07:00
#[ rpc ]
pub trait VoteSignerRpc {
type Metadata ;
2018-11-30 15:07:08 -08:00
2019-02-04 17:00:10 -07:00
#[ rpc(meta, name = " registerNode " ) ]
fn register ( & self , _ : Self ::Metadata , _ : Pubkey , _ : Signature , _ : Vec < u8 > ) -> Result < Pubkey > ;
2018-11-30 15:07:08 -08:00
2019-02-04 17:00:10 -07:00
#[ rpc(meta, name = " signVote " ) ]
fn sign ( & self , _ : Self ::Metadata , _ : Pubkey , _ : Signature , _ : Vec < u8 > ) -> Result < Signature > ;
2018-11-30 15:07:08 -08:00
2019-02-04 17:00:10 -07:00
#[ rpc(meta, name = " deregisterNode " ) ]
fn deregister ( & self , _ : Self ::Metadata , _ : Pubkey , _ : Signature , _ : Vec < u8 > ) -> Result < ( ) > ;
2018-11-30 15:07:08 -08:00
}
pub struct VoteSignerRpcImpl ;
impl VoteSignerRpc for VoteSignerRpcImpl {
type Metadata = Meta ;
2018-12-04 11:10:57 -08:00
fn register (
& self ,
meta : Self ::Metadata ,
2019-01-05 12:57:52 -08:00
id : Pubkey ,
2018-12-04 11:10:57 -08:00
sig : Signature ,
signed_msg : Vec < u8 > ,
) -> Result < Pubkey > {
2018-11-30 15:07:08 -08:00
info! ( " register rpc request received: {:?} " , id ) ;
2019-01-11 12:58:31 -08:00
meta . request_processor . register ( id , & sig , & signed_msg )
2018-11-30 15:07:08 -08:00
}
2018-12-04 11:10:57 -08:00
fn sign (
& self ,
meta : Self ::Metadata ,
2019-01-05 12:57:52 -08:00
id : Pubkey ,
2018-12-04 11:10:57 -08:00
sig : Signature ,
signed_msg : Vec < u8 > ,
) -> Result < Signature > {
2018-11-30 15:07:08 -08:00
info! ( " sign rpc request received: {:?} " , id ) ;
2019-01-11 12:58:31 -08:00
meta . request_processor . sign ( id , & sig , & signed_msg )
2018-11-30 15:07:08 -08:00
}
2018-12-04 11:10:57 -08:00
fn deregister (
& self ,
meta : Self ::Metadata ,
2019-01-05 12:57:52 -08:00
id : Pubkey ,
2018-12-04 11:10:57 -08:00
sig : Signature ,
signed_msg : Vec < u8 > ,
) -> Result < ( ) > {
2018-11-30 15:07:08 -08:00
info! ( " deregister rpc request received: {:?} " , id ) ;
2019-01-11 12:58:31 -08:00
meta . request_processor . deregister ( id , & sig , & signed_msg )
2018-11-30 15:07:08 -08:00
}
}
2018-12-04 11:10:57 -08:00
fn verify_signature ( sig : & Signature , pubkey : & Pubkey , msg : & [ u8 ] ) -> Result < ( ) > {
if sig . verify ( pubkey . as_ref ( ) , msg ) {
Ok ( ( ) )
} else {
Err ( Error ::invalid_request ( ) )
}
}
2019-01-11 12:58:31 -08:00
pub trait VoteSigner {
fn register ( & self , pubkey : Pubkey , sig : & Signature , signed_msg : & [ u8 ] ) -> Result < Pubkey > ;
fn sign ( & self , pubkey : Pubkey , sig : & Signature , msg : & [ u8 ] ) -> Result < Signature > ;
fn deregister ( & self , pubkey : Pubkey , sig : & Signature , msg : & [ u8 ] ) -> Result < ( ) > ;
}
2018-12-04 11:10:57 -08:00
#[ derive(Clone) ]
2019-01-11 12:58:31 -08:00
pub struct LocalVoteSigner {
2018-12-04 11:10:57 -08:00
nodes : Arc < RwLock < HashMap < Pubkey , Keypair > > > ,
}
2019-01-11 12:58:31 -08:00
impl VoteSigner for LocalVoteSigner {
2018-11-30 15:07:08 -08:00
/// Process JSON-RPC request items sent via JSON-RPC.
2019-01-11 12:58:31 -08:00
fn register ( & self , pubkey : Pubkey , sig : & Signature , msg : & [ u8 ] ) -> Result < Pubkey > {
verify_signature ( & sig , & pubkey , & msg ) ? ;
2018-12-04 11:10:57 -08:00
{
if let Some ( voting_keypair ) = self . nodes . read ( ) . unwrap ( ) . get ( & pubkey ) {
return Ok ( voting_keypair . pubkey ( ) ) ;
}
}
let voting_keypair = Keypair ::new ( ) ;
let voting_pubkey = voting_keypair . pubkey ( ) ;
self . nodes . write ( ) . unwrap ( ) . insert ( pubkey , voting_keypair ) ;
Ok ( voting_pubkey )
2018-11-30 15:07:08 -08:00
}
2019-01-11 12:58:31 -08:00
fn sign ( & self , pubkey : Pubkey , sig : & Signature , msg : & [ u8 ] ) -> Result < Signature > {
verify_signature ( & sig , & pubkey , & msg ) ? ;
2018-12-04 11:10:57 -08:00
match self . nodes . read ( ) . unwrap ( ) . get ( & pubkey ) {
2019-01-25 23:41:20 -07:00
Some ( voting_keypair ) = > Ok ( voting_keypair . sign_message ( & msg ) ) ,
2018-12-04 11:10:57 -08:00
None = > Err ( Error ::invalid_request ( ) ) ,
}
2018-11-30 15:07:08 -08:00
}
2019-01-11 12:58:31 -08:00
fn deregister ( & self , pubkey : Pubkey , sig : & Signature , msg : & [ u8 ] ) -> Result < ( ) > {
verify_signature ( & sig , & pubkey , & msg ) ? ;
2018-12-04 11:10:57 -08:00
self . nodes . write ( ) . unwrap ( ) . remove ( & pubkey ) ;
2018-11-30 15:07:08 -08:00
Ok ( ( ) )
}
}
2019-01-11 12:58:31 -08:00
impl Default for LocalVoteSigner {
2018-12-04 11:10:57 -08:00
fn default ( ) -> Self {
2019-01-11 12:58:31 -08:00
LocalVoteSigner {
2018-12-04 11:10:57 -08:00
nodes : Arc ::new ( RwLock ::new ( HashMap ::new ( ) ) ) ,
}
}
}
2018-11-30 15:07:08 -08:00
#[ cfg(test) ]
2018-12-04 11:10:57 -08:00
mod tests {
use super ::* ;
2019-02-04 17:41:03 -07:00
use jsonrpc_core ::{ types ::* , Response } ;
2018-12-04 11:10:57 -08:00
use solana_sdk ::signature ::{ Keypair , KeypairUtil } ;
2019-01-05 12:57:52 -08:00
use std ::mem ;
2018-12-04 11:10:57 -08:00
fn start_rpc_handler ( ) -> ( MetaIoHandler < Meta > , Meta ) {
2019-01-11 12:58:31 -08:00
let request_processor = LocalVoteSigner ::default ( ) ;
2018-12-04 11:10:57 -08:00
let mut io = MetaIoHandler ::default ( ) ;
let rpc = VoteSignerRpcImpl ;
io . extend_with ( rpc . to_delegate ( ) ) ;
let meta = Meta { request_processor } ;
( io , meta )
}
#[ test ]
fn test_rpc_register_node ( ) {
let ( io , meta ) = start_rpc_handler ( ) ;
let node_keypair = Keypair ::new ( ) ;
let node_pubkey = node_keypair . pubkey ( ) ;
let msg = " This is a test " ;
2019-01-25 23:41:20 -07:00
let sig = node_keypair . sign_message ( msg . as_bytes ( ) ) ;
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " registerNode " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let res = io . handle_request_sync ( & req . to_string ( ) , meta ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
if let Response ::Single ( out ) = result {
if let Output ::Success ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
assert_eq! (
succ . result . as_array ( ) . unwrap ( ) . len ( ) ,
mem ::size_of ::< Pubkey > ( )
) ;
2019-01-05 12:57:52 -08:00
let _pk : Pubkey = serde_json ::from_value ( succ . result ) . unwrap ( ) ;
2018-12-04 11:10:57 -08:00
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
}
#[ test ]
fn test_rpc_register_node_invalid_sig ( ) {
let ( io , meta ) = start_rpc_handler ( ) ;
let node_keypair = Keypair ::new ( ) ;
let node_pubkey = node_keypair . pubkey ( ) ;
let msg = " This is a test " ;
let msg1 = " This is a Test1 " ;
2019-01-25 23:41:20 -07:00
let sig = node_keypair . sign_message ( msg . as_bytes ( ) ) ;
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " registerNode " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg1 . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let res = io . handle_request_sync ( & req . to_string ( ) , meta ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
if let Response ::Single ( out ) = result {
if let Output ::Failure ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
}
#[ test ]
fn test_rpc_deregister_node ( ) {
let ( io , meta ) = start_rpc_handler ( ) ;
let node_keypair = Keypair ::new ( ) ;
let node_pubkey = node_keypair . pubkey ( ) ;
let msg = " This is a test " ;
2019-01-25 23:41:20 -07:00
let sig = node_keypair . sign_message ( msg . as_bytes ( ) ) ;
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " deregisterNode " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let res = io . handle_request_sync ( & req . to_string ( ) , meta ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
if let Response ::Single ( out ) = result {
if let Output ::Success ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
}
#[ test ]
fn test_rpc_deregister_node_invalid_sig ( ) {
let ( io , meta ) = start_rpc_handler ( ) ;
let node_keypair = Keypair ::new ( ) ;
let node_pubkey = node_keypair . pubkey ( ) ;
let msg = " This is a test " ;
let msg1 = " This is a Test1 " ;
2019-01-25 23:41:20 -07:00
let sig = node_keypair . sign_message ( msg . as_bytes ( ) ) ;
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " deregisterNode " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg1 . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let res = io . handle_request_sync ( & req . to_string ( ) , meta ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
if let Response ::Single ( out ) = result {
if let Output ::Failure ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
}
#[ test ]
fn test_rpc_sign_vote ( ) {
let ( io , meta ) = start_rpc_handler ( ) ;
let node_keypair = Keypair ::new ( ) ;
let node_pubkey = node_keypair . pubkey ( ) ;
let msg = " This is a test " ;
2019-01-25 23:41:20 -07:00
let sig = node_keypair . sign_message ( msg . as_bytes ( ) ) ;
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " registerNode " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
2019-01-05 12:57:52 -08:00
let res = io . handle_request_sync ( & req . to_string ( ) , meta . clone ( ) ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
let mut vote_pubkey = Keypair ::new ( ) . pubkey ( ) ;
if let Response ::Single ( out ) = result {
if let Output ::Success ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
assert_eq! (
succ . result . as_array ( ) . unwrap ( ) . len ( ) ,
mem ::size_of ::< Pubkey > ( )
) ;
vote_pubkey = serde_json ::from_value ( succ . result ) . unwrap ( ) ;
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " signVote " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let res = io . handle_request_sync ( & req . to_string ( ) , meta ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
if let Response ::Single ( out ) = result {
if let Output ::Success ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
2019-01-05 12:57:52 -08:00
assert_eq! (
succ . result . as_array ( ) . unwrap ( ) . len ( ) ,
mem ::size_of ::< Signature > ( )
) ;
let sig : Signature = serde_json ::from_value ( succ . result ) . unwrap ( ) ;
assert_eq! ( verify_signature ( & sig , & vote_pubkey , msg . as_bytes ( ) ) , Ok ( ( ) ) ) ;
2018-12-04 11:10:57 -08:00
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
}
#[ test ]
fn test_rpc_sign_vote_before_register ( ) {
let ( io , meta ) = start_rpc_handler ( ) ;
let node_keypair = Keypair ::new ( ) ;
let node_pubkey = node_keypair . pubkey ( ) ;
let msg = " This is a test " ;
2019-01-25 23:41:20 -07:00
let sig = node_keypair . sign_message ( msg . as_bytes ( ) ) ;
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " signVote " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let res = io . handle_request_sync ( & req . to_string ( ) , meta ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
if let Response ::Single ( out ) = result {
if let Output ::Failure ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
}
#[ test ]
fn test_rpc_sign_vote_after_deregister ( ) {
let ( io , meta ) = start_rpc_handler ( ) ;
let node_keypair = Keypair ::new ( ) ;
let node_pubkey = node_keypair . pubkey ( ) ;
let msg = " This is a test " ;
2019-01-25 23:41:20 -07:00
let sig = node_keypair . sign_message ( msg . as_bytes ( ) ) ;
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " registerNode " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let _res = io . handle_request_sync ( & req . to_string ( ) , meta . clone ( ) ) ;
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " deregisterNode " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let _res = io . handle_request_sync ( & req . to_string ( ) , meta . clone ( ) ) ;
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " signVote " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let res = io . handle_request_sync ( & req . to_string ( ) , meta ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
if let Response ::Single ( out ) = result {
if let Output ::Failure ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
}
#[ test ]
fn test_rpc_sign_vote_invalid_sig ( ) {
let ( io , meta ) = start_rpc_handler ( ) ;
let node_keypair = Keypair ::new ( ) ;
let node_pubkey = node_keypair . pubkey ( ) ;
let msg = " This is a test " ;
let msg1 = " This is a Test " ;
2019-01-25 23:41:20 -07:00
let sig = node_keypair . sign_message ( msg . as_bytes ( ) ) ;
2018-12-04 11:10:57 -08:00
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " registerNode " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let _res = io . handle_request_sync ( & req . to_string ( ) , meta . clone ( ) ) ;
let req = json! ( {
" jsonrpc " : " 2.0 " ,
" id " : 1 ,
" method " : " signVote " ,
2019-01-05 12:57:52 -08:00
" params " : [ node_pubkey , sig , msg1 . as_bytes ( ) ] ,
2018-12-04 11:10:57 -08:00
} ) ;
let res = io . handle_request_sync ( & req . to_string ( ) , meta ) ;
let result : Response = serde_json ::from_str ( & res . expect ( " actual response " ) )
. expect ( " actual response deserialization " ) ;
if let Response ::Single ( out ) = result {
if let Output ::Failure ( succ ) = out {
assert_eq! ( succ . jsonrpc . unwrap ( ) , Version ::V2 ) ;
assert_eq! ( succ . id , Id ::Num ( 1 ) ) ;
} else {
assert! ( false ) ;
}
} else {
assert! ( false ) ;
}
}
}