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:
@@ -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();
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user