Use vote signer service in fullnode (#2009)

* Use vote signer service in fullnode

* Use native types for signature and pubkey, and address other review comments

* Start local vote signer if a remote service address is not provided

* Rebased to master

* Fixes after rebase
This commit is contained in:
Pankaj Garg
2019-01-05 12:57:52 -08:00
committed by GitHub
parent 71a2b794b4
commit 91bd38504e
23 changed files with 774 additions and 227 deletions

View File

@@ -9,7 +9,8 @@ use clap::{App, Arg};
use solana_vote_signer::rpc::VoteSignerRpcService;
use std::error;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
pub const RPC_PORT: u16 = 8989;
fn main() -> Result<(), Box<error::Error>> {
@@ -34,8 +35,11 @@ fn main() -> Result<(), Box<error::Error>> {
RPC_PORT
};
let service =
VoteSignerRpcService::new(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), port));
let exit = Arc::new(AtomicBool::new(false));
let service = VoteSignerRpcService::new(
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), port),
exit,
);
service.join().unwrap();

View File

@@ -1,12 +1,10 @@
//! The `rpc` module implements the Vote signing service RPC interface.
use bs58;
use jsonrpc_core::*;
use jsonrpc_http_server::*;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
use std::collections::HashMap;
use std::mem;
use std::net::SocketAddr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock};
@@ -19,9 +17,8 @@ pub struct VoteSignerRpcService {
}
impl VoteSignerRpcService {
pub fn new(rpc_addr: SocketAddr) -> Self {
pub fn new(rpc_addr: SocketAddr, exit: Arc<AtomicBool>) -> Self {
let request_processor = VoteSignRequestProcessor::default();
let exit = Arc::new(AtomicBool::new(false));
let exit_ = exit.clone();
let thread_hdl = Builder::new()
.name("solana-vote-signer-jsonrpc".to_string())
@@ -76,13 +73,13 @@ build_rpc_trait! {
type Metadata;
#[rpc(meta, name = "registerNode")]
fn register(&self, Self::Metadata, String, Signature, Vec<u8>) -> Result<Pubkey>;
fn register(&self, Self::Metadata, Pubkey, Signature, Vec<u8>) -> Result<Pubkey>;
#[rpc(meta, name = "signVote")]
fn sign(&self, Self::Metadata, String, Signature, Vec<u8>) -> Result<Signature>;
fn sign(&self, Self::Metadata, Pubkey, Signature, Vec<u8>) -> Result<Signature>;
#[rpc(meta, name = "deregisterNode")]
fn deregister(&self, Self::Metadata, String, Signature, Vec<u8>) -> Result<()>;
fn deregister(&self, Self::Metadata, Pubkey, Signature, Vec<u8>) -> Result<()>;
}
}
@@ -93,40 +90,37 @@ impl VoteSignerRpc for VoteSignerRpcImpl {
fn register(
&self,
meta: Self::Metadata,
id: String,
id: Pubkey,
sig: Signature,
signed_msg: Vec<u8>,
) -> Result<Pubkey> {
info!("register rpc request received: {:?}", id);
let pubkey = verify_pubkey(id)?;
verify_signature(&sig, &pubkey, &signed_msg)?;
meta.request_processor.register(pubkey)
verify_signature(&sig, &id, &signed_msg)?;
meta.request_processor.register(id)
}
fn sign(
&self,
meta: Self::Metadata,
id: String,
id: Pubkey,
sig: Signature,
signed_msg: Vec<u8>,
) -> Result<Signature> {
info!("sign rpc request received: {:?}", id);
let pubkey = verify_pubkey(id)?;
verify_signature(&sig, &pubkey, &signed_msg)?;
meta.request_processor.sign(pubkey, &signed_msg)
verify_signature(&sig, &id, &signed_msg)?;
meta.request_processor.sign(id, &signed_msg)
}
fn deregister(
&self,
meta: Self::Metadata,
id: String,
id: Pubkey,
sig: Signature,
signed_msg: Vec<u8>,
) -> Result<()> {
info!("deregister rpc request received: {:?}", id);
let pubkey = verify_pubkey(id)?;
verify_signature(&sig, &pubkey, &signed_msg)?;
meta.request_processor.deregister(pubkey)
verify_signature(&sig, &id, &signed_msg)?;
meta.request_processor.deregister(id)
}
}
@@ -154,6 +148,7 @@ impl VoteSignRequestProcessor {
let voting_pubkey = voting_keypair.pubkey();
self.nodes.write().unwrap().insert(pubkey, voting_keypair);
Ok(voting_pubkey)
//Ok(bs58::encode(voting_pubkey).into_string())
}
pub fn sign(&self, pubkey: Pubkey, msg: &[u8]) -> Result<Signature> {
match self.nodes.read().unwrap().get(&pubkey) {
@@ -178,27 +173,12 @@ impl Default for VoteSignRequestProcessor {
}
}
fn verify_pubkey(input: String) -> Result<Pubkey> {
let pubkey_vec = bs58::decode(input).into_vec().map_err(|err| {
info!("verify_pubkey: invalid input: {:?}", err);
Error::invalid_request()
})?;
if pubkey_vec.len() != mem::size_of::<Pubkey>() {
info!(
"verify_pubkey: invalid pubkey_vec length: {}",
pubkey_vec.len()
);
Err(Error::invalid_request())
} else {
Ok(Pubkey::new(&pubkey_vec))
}
}
#[cfg(test)]
mod tests {
use super::*;
use jsonrpc_core::Response;
use solana_sdk::signature::{Keypair, KeypairUtil};
use std::mem;
fn start_rpc_handler() -> (MetaIoHandler<Meta>, Meta) {
let request_processor = VoteSignRequestProcessor::default();
@@ -221,7 +201,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "registerNode",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let res = io.handle_request_sync(&req.to_string(), meta);
@@ -232,11 +212,11 @@ mod tests {
if let Output::Success(succ) = out {
assert_eq!(succ.jsonrpc.unwrap(), Version::V2);
assert_eq!(succ.id, Id::Num(1));
assert!(succ.result.is_array());
assert_eq!(
succ.result.as_array().unwrap().len(),
mem::size_of::<Pubkey>()
);
let _pk: Pubkey = serde_json::from_value(succ.result).unwrap();
} else {
assert!(false);
}
@@ -258,7 +238,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "registerNode",
"params": [node_pubkey.to_string(), sig, msg1.as_bytes()],
"params": [node_pubkey, sig, msg1.as_bytes()],
});
let res = io.handle_request_sync(&req.to_string(), meta);
@@ -289,7 +269,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "deregisterNode",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let res = io.handle_request_sync(&req.to_string(), meta);
@@ -321,7 +301,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "deregisterNode",
"params": [node_pubkey.to_string(), sig, msg1.as_bytes()],
"params": [node_pubkey, sig, msg1.as_bytes()],
});
let res = io.handle_request_sync(&req.to_string(), meta);
@@ -353,15 +333,33 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "registerNode",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
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);
}
let req = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "signVote",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let res = io.handle_request_sync(&req.to_string(), meta);
@@ -372,6 +370,12 @@ mod tests {
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::<Signature>()
);
let sig: Signature = serde_json::from_value(succ.result).unwrap();
assert_eq!(verify_signature(&sig, &vote_pubkey, msg.as_bytes()), Ok(()));
} else {
assert!(false);
}
@@ -392,7 +396,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "signVote",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let res = io.handle_request_sync(&req.to_string(), meta);
@@ -424,7 +428,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "registerNode",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
@@ -432,7 +436,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "deregisterNode",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
@@ -440,7 +444,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "signVote",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let res = io.handle_request_sync(&req.to_string(), meta);
@@ -473,7 +477,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "registerNode",
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
"params": [node_pubkey, sig, msg.as_bytes()],
});
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
@@ -481,7 +485,7 @@ mod tests {
"jsonrpc": "2.0",
"id": 1,
"method": "signVote",
"params": [node_pubkey.to_string(), sig, msg1.as_bytes()],
"params": [node_pubkey, sig, msg1.as_bytes()],
});
let res = io.handle_request_sync(&req.to_string(), meta);