abci/
types.rs

1//! Types used in ABCI
2pub use prost_types::{Duration, Timestamp};
3pub use tendermint_proto::{
4    abci::{
5        response_apply_snapshot_chunk::Result as ApplySnapshotChunkResult,
6        response_offer_snapshot::Result as OfferSnapshotResult, BlockParams, CheckTxType,
7        ConsensusParams, Event, EventAttribute, Evidence, LastCommitInfo,
8        RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, RequestCommit,
9        RequestDeliverTx, RequestEcho, RequestEndBlock, RequestFlush, RequestInfo,
10        RequestInitChain, RequestListSnapshots, RequestLoadSnapshotChunk, RequestOfferSnapshot,
11        RequestQuery, RequestSetOption, ResponseApplySnapshotChunk, ResponseBeginBlock,
12        ResponseCheckTx, ResponseCommit, ResponseDeliverTx, ResponseEcho, ResponseEndBlock,
13        ResponseFlush, ResponseInfo, ResponseInitChain, ResponseListSnapshots,
14        ResponseLoadSnapshotChunk, ResponseOfferSnapshot, ResponseQuery, ResponseSetOption,
15        Snapshot, Validator, ValidatorUpdate, VoteInfo,
16    },
17    crypto::{public_key::Sum, ProofOp, ProofOps, PublicKey},
18    types::{BlockId, EvidenceParams, Header, PartSetHeader, ValidatorParams, VersionParams},
19    version::Consensus,
20};
21
22use std::{
23    convert::TryFrom,
24    io::{Error, ErrorKind, Result},
25};
26
27use bytes::{Buf, BufMut};
28use integer_encoding::VarInt;
29use prost::Message;
30
31/// Returns decoded message and number of bytes read from buffer
32pub(crate) fn decode<M, B>(buf: &mut B) -> Result<Option<M>>
33where
34    M: Message + Default,
35    B: Buf,
36{
37    if buf.remaining() == 0 {
38        // Buffer is empty
39        return Ok(None);
40    }
41
42    let (len, advance) =
43        i64::decode_var(buf.chunk()).ok_or_else(|| Error::from(ErrorKind::InvalidData))?;
44
45    assert!(len >= 0, "Length of protobuf message must not be negative");
46
47    if len == 0 {
48        // Received empty request
49        buf.advance(advance);
50        return Ok(None);
51    }
52
53    let len = usize::try_from(len).map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
54
55    if buf.remaining() < (advance + len) {
56        // We haven't received all the data yet
57        return Ok(None);
58    }
59
60    buf.advance(advance);
61    let bytes = buf.copy_to_bytes(len);
62    let message = M::decode(bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
63
64    Ok(Some(message))
65}
66
67pub(crate) fn encode<M, B>(message: M, buf: &mut B) -> Result<()>
68where
69    M: Message,
70    B: BufMut,
71{
72    let len = i64::try_from(message.encoded_len()).map_err(|e| Error::new(ErrorKind::Other, e))?;
73    let len_bytes = len.encode_var_vec();
74
75    buf.put(len_bytes.as_ref());
76
77    message
78        .encode(buf)
79        .map_err(|e| Error::new(ErrorKind::Other, e))?;
80
81    Ok(())
82}
83
84#[cfg(test)]
85mod tests {
86    use bytes::{Buf, BytesMut};
87    use tendermint_proto::abci::{request::Value, Request, RequestFlush, RequestInfo};
88
89    use super::{decode, encode};
90
91    #[test]
92    fn check_decoding() {
93        let mut buf = BytesMut::new();
94        buf.extend_from_slice(&[
95            30, 26, 13, 10, 7, 118, 48, 46, 51, 52, 46, 51, 16, 11, 24, 8, 4, 18, 0,
96        ]);
97
98        let request = decode::<Request, _>(&mut buf);
99        assert!(request.is_ok());
100        let request = request.unwrap();
101        assert!(request.is_some());
102        let request = request.unwrap();
103        assert_eq!(
104            request,
105            Request {
106                value: Some(Value::Info(RequestInfo {
107                    version: "v0.34.3".to_string(),
108                    block_version: 11,
109                    p2p_version: 8
110                }))
111            }
112        );
113
114        let request = decode::<Request, _>(&mut buf);
115        assert!(request.is_ok());
116        let request = request.unwrap();
117        assert!(request.is_some());
118        let request = request.unwrap();
119        assert_eq!(
120            request,
121            Request {
122                value: Some(Value::Flush(RequestFlush {}))
123            }
124        );
125
126        let request = decode::<Request, _>(&mut buf);
127        assert!(request.is_ok());
128        let request = request.unwrap();
129        assert!(request.is_none());
130
131        assert_eq!(0, buf.remaining());
132    }
133
134    #[test]
135    fn check_encoding() {
136        let mut buf = BytesMut::new();
137
138        let request = Request {
139            value: Some(Value::Flush(RequestFlush {})),
140        };
141        encode(request, &mut buf).unwrap();
142        assert_eq!([4, 18, 0], buf.chunk());
143
144        buf.clear();
145
146        let request = Request {
147            value: Some(Value::Info(RequestInfo {
148                version: "v0.34.3".to_string(),
149                block_version: 11,
150                p2p_version: 8,
151            })),
152        };
153
154        encode(request, &mut buf).unwrap();
155        assert_eq!(
156            [30, 26, 13, 10, 7, 118, 48, 46, 51, 52, 46, 51, 16, 11, 24, 8],
157            buf.chunk()
158        );
159    }
160}