1use 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
40const HEADER_LEN: usize = 24usize;
42
43const MAX_HANDSHAKE_BODY_LEN: usize = 1024;
48
49pub struct Codec {
51 builder: Builder,
52 state: DecodeState,
53}
54
55pub struct Builder {
57 network: Network,
59 version: Version,
61 max_len: usize,
63 metrics_addr_label: Option<String>,
65}
66
67impl Codec {
68 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 pub fn reconfigure_version(&mut self, version: Version) {
80 self.builder.version = version;
81 }
82
83 pub fn reconfigure_full_body_len(&mut self) {
88 self.builder.max_len = MAX_PROTOCOL_MESSAGE_LEN;
89 }
90}
91
92impl Builder {
93 pub fn finish(self) -> Codec {
95 Codec {
96 builder: self,
97 state: DecodeState::Head,
98 }
99 }
100
101 pub fn for_network(mut self, network: &Network) -> Self {
103 self.network = network.clone();
104 self
105 }
106
107 #[allow(dead_code)]
109 pub fn for_version(mut self, version: Version) -> Self {
110 self.version = version;
111 self
112 }
113
114 #[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 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
128impl 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 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 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 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 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 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 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 => { }
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 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 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 => { }
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 => { }
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 => { }
337 }
338 Ok(())
339 }
340}
341
342enum 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 if src.len() < HEADER_LEN {
382 trace!(?self.state, "src buffer does not have an entire header, waiting");
383 return Ok(None);
385 }
386
387 let header = src.split_to(HEADER_LEN);
389
390 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 src.reserve(body_len + HEADER_LEN);
424
425 self.state = DecodeState::Body {
426 body_len,
427 command,
428 checksum,
429 };
430
431 self.decode(src)
433 }
434 DecodeState::Body {
435 body_len,
436 command,
437 checksum,
438 } => {
439 if src.len() < body_len {
440 trace!(?self.state, len = src.len(), "src buffer does not have an entire body, waiting");
442 return Ok(None);
443 }
444
445 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 debug!(?command, %command_string, "unknown message command from peer");
490 return Ok(None);
491 }
492 }
493 .map(|msg| {
496 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 debug!(?extra_bytes, %msg, "extra data after decoding message");
506 }
507 Some(msg)
508 })
509 }
510 }
511 }
512}
513
514impl Codec {
515 fn read_version<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
522 Ok(VersionMessage {
523 version: Version(reader.read_u32::<LittleEndian>()?),
524 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 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 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 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 data: reader.read_32_bytes().ok(),
629 })
630 }
631
632 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 let addrs = addrs.into_iter().map(Into::into).collect();
644 Ok(Message::Addr(addrs))
645 }
646
647 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 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 fn read_headers<R: Read>(&self, mut reader: R) -> Result<Message, Error> {
699 let count: CompactSizeMessage = (&mut reader).zcash_deserialize_into()?;
701 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 const MAX_FILTERLOAD_FILTER_LENGTH: usize = 36000;
753
754 const FILTERLOAD_FIELDS_LENGTH: usize = 4 + 4 + 1;
757
758 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 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 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 #[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 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 #[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 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}