diff --git a/src/commands/ledger.rs b/src/commands/ledger.rs index 9b3f6f9b..992008b3 100644 --- a/src/commands/ledger.rs +++ b/src/commands/ledger.rs @@ -8,6 +8,7 @@ use crate::{ use abscissa_core::{Command, Runnable}; use clap::{Parser, Subcommand}; use std::{path::PathBuf, process}; +use tendermint::Vote; use tendermint_proto as proto; /// `ledger` subcommand @@ -61,7 +62,7 @@ impl Runnable for InitCommand { ..Default::default() }; println!("{vote:?}"); - let sign_vote_req = SignableMsg::try_from(vote).unwrap(); + let sign_vote_req = SignableMsg::from(Vote::try_from(vote).unwrap()); let to_sign = sign_vote_req .signable_bytes(config.validator[0].chain_id.clone()) .unwrap(); diff --git a/src/privval.rs b/src/privval.rs index 4fc5b8f7..1c731452 100644 --- a/src/privval.rs +++ b/src/privval.rs @@ -107,6 +107,18 @@ impl SignableMsg { } } +impl From for SignableMsg { + fn from(proposal: Proposal) -> Self { + Self::Proposal(proposal) + } +} + +impl From for SignableMsg { + fn from(vote: Vote) -> Self { + Self::Vote(vote) + } +} + impl TryFrom for SignableMsg { type Error = Error; @@ -205,7 +217,7 @@ impl TryFrom for SignedMsgType { #[cfg(test)] mod tests { use super::{chain, proto, SignableMsg, SignedMsgType}; - use tendermint::Time; + use tendermint::{Proposal, Time, Vote}; fn example_chain_id() -> chain::Id { chain::Id::try_from("test_chain_id").unwrap() @@ -220,7 +232,7 @@ mod tests { } } - fn example_proposal() -> proto::types::Proposal { + fn example_proposal() -> Proposal { proto::types::Proposal { r#type: SignedMsgType::Proposal.into(), height: 12345, @@ -230,9 +242,11 @@ mod tests { block_id: None, signature: vec![], } + .try_into() + .unwrap() } - fn example_vote() -> proto::types::Vote { + fn example_vote() -> Vote { proto::types::Vote { r#type: 0x01, height: 500001, @@ -254,6 +268,8 @@ mod tests { extension: vec![], extension_signature: vec![], } + .try_into() + .unwrap() } #[test] diff --git a/src/rpc.rs b/src/rpc.rs index 3123aecc..f9331366 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -6,7 +6,7 @@ use crate::{keyring::Signature, privval::SignableMsg}; use prost::Message as _; use std::io::Read; -use tendermint::chain; +use tendermint::{chain, Proposal, Vote}; use tendermint_proto as proto; // TODO(tarcieri): use `tendermint_p2p::secret_connection::DATA_MAX_SIZE` @@ -22,66 +22,68 @@ use crate::{ #[derive(Debug)] pub enum Request { /// Sign the given message - SignProposal(proto::privval::SignProposalRequest), - SignVote(proto::privval::SignVoteRequest), - ShowPublicKey(proto::privval::PubKeyRequest), - ReplyPing(proto::privval::PingRequest), + SignProposal(Proposal), + SignVote(Vote), + ShowPublicKey, + PingRequest, } impl Request { /// Read a request from the given readable. - pub fn read(conn: &mut impl Read) -> Result { - let msg = read_msg(conn)?; + pub fn read(conn: &mut impl Read, expected_chain_id: &chain::Id) -> Result { + let msg_bytes = read_msg(conn)?; // Parse Protobuf-encoded request message - let msg = proto::privval::Message::decode_length_delimited(msg.as_ref()) + let msg = proto::privval::Message::decode_length_delimited(msg_bytes.as_ref()) .map_err(|e| format_err!(ErrorKind::ProtocolError, "malformed message packet: {}", e))? .sum; - match msg { - Some(proto::privval::message::Sum::SignVoteRequest(req)) => Ok(Request::SignVote(req)), - Some(proto::privval::message::Sum::SignProposalRequest(req)) => { - Ok(Request::SignProposal(req)) - } + let (req, chain_id) = match msg { + Some(proto::privval::message::Sum::SignVoteRequest( + proto::privval::SignVoteRequest { + vote: Some(vote), + chain_id, + }, + )) => (Request::SignVote(vote.try_into()?), chain_id), + Some(proto::privval::message::Sum::SignProposalRequest( + proto::privval::SignProposalRequest { + proposal: Some(proposal), + chain_id, + }, + )) => (Request::SignProposal(proposal.try_into()?), chain_id), Some(proto::privval::message::Sum::PubKeyRequest(req)) => { - Ok(Request::ShowPublicKey(req)) + (Request::ShowPublicKey, req.chain_id) + } + Some(proto::privval::message::Sum::PingRequest(_)) => { + return Ok(Request::PingRequest); } - Some(proto::privval::message::Sum::PingRequest(req)) => Ok(Request::ReplyPing(req)), _ => fail!(ErrorKind::ProtocolError, "invalid RPC message: {:?}", msg), - } + }; + + ensure!( + expected_chain_id == &chain::Id::try_from(chain_id.as_str())?, + ErrorKind::ChainIdError, + "got unexpected chain ID: {} (expecting: {})", + &chain_id, + expected_chain_id + ); + + Ok(req) } /// Convert this request into a [`SignableMsg`]. /// /// The expected `chain::Id` is used to validate the request. - pub fn into_signable_msg(self, expected_chain_id: &chain::Id) -> Result { - let (signable_msg, chain_id) = match self { - Self::SignProposal(proto::privval::SignProposalRequest { - proposal: Some(proposal), - chain_id, - }) => (SignableMsg::try_from(proposal)?, chain_id), - Self::SignVote(proto::privval::SignVoteRequest { - vote: Some(vote), - chain_id, - }) => (SignableMsg::try_from(vote)?, chain_id), + pub fn into_signable_msg(self) -> Result { + match self { + Self::SignProposal(proposal) => Ok(proposal.into()), + Self::SignVote(vote) => Ok(vote.into()), _ => fail!( ErrorKind::InvalidMessageError, "expected a signable message type: {:?}", self ), - }; - - let chain_id = chain::Id::try_from(chain_id)?; - - ensure!( - expected_chain_id == &chain_id, - ErrorKind::ChainIdError, - "got unexpected chain ID: {} (expecting: {})", - &chain_id, - expected_chain_id - ); - - Ok(signable_msg) + } } } diff --git a/src/session.rs b/src/session.rs index 7301f8c4..31b0e8f0 100644 --- a/src/session.rs +++ b/src/session.rs @@ -96,7 +96,7 @@ impl Session { /// Handle an incoming request from the validator fn handle_request(&mut self) -> Result { - let request = Request::read(&mut self.connection)?; + let request = Request::read(&mut self.connection, &self.config.chain_id)?; debug!( "[{}@{}] received request: {:?}", &self.config.chain_id, &self.config.addr, &request @@ -104,11 +104,11 @@ impl Session { let response = match request { Request::SignProposal(_) | Request::SignVote(_) => { - self.sign(request.into_signable_msg(&self.config.chain_id)?)? + self.sign(request.into_signable_msg()?)? } // non-signable requests: - Request::ReplyPing(_) => Response::Ping(proto::privval::PingResponse {}), - Request::ShowPublicKey(ref req) => self.get_public_key(req)?, + Request::PingRequest => Response::Ping(proto::privval::PingResponse {}), + Request::ShowPublicKey => self.get_public_key()?, }; debug!( @@ -203,10 +203,7 @@ impl Session { } /// Get the public key for (the only) public key in the keyring - fn get_public_key( - &mut self, - _request: &proto::privval::PubKeyRequest, - ) -> Result { + fn get_public_key(&mut self) -> Result { let registry = chain::REGISTRY.get(); let chain = registry