1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#![allow(missing_docs)]
use crate::{
prost::encoding::{decode_varint, encoded_len_varint},
prost::Message,
};
use bytes::IntoBuf;
use lazy_static::lazy_static;
use sha2::{Digest, Sha256};
use std::io::Cursor;
use std::io::{self, Read};
use std::io::{Error, ErrorKind};
use tendermint::amino_types::*;
pub const MAX_MSG_LEN: usize = 1024;
#[derive(Debug)]
pub enum Request {
SignProposal(SignProposalRequest),
SignVote(SignVoteRequest),
ShowPublicKey(PubKeyRequest),
ReplyPing(PingRequest),
}
#[derive(Debug)]
pub enum Response {
SignedVote(SignedVoteResponse),
SignedProposal(SignedProposalResponse),
Ping(PingResponse),
PublicKey(PubKeyResponse),
}
pub trait TendermintRequest: SignableMsg {
fn build_response(self, error: Option<RemoteError>) -> Response;
}
fn compute_prefix(name: &str) -> (Vec<u8>) {
let mut sh = Sha256::default();
sh.input(name.as_bytes());
let output = sh.result();
let prefix_bytes: Vec<u8> = output
.iter()
.filter(|&x| *x != 0x00)
.skip(3)
.filter(|&x| *x != 0x00)
.cloned()
.take(4)
.collect();
prefix_bytes
}
lazy_static! {
static ref VOTE_PREFIX: Vec<u8> = compute_prefix(VOTE_AMINO_NAME);
static ref PROPOSAL_PREFIX: Vec<u8> = compute_prefix(PROPOSAL_AMINO_NAME);
static ref PUBKEY_PREFIX: Vec<u8> = compute_prefix(PUBKEY_AMINO_NAME);
static ref PING_PREFIX: Vec<u8> = compute_prefix(PING_AMINO_NAME);
}
impl Request {
pub fn read<R: Read>(r: &mut R) -> io::Result<Self> {
let mut buf = vec![0; MAX_MSG_LEN];
let bytes_read = r.read(&mut buf)?;
if bytes_read < 4 {
return Err(Error::new(
ErrorKind::InvalidData,
"Did not read enough bytes to continue.",
));
}
let buff: &mut Cursor<Vec<u8>> = &mut buf.into_buf();
let len = decode_varint(buff).unwrap();
if len > MAX_MSG_LEN as u64 {
return Err(Error::new(ErrorKind::InvalidData, "RPC message too large."));
}
let mut amino_pre = vec![0; 4];
buff.read_exact(&mut amino_pre)?;
buff.set_position(0);
let total_len = encoded_len_varint(len).checked_add(len as usize).unwrap();
let rem = buff.get_ref()[..total_len].to_vec();
match amino_pre {
ref vt if *vt == *VOTE_PREFIX => Ok(Request::SignVote(SignVoteRequest::decode(&rem)?)),
ref pr if *pr == *PROPOSAL_PREFIX => {
Ok(Request::SignProposal(SignProposalRequest::decode(&rem)?))
}
ref pubk if *pubk == *PUBKEY_PREFIX => {
Ok(Request::ShowPublicKey(PubKeyRequest::decode(&rem)?))
}
ref ping if *ping == *PING_PREFIX => Ok(Request::ReplyPing(PingRequest::decode(&rem)?)),
_ => Err(Error::new(
ErrorKind::InvalidData,
"Received unknown RPC message.",
)),
}
}
}
impl TendermintRequest for SignVoteRequest {
fn build_response(self, error: Option<RemoteError>) -> Response {
let response = if let Some(e) = error {
SignedVoteResponse {
vote: None,
err: Some(e),
}
} else {
SignedVoteResponse {
vote: self.vote,
err: None,
}
};
Response::SignedVote(response)
}
}
impl TendermintRequest for SignProposalRequest {
fn build_response(self, error: Option<RemoteError>) -> Response {
let response = if let Some(e) = error {
SignedProposalResponse {
proposal: None,
err: Some(e),
}
} else {
SignedProposalResponse {
proposal: self.proposal,
err: None,
}
};
Response::SignedProposal(response)
}
}