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