Skip to main content

zebra_network/protocol/external/
codec.rs

1//! A Tokio codec mapping byte streams to Bitcoin message streams.
2
3use std::{
4    cmp::min,
5    fmt,
6    io::{Cursor, Read, Write},
7};
8
9use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
10use bytes::{BufMut, BytesMut};
11use chrono::{TimeZone, Utc};
12use tokio_util::codec::{Decoder, Encoder};
13
14use zebra_chain::{
15    block::{self, Block},
16    parameters::{Magic, Network},
17    serialization::{
18        sha256d, zcash_deserialize_bytes_external_count, zcash_deserialize_external_count,
19        zcash_deserialize_string_external_count, CompactSizeMessage, FakeWriter, ReadZcashExt,
20        SerializationError as Error, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize,
21        MAX_HEADERS_PER_MESSAGE, MAX_PROTOCOL_MESSAGE_LEN,
22    },
23    transaction::Transaction,
24};
25
26use crate::constants;
27
28use super::{
29    addr::{AddrInVersion, AddrV1, AddrV2},
30    message::{
31        Message, RejectReason, VersionMessage, MAX_REJECT_MESSAGE_LENGTH, MAX_REJECT_REASON_LENGTH,
32        MAX_USER_AGENT_LENGTH,
33    },
34    types::*,
35};
36
37#[cfg(test)]
38mod tests;
39
40/// The length of a Bitcoin message header.
41const HEADER_LEN: usize = 24usize;
42
43/// The maximum body length allowed before the handshake completes.
44///
45/// Version messages are ~344 bytes max (including a 256-byte user agent);
46/// verack is 0 bytes. 1 KB provides headroom for future protocol changes.
47const MAX_HANDSHAKE_BODY_LEN: usize = 1024;
48
49/// A codec which produces Bitcoin messages from byte streams and vice versa.
50pub struct Codec {
51    builder: Builder,
52    state: DecodeState,
53}
54
55/// A builder for specifying [`Codec`] options.
56pub struct Builder {
57    /// The network magic to use in encoding.
58    network: Network,
59    /// The protocol version to speak when encoding/decoding.
60    version: Version,
61    /// The maximum allowable message length.
62    max_len: usize,
63    /// An optional address label, to use for reporting metrics.
64    metrics_addr_label: Option<String>,
65}
66
67impl Codec {
68    /// Return a builder for constructing a [`Codec`].
69    pub fn builder() -> Builder {
70        Builder {
71            network: Network::Mainnet,
72            version: constants::CURRENT_NETWORK_PROTOCOL_VERSION,
73            max_len: MAX_HANDSHAKE_BODY_LEN,
74            metrics_addr_label: None,
75        }
76    }
77
78    /// Reconfigure the version used by the codec, e.g., after completing a handshake.
79    pub fn reconfigure_version(&mut self, version: Version) {
80        self.builder.version = version;
81    }
82
83    /// Raise the maximum accepted body length to the full protocol limit.
84    ///
85    /// Called after a successful handshake so post-handshake messages (blocks,
86    /// transactions) can use the full `MAX_PROTOCOL_MESSAGE_LEN`.
87    pub fn reconfigure_full_body_len(&mut self) {
88        self.builder.max_len = MAX_PROTOCOL_MESSAGE_LEN;
89    }
90}
91
92impl Builder {
93    /// Finalize the builder and return a [`Codec`].
94    pub fn finish(self) -> Codec {
95        Codec {
96            builder: self,
97            state: DecodeState::Head,
98        }
99    }
100
101    /// Configure the codec for the given [`Network`].
102    pub fn for_network(mut self, network: &Network) -> Self {
103        self.network = network.clone();
104        self
105    }
106
107    /// Configure the codec for the given [`Version`].
108    #[allow(dead_code)]
109    pub fn for_version(mut self, version: Version) -> Self {
110        self.version = version;
111        self
112    }
113
114    /// Configure the codec's maximum accepted payload size, in bytes.
115    #[allow(dead_code)]
116    pub fn with_max_body_len(mut self, len: usize) -> Self {
117        self.max_len = len;
118        self
119    }
120
121    /// Configure the codec with a label corresponding to the peer address.
122    pub fn with_metrics_addr_label(mut self, metrics_addr_label: String) -> Self {
123        self.metrics_addr_label = Some(metrics_addr_label);
124        self
125    }
126}
127
128// ======== Encoding =========
129
130impl Encoder<Message> for Codec {
131    type Error = Error;
132
133    fn encode(&mut self, item: Message, dst: &mut BytesMut) -> Result<(), Self::Error> {
134        use Error::Parse;
135
136        let body_length = self.body_length(&item);
137
138        if body_length > self.builder.max_len {
139            return Err(Parse("body length exceeded maximum size"));
140        }
141
142        if let Some(addr_label) = self.builder.metrics_addr_label.clone() {
143            metrics::counter!("zcash.net.out.bytes.total",
144                              "addr" => addr_label)
145            .increment((body_length + HEADER_LEN) as u64);
146        }
147
148        use Message::*;
149        // Note: because all match arms must have
150        // the same type, and the array length is
151        // part of the type, having at least one
152        // of length 12 checks that they are all
153        // of length 12, as they must be &[u8; 12].
154        let command = match item {
155            Version { .. } => b"version\0\0\0\0\0",
156            Verack => b"verack\0\0\0\0\0\0",
157            Ping { .. } => b"ping\0\0\0\0\0\0\0\0",
158            Pong { .. } => b"pong\0\0\0\0\0\0\0\0",
159            Reject { .. } => b"reject\0\0\0\0\0\0",
160            Addr { .. } => b"addr\0\0\0\0\0\0\0\0",
161            GetAddr => b"getaddr\0\0\0\0\0",
162            Block { .. } => b"block\0\0\0\0\0\0\0",
163            GetBlocks { .. } => b"getblocks\0\0\0",
164            Headers { .. } => b"headers\0\0\0\0\0",
165            GetHeaders { .. } => b"getheaders\0\0",
166            Inv { .. } => b"inv\0\0\0\0\0\0\0\0\0",
167            GetData { .. } => b"getdata\0\0\0\0\0",
168            NotFound { .. } => b"notfound\0\0\0\0",
169            Tx { .. } => b"tx\0\0\0\0\0\0\0\0\0\0",
170            Mempool => b"mempool\0\0\0\0\0",
171            FilterLoad { .. } => b"filterload\0\0",
172            FilterAdd { .. } => b"filteradd\0\0\0",
173            FilterClear => b"filterclear\0",
174        };
175        trace!(?item, len = body_length);
176
177        dst.reserve(HEADER_LEN + body_length);
178        let start_len = dst.len();
179        {
180            let dst = &mut dst.writer();
181            dst.write_all(&self.builder.network.magic().0[..])?;
182            dst.write_all(command)?;
183            dst.write_u32::<LittleEndian>(body_length as u32)?;
184
185            // We zero the checksum at first, and compute it later
186            // after the body has been written.
187            dst.write_u32::<LittleEndian>(0)?;
188
189            self.write_body(&item, dst)?;
190        }
191        let checksum = sha256d::Checksum::from(&dst[start_len + HEADER_LEN..]);
192        dst[start_len + 20..][..4].copy_from_slice(&checksum.0);
193
194        Ok(())
195    }
196}
197
198impl Codec {
199    /// Obtain the size of the body of a given message. This will match the
200    /// number of bytes written to the writer provided to `write_body` for the
201    /// same message.
202    // # Performance TODO
203    //
204    // If this code shows up in profiles, replace with a size estimate or cached size,
205    // to avoid multiple serializations for large data structures like lists, blocks, and transactions.
206    fn body_length(&self, msg: &Message) -> usize {
207        let mut writer = FakeWriter(0);
208
209        self.write_body(msg, &mut writer)
210            .expect("writer should never fail");
211        writer.0
212    }
213
214    /// Write the body of the message into the given writer. This allows writing
215    /// the message body prior to writing the header, so that the header can
216    /// contain a checksum of the message body.
217    fn write_body<W: Write>(&self, msg: &Message, mut writer: W) -> Result<(), Error> {
218        match msg {
219            Message::Version(VersionMessage {
220                version,
221                services,
222                timestamp,
223                address_recv,
224                address_from,
225                nonce,
226                user_agent,
227                start_height,
228                relay,
229            }) => {
230                writer.write_u32::<LittleEndian>(version.0)?;
231                writer.write_u64::<LittleEndian>(services.bits())?;
232                // # Security
233                // DateTime<Utc>::timestamp has a smaller range than i64, so
234                // serialization can not error.
235                writer.write_i64::<LittleEndian>(timestamp.timestamp())?;
236
237                address_recv.zcash_serialize(&mut writer)?;
238                address_from.zcash_serialize(&mut writer)?;
239
240                writer.write_u64::<LittleEndian>(nonce.0)?;
241
242                if user_agent.len() > MAX_USER_AGENT_LENGTH {
243                    // zcashd won't accept this version message
244                    return Err(Error::Parse(
245                        "user agent too long: must be 256 bytes or less",
246                    ));
247                }
248
249                user_agent.zcash_serialize(&mut writer)?;
250                writer.write_u32::<LittleEndian>(start_height.0)?;
251                writer.write_u8(*relay as u8)?;
252            }
253            Message::Verack => { /* Empty payload -- no-op */ }
254            Message::Ping(nonce) => {
255                writer.write_u64::<LittleEndian>(nonce.0)?;
256            }
257            Message::Pong(nonce) => {
258                writer.write_u64::<LittleEndian>(nonce.0)?;
259            }
260            Message::Reject {
261                message,
262                ccode,
263                reason,
264                data,
265            } => {
266                if message.len() > MAX_REJECT_MESSAGE_LENGTH {
267                    // zcashd won't accept this reject message
268                    return Err(Error::Parse(
269                        "reject message too long: must be 12 bytes or less",
270                    ));
271                }
272
273                message.zcash_serialize(&mut writer)?;
274
275                writer.write_u8(*ccode as u8)?;
276
277                if reason.len() > MAX_REJECT_REASON_LENGTH {
278                    return Err(Error::Parse(
279                        "reject reason too long: must be 111 bytes or less",
280                    ));
281                }
282
283                reason.zcash_serialize(&mut writer)?;
284                if let Some(data) = data {
285                    writer.write_all(data)?;
286                }
287            }
288            Message::Addr(addrs) => {
289                assert!(
290                    addrs.len() <= constants::MAX_ADDRS_IN_MESSAGE,
291                    "unexpectedly large Addr message: greater than MAX_ADDRS_IN_MESSAGE addresses"
292                );
293
294                // Regardless of the way we received the address,
295                // Zebra always sends `addr` messages
296                let v1_addrs: Vec<AddrV1> = addrs
297                    .iter()
298                    .map(|addr| AddrV1::from(addr.clone()))
299                    .collect();
300                v1_addrs.zcash_serialize(&mut writer)?
301            }
302            Message::GetAddr => { /* Empty payload -- no-op */ }
303            Message::Block(block) => block.zcash_serialize(&mut writer)?,
304            Message::GetBlocks { known_blocks, stop } => {
305                writer.write_u32::<LittleEndian>(self.builder.version.0)?;
306                known_blocks.zcash_serialize(&mut writer)?;
307                stop.unwrap_or(block::Hash([0; 32]))
308                    .zcash_serialize(&mut writer)?;
309            }
310            Message::GetHeaders { known_blocks, stop } => {
311                writer.write_u32::<LittleEndian>(self.builder.version.0)?;
312                known_blocks.zcash_serialize(&mut writer)?;
313                stop.unwrap_or(block::Hash([0; 32]))
314                    .zcash_serialize(&mut writer)?;
315            }
316            Message::Headers(headers) => headers.zcash_serialize(&mut writer)?,
317            Message::Inv(hashes) => hashes.zcash_serialize(&mut writer)?,
318            Message::GetData(hashes) => hashes.zcash_serialize(&mut writer)?,
319            Message::NotFound(hashes) => hashes.zcash_serialize(&mut writer)?,
320            Message::Tx(transaction) => transaction.transaction.zcash_serialize(&mut writer)?,
321            Message::Mempool => { /* Empty payload -- no-op */ }
322            Message::FilterLoad {
323                filter,
324                hash_functions_count,
325                tweak,
326                flags,
327            } => {
328                writer.write_all(&filter.0)?;
329                writer.write_u32::<LittleEndian>(*hash_functions_count)?;
330                writer.write_u32::<LittleEndian>(tweak.0)?;
331                writer.write_u8(*flags)?;
332            }
333            Message::FilterAdd { data } => {
334                writer.write_all(data)?;
335            }
336            Message::FilterClear => { /* Empty payload -- no-op */ }
337        }
338        Ok(())
339    }
340}
341
342// ======== Decoding =========
343
344enum DecodeState {
345    Head,
346    Body {
347        body_len: usize,
348        command: [u8; 12],
349        checksum: sha256d::Checksum,
350    },
351}
352
353impl fmt::Debug for DecodeState {
354    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
355        match self {
356            DecodeState::Head => write!(f, "DecodeState::Head"),
357            DecodeState::Body {
358                body_len,
359                command,
360                checksum,
361            } => f
362                .debug_struct("DecodeState::Body")
363                .field("body_len", &body_len)
364                .field("command", &String::from_utf8_lossy(command))
365                .field("checksum", &checksum)
366                .finish(),
367        }
368    }
369}
370
371impl Decoder for Codec {
372    type Item = Message;
373    type Error = Error;
374
375    #[allow(clippy::unwrap_in_result)]
376    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
377        use Error::Parse;
378        match self.state {
379            DecodeState::Head => {
380                // First check that the src buffer contains an entire header.
381                if src.len() < HEADER_LEN {
382                    trace!(?self.state, "src buffer does not have an entire header, waiting");
383                    // Signal that decoding requires more data.
384                    return Ok(None);
385                }
386
387                // Now that we know that src contains a header, split off the header section.
388                let header = src.split_to(HEADER_LEN);
389
390                // Create a cursor over the header and parse its fields.
391                let mut header_reader = Cursor::new(&header);
392                let magic = Magic(header_reader.read_4_bytes()?);
393                let command = header_reader.read_12_bytes()?;
394                let body_len = header_reader.read_u32::<LittleEndian>()? as usize;
395                let checksum = sha256d::Checksum(header_reader.read_4_bytes()?);
396                trace!(
397                    ?self.state,
398                    ?magic,
399                    command = %String::from_utf8(
400                        command.iter()
401                            .cloned()
402                            .flat_map(std::ascii::escape_default)
403                            .collect()
404                    ).unwrap(),
405                    body_len,
406                    ?checksum,
407                    "read header from src buffer"
408                );
409
410                if magic != self.builder.network.magic() {
411                    return Err(Parse("supplied magic did not meet expectations"));
412                }
413                if body_len > self.builder.max_len {
414                    return Err(Parse("body length exceeded maximum size"));
415                }
416
417                if let Some(label) = self.builder.metrics_addr_label.clone() {
418                    metrics::counter!("zcash.net.in.bytes.total", "addr" =>  label)
419                        .increment((body_len + HEADER_LEN) as u64);
420                }
421
422                // Reserve buffer space for the expected body and the following header.
423                src.reserve(body_len + HEADER_LEN);
424
425                self.state = DecodeState::Body {
426                    body_len,
427                    command,
428                    checksum,
429                };
430
431                // Now that the state is updated, recurse to attempt body decoding.
432                self.decode(src)
433            }
434            DecodeState::Body {
435                body_len,
436                command,
437                checksum,
438            } => {
439                if src.len() < body_len {
440                    // Need to wait for the full body
441                    trace!(?self.state, len = src.len(), "src buffer does not have an entire body, waiting");
442                    return Ok(None);
443                }
444
445                // Now that we know we have the full body, split off the body,
446                // and reset the decoder state for the next message. Otherwise
447                // we will attempt to read the next header as the current body.
448                let body = src.split_to(body_len);
449                self.state = DecodeState::Head;
450
451                if checksum != sha256d::Checksum::from(&body[..]) {
452                    return Err(Parse(
453                        "supplied message checksum does not match computed checksum",
454                    ));
455                }
456
457                let mut body_reader = Cursor::new(&body);
458                match &command {
459                    b"version\0\0\0\0\0" => self.read_version(&mut body_reader),
460                    b"verack\0\0\0\0\0\0" => self.read_verack(&mut body_reader),
461                    b"ping\0\0\0\0\0\0\0\0" => self.read_ping(&mut body_reader),
462                    b"pong\0\0\0\0\0\0\0\0" => self.read_pong(&mut body_reader),
463                    b"reject\0\0\0\0\0\0" => self.read_reject(&mut body_reader),
464                    b"addr\0\0\0\0\0\0\0\0" => self.read_addr(&mut body_reader),
465                    b"addrv2\0\0\0\0\0\0" => self.read_addrv2(&mut body_reader),
466                    b"getaddr\0\0\0\0\0" => self.read_getaddr(&mut body_reader),
467                    b"block\0\0\0\0\0\0\0" => self.read_block(&mut body_reader),
468                    b"getblocks\0\0\0" => self.read_getblocks(&mut body_reader),
469                    b"headers\0\0\0\0\0" => self.read_headers(&mut body_reader),
470                    b"getheaders\0\0" => self.read_getheaders(&mut body_reader),
471                    b"inv\0\0\0\0\0\0\0\0\0" => self.read_inv(&mut body_reader),
472                    b"getdata\0\0\0\0\0" => self.read_getdata(&mut body_reader),
473                    b"notfound\0\0\0\0" => self.read_notfound(&mut body_reader),
474                    b"tx\0\0\0\0\0\0\0\0\0\0" => self.read_tx(&mut body_reader),
475                    b"mempool\0\0\0\0\0" => self.read_mempool(&mut body_reader),
476                    b"filterload\0\0" => self.read_filterload(&mut body_reader, body_len),
477                    b"filteradd\0\0\0" => self.read_filteradd(&mut body_reader, body_len),
478                    b"filterclear\0" => self.read_filterclear(&mut body_reader),
479                    _ => {
480                        let command_string = String::from_utf8_lossy(&command);
481
482                        // # Security
483                        //
484                        // Zcash connections are not authenticated, so malicious nodes can
485                        // send fake messages, with connected peers' IP addresses in the IP header.
486                        //
487                        // Since we can't verify their source, Zebra needs to ignore unexpected messages,
488                        // because closing the connection could cause a denial of service or eclipse attack.
489                        debug!(?command, %command_string, "unknown message command from peer");
490                        return Ok(None);
491                    }
492                }
493                // We need Ok(Some(msg)) to signal that we're done decoding.
494                // This is also convenient for tracing the parse result.
495                .map(|msg| {
496                    // bitcoin allows extra data at the end of most messages,
497                    // so that old nodes can still read newer message formats,
498                    // and ignore any extra fields
499                    let extra_bytes = body.len() as u64 - body_reader.position();
500                    if extra_bytes == 0 {
501                        trace!(?extra_bytes, %msg, "finished message decoding");
502                    } else {
503                        // log when there are extra bytes, so we know when we need to
504                        // upgrade message formats
505                        debug!(?extra_bytes, %msg, "extra data after decoding message");
506                    }
507                    Some(msg)
508                })
509            }
510        }
511    }
512}
513
514impl Codec {
515    /// Deserializes a version message.
516    ///
517    /// The `relay` field is optional, as defined in <https://developer.bitcoin.org/reference/p2p_networking.html#version>
518    ///
519    /// Note: zcashd only requires fields up to `address_recv`, but everything up to `relay` is required in Zebra.
520    ///       see <https://github.com/zcash/zcash/blob/11d563904933e889a11d9685c3b249f1536cfbe7/src/main.cpp#L6490-L6507>
521    fn read_version<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
522        Ok(VersionMessage {
523            version: Version(reader.read_u32::<LittleEndian>()?),
524            // Use from_bits_truncate to discard unknown service bits.
525            services: PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?),
526            timestamp: Utc
527                .timestamp_opt(reader.read_i64::<LittleEndian>()?, 0)
528                .single()
529                .ok_or(Error::Parse(
530                    "version timestamp is out of range for DateTime",
531                ))?,
532            address_recv: AddrInVersion::zcash_deserialize(&mut reader)?,
533            address_from: AddrInVersion::zcash_deserialize(&mut reader)?,
534            nonce: Nonce(reader.read_u64::<LittleEndian>()?),
535            user_agent: {
536                let byte_count: CompactSizeMessage = (&mut reader).zcash_deserialize_into()?;
537                let byte_count: usize = byte_count.into();
538
539                // # Security
540                //
541                // Limit peer set memory usage, Zebra stores an `Arc<VersionMessage>` per
542                // connected peer.
543                //
544                // Without this check, we can use `200 peers * 2 MB message size limit = 400 MB`.
545                if byte_count > MAX_USER_AGENT_LENGTH {
546                    return Err(Error::Parse(
547                        "user agent too long: must be 256 bytes or less",
548                    ));
549                }
550
551                zcash_deserialize_string_external_count(byte_count, &mut reader)?
552            },
553            start_height: block::Height(reader.read_u32::<LittleEndian>()?),
554            relay: match reader.read_u8() {
555                Ok(val @ 0..=1) => val == 1,
556                Ok(_) => return Err(Error::Parse("non-bool value supplied in relay field")),
557                Err(err) if err.kind() == std::io::ErrorKind::UnexpectedEof => true,
558                Err(err) => Err(err)?,
559            },
560        }
561        .into())
562    }
563
564    fn read_verack<R: Read>(&self, mut _reader: R) -> Result<Message, Error> {
565        Ok(Message::Verack)
566    }
567
568    fn read_ping<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
569        Ok(Message::Ping(Nonce(reader.read_u64::<LittleEndian>()?)))
570    }
571
572    fn read_pong<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
573        Ok(Message::Pong(Nonce(reader.read_u64::<LittleEndian>()?)))
574    }
575
576    fn read_reject<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
577        Ok(Message::Reject {
578            message: {
579                let byte_count: CompactSizeMessage = (&mut reader).zcash_deserialize_into()?;
580                let byte_count: usize = byte_count.into();
581
582                // # Security
583                //
584                // Limit log size on disk, Zebra might print large reject messages to disk.
585                if byte_count > MAX_REJECT_MESSAGE_LENGTH {
586                    return Err(Error::Parse(
587                        "reject message too long: must be 12 bytes or less",
588                    ));
589                }
590
591                zcash_deserialize_string_external_count(byte_count, &mut reader)?
592            },
593            ccode: match reader.read_u8()? {
594                0x01 => RejectReason::Malformed,
595                0x10 => RejectReason::Invalid,
596                0x11 => RejectReason::Obsolete,
597                0x12 => RejectReason::Duplicate,
598                0x40 => RejectReason::Nonstandard,
599                0x41 => RejectReason::Dust,
600                0x42 => RejectReason::InsufficientFee,
601                0x43 => RejectReason::Checkpoint,
602                0x50 => RejectReason::Other,
603                _ => return Err(Error::Parse("invalid RejectReason value in ccode field")),
604            },
605            reason: {
606                let byte_count: CompactSizeMessage = (&mut reader).zcash_deserialize_into()?;
607                let byte_count: usize = byte_count.into();
608
609                // # Security
610                //
611                // Limit log size on disk, Zebra might print large reject messages to disk.
612                if byte_count > MAX_REJECT_REASON_LENGTH {
613                    return Err(Error::Parse(
614                        "reject reason too long: must be 111 bytes or less",
615                    ));
616                }
617
618                zcash_deserialize_string_external_count(byte_count, &mut reader)?
619            },
620            // Sometimes there's data, sometimes there isn't. There's no length
621            // field, this is just implicitly encoded by the body_len.
622            // Apparently all existing implementations only supply 32 bytes of
623            // data (hash identifying the rejected object) or none (and we model
624            // the Reject message that way), so instead of passing in the
625            // body_len separately and calculating remaining bytes, just try to
626            // read 32 bytes and ignore any failures. (The caller will log and
627            // ignore any trailing bytes.)
628            data: reader.read_32_bytes().ok(),
629        })
630    }
631
632    /// Deserialize an `addr` (v1) message into a list of `MetaAddr`s.
633    pub(super) fn read_addr<R: Read>(&self, reader: R) -> Result<Message, Error> {
634        let addrs: Vec<AddrV1> = reader.zcash_deserialize_into()?;
635
636        if addrs.len() > constants::MAX_ADDRS_IN_MESSAGE {
637            return Err(Error::Parse(
638                "more than MAX_ADDRS_IN_MESSAGE in addr message",
639            ));
640        }
641
642        // Convert the received address format to Zebra's internal `MetaAddr`.
643        let addrs = addrs.into_iter().map(Into::into).collect();
644        Ok(Message::Addr(addrs))
645    }
646
647    /// Deserialize an `addrv2` message into a list of `MetaAddr`s.
648    ///
649    /// Currently, Zebra parses received `addrv2`s, ignoring some address types.
650    /// Zebra never sends `addrv2` messages.
651    pub(super) fn read_addrv2<R: Read>(&self, reader: R) -> Result<Message, Error> {
652        let addrs: Vec<AddrV2> = reader.zcash_deserialize_into()?;
653
654        if addrs.len() > constants::MAX_ADDRS_IN_MESSAGE {
655            return Err(Error::Parse(
656                "more than MAX_ADDRS_IN_MESSAGE in addrv2 message",
657            ));
658        }
659
660        // Convert the received address format to Zebra's internal `MetaAddr`,
661        // ignoring unsupported network IDs.
662        let addrs = addrs
663            .into_iter()
664            .filter_map(|addr| addr.try_into().ok())
665            .collect();
666        Ok(Message::Addr(addrs))
667    }
668
669    fn read_getaddr<R: Read>(&self, mut _reader: R) -> Result<Message, Error> {
670        Ok(Message::GetAddr)
671    }
672
673    fn read_block<R: Read + std::marker::Send>(&self, reader: R) -> Result<Message, Error> {
674        let result = Self::deserialize_block_spawning(reader);
675        Ok(Message::Block(result?.into()))
676    }
677
678    fn read_getblocks<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
679        if self.builder.version == Version(reader.read_u32::<LittleEndian>()?) {
680            let known_blocks = Vec::zcash_deserialize(&mut reader)?;
681            let stop_hash = block::Hash::zcash_deserialize(&mut reader)?;
682            let stop = if stop_hash != block::Hash([0; 32]) {
683                Some(stop_hash)
684            } else {
685                None
686            };
687            Ok(Message::GetBlocks { known_blocks, stop })
688        } else {
689            Err(Error::Parse("getblocks version did not match negotiation"))
690        }
691    }
692
693    /// Deserialize a `headers` message.
694    ///
695    /// See [Zcash block header] for the enumeration of these fields.
696    ///
697    /// [Zcash block header](https://zips.z.cash/protocol/protocol.pdf#page=84)
698    fn read_headers<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
699        // CompactSizeMessage is bounded to MAX_PROTOCOL_MESSAGE_LEN on deserialization.
700        let count: CompactSizeMessage = (&mut reader).zcash_deserialize_into()?;
701        // Infallible: CompactSizeMessage wraps u32, which always fits in usize.
702        let count: usize = count.into();
703        if count > MAX_HEADERS_PER_MESSAGE {
704            return Err(Error::Parse(
705                "headers message exceeds the protocol limit of 160 entries",
706            ));
707        }
708        Ok(Message::Headers(zcash_deserialize_external_count(
709            count,
710            &mut reader,
711        )?))
712    }
713
714    fn read_getheaders<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
715        if self.builder.version == Version(reader.read_u32::<LittleEndian>()?) {
716            let known_blocks = Vec::zcash_deserialize(&mut reader)?;
717            let stop_hash = block::Hash::zcash_deserialize(&mut reader)?;
718            let stop = if stop_hash != block::Hash([0; 32]) {
719                Some(stop_hash)
720            } else {
721                None
722            };
723            Ok(Message::GetHeaders { known_blocks, stop })
724        } else {
725            Err(Error::Parse("getblocks version did not match negotiation"))
726        }
727    }
728
729    fn read_inv<R: Read>(&self, reader: R) -> Result<Message, Error> {
730        Ok(Message::Inv(Vec::zcash_deserialize(reader)?))
731    }
732
733    fn read_getdata<R: Read>(&self, reader: R) -> Result<Message, Error> {
734        Ok(Message::GetData(Vec::zcash_deserialize(reader)?))
735    }
736
737    fn read_notfound<R: Read>(&self, reader: R) -> Result<Message, Error> {
738        Ok(Message::NotFound(Vec::zcash_deserialize(reader)?))
739    }
740
741    fn read_tx<R: Read + std::marker::Send>(&self, reader: R) -> Result<Message, Error> {
742        let result = Self::deserialize_transaction_spawning(reader);
743        Ok(Message::Tx(result?.into()))
744    }
745
746    fn read_mempool<R: Read>(&self, mut _reader: R) -> Result<Message, Error> {
747        Ok(Message::Mempool)
748    }
749
750    fn read_filterload<R: Read>(&self, mut reader: R, body_len: usize) -> Result<Message, Error> {
751        // The maximum length of a filter.
752        const MAX_FILTERLOAD_FILTER_LENGTH: usize = 36000;
753
754        // The data length of the fields:
755        // hash_functions_count + tweak + flags.
756        const FILTERLOAD_FIELDS_LENGTH: usize = 4 + 4 + 1;
757
758        // The maximum length of a filter message's data.
759        const MAX_FILTERLOAD_MESSAGE_LENGTH: usize =
760            MAX_FILTERLOAD_FILTER_LENGTH + FILTERLOAD_FIELDS_LENGTH;
761
762        if !(FILTERLOAD_FIELDS_LENGTH..=MAX_FILTERLOAD_MESSAGE_LENGTH).contains(&body_len) {
763            return Err(Error::Parse("Invalid filterload message body length."));
764        }
765
766        // Memory Denial of Service: we just checked the untrusted parsed length
767        let filter_length: usize = body_len - FILTERLOAD_FIELDS_LENGTH;
768        let filter_bytes = zcash_deserialize_bytes_external_count(filter_length, &mut reader)?;
769
770        Ok(Message::FilterLoad {
771            filter: Filter(filter_bytes),
772            hash_functions_count: reader.read_u32::<LittleEndian>()?,
773            tweak: Tweak(reader.read_u32::<LittleEndian>()?),
774            flags: reader.read_u8()?,
775        })
776    }
777
778    fn read_filteradd<R: Read>(&self, mut reader: R, body_len: usize) -> Result<Message, Error> {
779        const MAX_FILTERADD_LENGTH: usize = 520;
780
781        // Memory Denial of Service: limit the untrusted parsed length
782        let filter_length: usize = min(body_len, MAX_FILTERADD_LENGTH);
783        let filter_bytes = zcash_deserialize_bytes_external_count(filter_length, &mut reader)?;
784
785        Ok(Message::FilterAdd { data: filter_bytes })
786    }
787
788    fn read_filterclear<R: Read>(&self, mut _reader: R) -> Result<Message, Error> {
789        Ok(Message::FilterClear)
790    }
791
792    /// Given the reader, deserialize the transaction in the rayon thread pool.
793    #[allow(clippy::unwrap_in_result)]
794    fn deserialize_transaction_spawning<R: Read + std::marker::Send>(
795        reader: R,
796    ) -> Result<Transaction, Error> {
797        let mut result = None;
798
799        // Correctness: Do CPU-intensive work on a dedicated thread, to avoid blocking other futures.
800        //
801        // Since we use `block_in_place()`, other futures running on the connection task will be blocked:
802        // https://docs.rs/tokio/latest/tokio/task/fn.block_in_place.html
803        //
804        // We can't use `spawn_blocking()` because:
805        // - The `reader` has a lifetime (but we could replace it with a `Vec` of message data)
806        // - There is no way to check the blocking task's future for panics
807        tokio::task::block_in_place(|| {
808            rayon::in_place_scope_fifo(|s| {
809                s.spawn_fifo(|_s| result = Some(Transaction::zcash_deserialize(reader)))
810            })
811        });
812
813        result.expect("scope has already finished")
814    }
815
816    /// Given the reader, deserialize the block in the rayon thread pool.
817    #[allow(clippy::unwrap_in_result)]
818    fn deserialize_block_spawning<R: Read + std::marker::Send>(reader: R) -> Result<Block, Error> {
819        let mut result = None;
820
821        // Correctness: Do CPU-intensive work on a dedicated thread, to avoid blocking other futures.
822        //
823        // Since we use `block_in_place()`, other futures running on the connection task will be blocked:
824        // https://docs.rs/tokio/latest/tokio/task/fn.block_in_place.html
825        //
826        // We can't use `spawn_blocking()` because:
827        // - The `reader` has a lifetime (but we could replace it with a `Vec` of message data)
828        // - There is no way to check the blocking task's future for panics
829        tokio::task::block_in_place(|| {
830            rayon::in_place_scope_fifo(|s| {
831                s.spawn_fifo(|_s| result = Some(Block::zcash_deserialize(reader)))
832            })
833        });
834
835        result.expect("scope has already finished")
836    }
837}