1use 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
41const HEADER_LEN: usize = 24usize;
43
44const MAX_HANDSHAKE_BODY_LEN: usize = 1024;
49
50pub struct Codec {
52 builder: Builder,
53 state: DecodeState,
54}
55
56pub struct Builder {
58 network: Network,
60 version: Version,
62 max_len: usize,
64 metrics_addr_label: Option<String>,
66}
67
68impl Codec {
69 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 pub fn reconfigure_version(&mut self, version: Version) {
81 self.builder.version = version;
82 }
83
84 pub fn reconfigure_full_body_len(&mut self) {
89 self.builder.max_len = MAX_PROTOCOL_MESSAGE_LEN;
90 }
91}
92
93impl Builder {
94 pub fn finish(self) -> Codec {
96 Codec {
97 builder: self,
98 state: DecodeState::Head,
99 }
100 }
101
102 pub fn for_network(mut self, network: &Network) -> Self {
104 self.network = network.clone();
105 self
106 }
107
108 #[allow(dead_code)]
110 pub fn for_version(mut self, version: Version) -> Self {
111 self.version = version;
112 self
113 }
114
115 #[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 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
129impl 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 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 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 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 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 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 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 => { }
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 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 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 => { }
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 => { }
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 => { }
338 }
339 Ok(())
340 }
341}
342
343enum 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 if src.len() < HEADER_LEN {
383 trace!(?self.state, "src buffer does not have an entire header, waiting");
384 return Ok(None);
386 }
387
388 let header = src.split_to(HEADER_LEN);
390
391 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 src.reserve(body_len + HEADER_LEN);
425
426 self.state = DecodeState::Body {
427 body_len,
428 command,
429 checksum,
430 };
431
432 self.decode(src)
434 }
435 DecodeState::Body {
436 body_len,
437 command,
438 checksum,
439 } => {
440 if src.len() < body_len {
441 trace!(?self.state, len = src.len(), "src buffer does not have an entire body, waiting");
443 return Ok(None);
444 }
445
446 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 debug!(?command, %command_string, "unknown message command from peer");
491 return Ok(None);
492 }
493 }
494 .map(|msg| {
497 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 debug!(?extra_bytes, %msg, "extra data after decoding message");
507 }
508 Some(msg)
509 })
510 }
511 }
512 }
513}
514
515impl Codec {
516 fn read_version<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
523 Ok(VersionMessage {
524 version: Version(reader.read_u32::<LittleEndian>()?),
525 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 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 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 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 data: reader.read_32_bytes().ok(),
630 })
631 }
632
633 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 let addrs = addrs.into_iter().map(Into::into).collect();
645 Ok(Message::Addr(addrs))
646 }
647
648 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 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 fn read_headers<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
700 let count: CompactSizeMessage = (&mut reader).zcash_deserialize_into()?;
702 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 const MAX_FILTERLOAD_FILTER_LENGTH: usize = 36000;
754
755 const FILTERLOAD_FIELDS_LENGTH: usize = 4 + 4 + 1;
758
759 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 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 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 #[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 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 #[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 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}