bitcoin/p2p/
message.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Bitcoin network messages.
4//!
5//! This module defines the `NetworkMessage` and `RawNetworkMessage` types that
6//! are used for (de)serializing Bitcoin objects for transmission on the network.
7//!
8
9use core::{fmt, iter};
10
11use hashes::{sha256d, Hash};
12use io::{Read, Write};
13
14use crate::blockdata::{block, transaction};
15use crate::consensus::encode::{self, CheckedData, Decodable, Encodable, VarInt};
16use crate::merkle_tree::MerkleBlock;
17use crate::p2p::address::{AddrV2Message, Address};
18use crate::p2p::{
19    message_blockdata, message_bloom, message_compact_blocks, message_filter, message_network,
20    Magic,
21};
22use crate::prelude::*;
23
24/// The maximum number of [super::message_blockdata::Inventory] items in an `inv` message.
25///
26/// This limit is not currently enforced by this implementation.
27pub const MAX_INV_SIZE: usize = 50_000;
28
29/// Maximum size, in bytes, of an encoded message
30/// This by neccessity should be larger tham `MAX_VEC_SIZE`
31pub const MAX_MSG_SIZE: usize = 5_000_000;
32
33/// Serializer for command string
34#[derive(PartialEq, Eq, Clone, Debug)]
35pub struct CommandString(Cow<'static, str>);
36
37impl CommandString {
38    /// Converts `&'static str` to `CommandString`
39    ///
40    /// This is more efficient for string literals than non-static conversions because it avoids
41    /// allocation.
42    ///
43    /// # Errors
44    ///
45    /// Returns an error if, and only if, the string is
46    /// larger than 12 characters in length.
47    pub fn try_from_static(s: &'static str) -> Result<CommandString, CommandStringError> {
48        Self::try_from_static_cow(s.into())
49    }
50
51    fn try_from_static_cow(cow: Cow<'static, str>) -> Result<CommandString, CommandStringError> {
52        if cow.len() > 12 {
53            Err(CommandStringError { cow })
54        } else {
55            Ok(CommandString(cow))
56        }
57    }
58}
59
60impl TryFrom<String> for CommandString {
61    type Error = CommandStringError;
62
63    fn try_from(value: String) -> Result<Self, Self::Error> {
64        Self::try_from_static_cow(value.into())
65    }
66}
67
68impl TryFrom<Box<str>> for CommandString {
69    type Error = CommandStringError;
70
71    fn try_from(value: Box<str>) -> Result<Self, Self::Error> {
72        Self::try_from_static_cow(String::from(value).into())
73    }
74}
75
76impl<'a> TryFrom<&'a str> for CommandString {
77    type Error = CommandStringError;
78
79    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
80        Self::try_from_static_cow(value.to_owned().into())
81    }
82}
83
84impl core::str::FromStr for CommandString {
85    type Err = CommandStringError;
86
87    fn from_str(s: &str) -> Result<Self, Self::Err> {
88        Self::try_from_static_cow(s.to_owned().into())
89    }
90}
91
92impl fmt::Display for CommandString {
93    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.0.as_ref()) }
94}
95
96impl AsRef<str> for CommandString {
97    fn as_ref(&self) -> &str { self.0.as_ref() }
98}
99
100impl Encodable for CommandString {
101    #[inline]
102    fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
103        let mut rawbytes = [0u8; 12];
104        let strbytes = self.0.as_bytes();
105        debug_assert!(strbytes.len() <= 12);
106        rawbytes[..strbytes.len()].copy_from_slice(strbytes);
107        rawbytes.consensus_encode(w)
108    }
109}
110
111impl Decodable for CommandString {
112    #[inline]
113    fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
114        let rawbytes: [u8; 12] = Decodable::consensus_decode(r)?;
115        let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| {
116            if u > 0 {
117                Some(u as char)
118            } else {
119                None
120            }
121        }));
122        Ok(CommandString(rv))
123    }
124}
125
126/// Error returned when a command string is invalid.
127///
128/// This is currently returned for command strings longer than 12.
129#[derive(Debug, Clone, PartialEq, Eq)]
130#[non_exhaustive]
131pub struct CommandStringError {
132    cow: Cow<'static, str>,
133}
134
135impl fmt::Display for CommandStringError {
136    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137        write!(
138            f,
139            "the command string '{}' has length {} which is larger than 12",
140            self.cow,
141            self.cow.len()
142        )
143    }
144}
145
146#[cfg(feature = "std")]
147impl std::error::Error for CommandStringError {
148    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
149}
150
151/// A Network message
152#[derive(Clone, Debug, PartialEq, Eq)]
153pub struct RawNetworkMessage {
154    magic: Magic,
155    payload: NetworkMessage,
156    payload_len: u32,
157    checksum: [u8; 4],
158}
159
160/// A Network message payload. Proper documentation is available on at
161/// [Bitcoin Wiki: Protocol Specification](https://en.bitcoin.it/wiki/Protocol_specification)
162#[derive(Clone, PartialEq, Eq, Debug)]
163pub enum NetworkMessage {
164    /// `version`
165    Version(message_network::VersionMessage),
166    /// `verack`
167    Verack,
168    /// `addr`
169    Addr(Vec<(u32, Address)>),
170    /// `inv`
171    Inv(Vec<message_blockdata::Inventory>),
172    /// `getdata`
173    GetData(Vec<message_blockdata::Inventory>),
174    /// `notfound`
175    NotFound(Vec<message_blockdata::Inventory>),
176    /// `getblocks`
177    GetBlocks(message_blockdata::GetBlocksMessage),
178    /// `getheaders`
179    GetHeaders(message_blockdata::GetHeadersMessage),
180    /// `mempool`
181    MemPool,
182    /// tx
183    Tx(transaction::Transaction),
184    /// `block`
185    Block(block::Block),
186    /// `headers`
187    Headers(Vec<block::Header>),
188    /// `sendheaders`
189    SendHeaders,
190    /// `getaddr`
191    GetAddr,
192    /// `ping`
193    Ping(u64),
194    /// `pong`
195    Pong(u64),
196    /// `merkleblock`
197    MerkleBlock(MerkleBlock),
198    /// BIP 37 `filterload`
199    FilterLoad(message_bloom::FilterLoad),
200    /// BIP 37 `filteradd`
201    FilterAdd(message_bloom::FilterAdd),
202    /// BIP 37 `filterclear`
203    FilterClear,
204    /// BIP157 getcfilters
205    GetCFilters(message_filter::GetCFilters),
206    /// BIP157 cfilter
207    CFilter(message_filter::CFilter),
208    /// BIP157 getcfheaders
209    GetCFHeaders(message_filter::GetCFHeaders),
210    /// BIP157 cfheaders
211    CFHeaders(message_filter::CFHeaders),
212    /// BIP157 getcfcheckpt
213    GetCFCheckpt(message_filter::GetCFCheckpt),
214    /// BIP157 cfcheckpt
215    CFCheckpt(message_filter::CFCheckpt),
216    /// BIP152 sendcmpct
217    SendCmpct(message_compact_blocks::SendCmpct),
218    /// BIP152 cmpctblock
219    CmpctBlock(message_compact_blocks::CmpctBlock),
220    /// BIP152 getblocktxn
221    GetBlockTxn(message_compact_blocks::GetBlockTxn),
222    /// BIP152 blocktxn
223    BlockTxn(message_compact_blocks::BlockTxn),
224    /// `alert`
225    Alert(Vec<u8>),
226    /// `reject`
227    Reject(message_network::Reject),
228    /// `feefilter`
229    FeeFilter(i64),
230    /// `wtxidrelay`
231    WtxidRelay,
232    /// `addrv2`
233    AddrV2(Vec<AddrV2Message>),
234    /// `sendaddrv2`
235    SendAddrV2,
236
237    /// Any other message.
238    Unknown {
239        /// The command of this message.
240        command: CommandString,
241        /// The payload of this message.
242        payload: Vec<u8>,
243    },
244}
245
246impl NetworkMessage {
247    /// Return the message command as a static string reference.
248    ///
249    /// This returns `"unknown"` for [NetworkMessage::Unknown],
250    /// regardless of the actual command in the unknown message.
251    /// Use the [Self::command] method to get the command for unknown messages.
252    pub fn cmd(&self) -> &'static str {
253        match *self {
254            NetworkMessage::Version(_) => "version",
255            NetworkMessage::Verack => "verack",
256            NetworkMessage::Addr(_) => "addr",
257            NetworkMessage::Inv(_) => "inv",
258            NetworkMessage::GetData(_) => "getdata",
259            NetworkMessage::NotFound(_) => "notfound",
260            NetworkMessage::GetBlocks(_) => "getblocks",
261            NetworkMessage::GetHeaders(_) => "getheaders",
262            NetworkMessage::MemPool => "mempool",
263            NetworkMessage::Tx(_) => "tx",
264            NetworkMessage::Block(_) => "block",
265            NetworkMessage::Headers(_) => "headers",
266            NetworkMessage::SendHeaders => "sendheaders",
267            NetworkMessage::GetAddr => "getaddr",
268            NetworkMessage::Ping(_) => "ping",
269            NetworkMessage::Pong(_) => "pong",
270            NetworkMessage::MerkleBlock(_) => "merkleblock",
271            NetworkMessage::FilterLoad(_) => "filterload",
272            NetworkMessage::FilterAdd(_) => "filteradd",
273            NetworkMessage::FilterClear => "filterclear",
274            NetworkMessage::GetCFilters(_) => "getcfilters",
275            NetworkMessage::CFilter(_) => "cfilter",
276            NetworkMessage::GetCFHeaders(_) => "getcfheaders",
277            NetworkMessage::CFHeaders(_) => "cfheaders",
278            NetworkMessage::GetCFCheckpt(_) => "getcfcheckpt",
279            NetworkMessage::CFCheckpt(_) => "cfcheckpt",
280            NetworkMessage::SendCmpct(_) => "sendcmpct",
281            NetworkMessage::CmpctBlock(_) => "cmpctblock",
282            NetworkMessage::GetBlockTxn(_) => "getblocktxn",
283            NetworkMessage::BlockTxn(_) => "blocktxn",
284            NetworkMessage::Alert(_) => "alert",
285            NetworkMessage::Reject(_) => "reject",
286            NetworkMessage::FeeFilter(_) => "feefilter",
287            NetworkMessage::WtxidRelay => "wtxidrelay",
288            NetworkMessage::AddrV2(_) => "addrv2",
289            NetworkMessage::SendAddrV2 => "sendaddrv2",
290            NetworkMessage::Unknown { .. } => "unknown",
291        }
292    }
293
294    /// Return the CommandString for the message command.
295    pub fn command(&self) -> CommandString {
296        match *self {
297            NetworkMessage::Unknown { command: ref c, .. } => c.clone(),
298            _ => CommandString::try_from_static(self.cmd()).expect("cmd returns valid commands"),
299        }
300    }
301}
302
303impl RawNetworkMessage {
304    /// Creates a [RawNetworkMessage]
305    pub fn new(magic: Magic, payload: NetworkMessage) -> Self {
306        let mut engine = sha256d::Hash::engine();
307        let payload_len = payload.consensus_encode(&mut engine).expect("engine doesn't error");
308        let payload_len = u32::try_from(payload_len).expect("network message use u32 as length");
309        let checksum = sha256d::Hash::from_engine(engine);
310        let checksum = [checksum[0], checksum[1], checksum[2], checksum[3]];
311        Self { magic, payload, payload_len, checksum }
312    }
313
314    /// Consumes the [RawNetworkMessage] instance and returns the inner payload.
315    pub fn into_payload(self) -> NetworkMessage { self.payload }
316
317    /// The actual message data
318    pub fn payload(&self) -> &NetworkMessage { &self.payload }
319
320    /// Magic bytes to identify the network these messages are meant for
321    pub fn magic(&self) -> &Magic { &self.magic }
322
323    /// Return the message command as a static string reference.
324    ///
325    /// This returns `"unknown"` for [NetworkMessage::Unknown],
326    /// regardless of the actual command in the unknown message.
327    /// Use the [Self::command] method to get the command for unknown messages.
328    pub fn cmd(&self) -> &'static str { self.payload.cmd() }
329
330    /// Return the CommandString for the message command.
331    pub fn command(&self) -> CommandString { self.payload.command() }
332}
333
334struct HeaderSerializationWrapper<'a>(&'a Vec<block::Header>);
335
336impl<'a> Encodable for HeaderSerializationWrapper<'a> {
337    #[inline]
338    fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
339        let mut len = 0;
340        len += VarInt::from(self.0.len()).consensus_encode(w)?;
341        for header in self.0.iter() {
342            len += header.consensus_encode(w)?;
343            len += 0u8.consensus_encode(w)?;
344        }
345        Ok(len)
346    }
347}
348
349impl Encodable for NetworkMessage {
350    fn consensus_encode<W: Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> {
351        match self {
352            NetworkMessage::Version(ref dat) => dat.consensus_encode(writer),
353            NetworkMessage::Addr(ref dat) => dat.consensus_encode(writer),
354            NetworkMessage::Inv(ref dat) => dat.consensus_encode(writer),
355            NetworkMessage::GetData(ref dat) => dat.consensus_encode(writer),
356            NetworkMessage::NotFound(ref dat) => dat.consensus_encode(writer),
357            NetworkMessage::GetBlocks(ref dat) => dat.consensus_encode(writer),
358            NetworkMessage::GetHeaders(ref dat) => dat.consensus_encode(writer),
359            NetworkMessage::Tx(ref dat) => dat.consensus_encode(writer),
360            NetworkMessage::Block(ref dat) => dat.consensus_encode(writer),
361            NetworkMessage::Headers(ref dat) =>
362                HeaderSerializationWrapper(dat).consensus_encode(writer),
363            NetworkMessage::Ping(ref dat) => dat.consensus_encode(writer),
364            NetworkMessage::Pong(ref dat) => dat.consensus_encode(writer),
365            NetworkMessage::MerkleBlock(ref dat) => dat.consensus_encode(writer),
366            NetworkMessage::FilterLoad(ref dat) => dat.consensus_encode(writer),
367            NetworkMessage::FilterAdd(ref dat) => dat.consensus_encode(writer),
368            NetworkMessage::GetCFilters(ref dat) => dat.consensus_encode(writer),
369            NetworkMessage::CFilter(ref dat) => dat.consensus_encode(writer),
370            NetworkMessage::GetCFHeaders(ref dat) => dat.consensus_encode(writer),
371            NetworkMessage::CFHeaders(ref dat) => dat.consensus_encode(writer),
372            NetworkMessage::GetCFCheckpt(ref dat) => dat.consensus_encode(writer),
373            NetworkMessage::CFCheckpt(ref dat) => dat.consensus_encode(writer),
374            NetworkMessage::SendCmpct(ref dat) => dat.consensus_encode(writer),
375            NetworkMessage::CmpctBlock(ref dat) => dat.consensus_encode(writer),
376            NetworkMessage::GetBlockTxn(ref dat) => dat.consensus_encode(writer),
377            NetworkMessage::BlockTxn(ref dat) => dat.consensus_encode(writer),
378            NetworkMessage::Alert(ref dat) => dat.consensus_encode(writer),
379            NetworkMessage::Reject(ref dat) => dat.consensus_encode(writer),
380            NetworkMessage::FeeFilter(ref dat) => dat.consensus_encode(writer),
381            NetworkMessage::AddrV2(ref dat) => dat.consensus_encode(writer),
382            NetworkMessage::Verack
383            | NetworkMessage::SendHeaders
384            | NetworkMessage::MemPool
385            | NetworkMessage::GetAddr
386            | NetworkMessage::WtxidRelay
387            | NetworkMessage::FilterClear
388            | NetworkMessage::SendAddrV2 => Ok(0),
389            NetworkMessage::Unknown { payload: ref data, .. } => data.consensus_encode(writer),
390        }
391    }
392}
393
394impl Encodable for RawNetworkMessage {
395    fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
396        let mut len = 0;
397        len += self.magic.consensus_encode(w)?;
398        len += self.command().consensus_encode(w)?;
399        len += self.payload_len.consensus_encode(w)?;
400        len += self.checksum.consensus_encode(w)?;
401        len += self.payload().consensus_encode(w)?;
402        Ok(len)
403    }
404}
405
406struct HeaderDeserializationWrapper(Vec<block::Header>);
407
408impl Decodable for HeaderDeserializationWrapper {
409    #[inline]
410    fn consensus_decode_from_finite_reader<R: Read + ?Sized>(
411        r: &mut R,
412    ) -> Result<Self, encode::Error> {
413        let len = VarInt::consensus_decode(r)?.0;
414        // should be above usual number of items to avoid
415        // allocation
416        let mut ret = Vec::with_capacity(core::cmp::min(1024 * 16, len as usize));
417        for _ in 0..len {
418            ret.push(Decodable::consensus_decode(r)?);
419            if u8::consensus_decode(r)? != 0u8 {
420                return Err(encode::Error::ParseFailed(
421                    "Headers message should not contain transactions",
422                ));
423            }
424        }
425        Ok(HeaderDeserializationWrapper(ret))
426    }
427
428    #[inline]
429    fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
430        Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE as u64))
431    }
432}
433
434impl Decodable for RawNetworkMessage {
435    fn consensus_decode_from_finite_reader<R: Read + ?Sized>(
436        r: &mut R,
437    ) -> Result<Self, encode::Error> {
438        let magic = Decodable::consensus_decode_from_finite_reader(r)?;
439        let cmd = CommandString::consensus_decode_from_finite_reader(r)?;
440        let checked_data = CheckedData::consensus_decode_from_finite_reader(r)?;
441        let checksum = checked_data.checksum();
442        let raw_payload = checked_data.into_data();
443        let payload_len = raw_payload.len() as u32;
444
445        let mut mem_d = raw_payload.as_slice();
446        let payload = match &cmd.0[..] {
447            "version" =>
448                NetworkMessage::Version(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
449            "verack" => NetworkMessage::Verack,
450            "addr" =>
451                NetworkMessage::Addr(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
452            "inv" =>
453                NetworkMessage::Inv(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
454            "getdata" =>
455                NetworkMessage::GetData(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
456            "notfound" => NetworkMessage::NotFound(Decodable::consensus_decode_from_finite_reader(
457                &mut mem_d,
458            )?),
459            "getblocks" => NetworkMessage::GetBlocks(
460                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
461            ),
462            "getheaders" => NetworkMessage::GetHeaders(
463                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
464            ),
465            "mempool" => NetworkMessage::MemPool,
466            "block" =>
467                NetworkMessage::Block(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
468            "headers" => NetworkMessage::Headers(
469                HeaderDeserializationWrapper::consensus_decode_from_finite_reader(&mut mem_d)?.0,
470            ),
471            "sendheaders" => NetworkMessage::SendHeaders,
472            "getaddr" => NetworkMessage::GetAddr,
473            "ping" =>
474                NetworkMessage::Ping(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
475            "pong" =>
476                NetworkMessage::Pong(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
477            "merkleblock" => NetworkMessage::MerkleBlock(
478                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
479            ),
480            "filterload" => NetworkMessage::FilterLoad(
481                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
482            ),
483            "filteradd" => NetworkMessage::FilterAdd(
484                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
485            ),
486            "filterclear" => NetworkMessage::FilterClear,
487            "tx" => NetworkMessage::Tx(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
488            "getcfilters" => NetworkMessage::GetCFilters(
489                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
490            ),
491            "cfilter" =>
492                NetworkMessage::CFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
493            "getcfheaders" => NetworkMessage::GetCFHeaders(
494                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
495            ),
496            "cfheaders" => NetworkMessage::CFHeaders(
497                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
498            ),
499            "getcfcheckpt" => NetworkMessage::GetCFCheckpt(
500                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
501            ),
502            "cfcheckpt" => NetworkMessage::CFCheckpt(
503                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
504            ),
505            "reject" =>
506                NetworkMessage::Reject(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
507            "alert" =>
508                NetworkMessage::Alert(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
509            "feefilter" => NetworkMessage::FeeFilter(
510                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
511            ),
512            "sendcmpct" => NetworkMessage::SendCmpct(
513                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
514            ),
515            "cmpctblock" => NetworkMessage::CmpctBlock(
516                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
517            ),
518            "getblocktxn" => NetworkMessage::GetBlockTxn(
519                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
520            ),
521            "blocktxn" => NetworkMessage::BlockTxn(Decodable::consensus_decode_from_finite_reader(
522                &mut mem_d,
523            )?),
524            "wtxidrelay" => NetworkMessage::WtxidRelay,
525            "addrv2" =>
526                NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
527            "sendaddrv2" => NetworkMessage::SendAddrV2,
528            _ => NetworkMessage::Unknown { command: cmd, payload: raw_payload },
529        };
530        Ok(RawNetworkMessage { magic, payload, payload_len, checksum })
531    }
532
533    #[inline]
534    fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
535        Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE as u64))
536    }
537}
538
539#[cfg(test)]
540mod test {
541    use std::net::Ipv4Addr;
542
543    use hashes::sha256d::Hash;
544    use hashes::Hash as HashTrait;
545    use hex::test_hex_unwrap as hex;
546
547    use super::message_network::{Reject, RejectReason, VersionMessage};
548    use super::*;
549    use crate::bip152::BlockTransactionsRequest;
550    use crate::blockdata::block::Block;
551    use crate::blockdata::script::ScriptBuf;
552    use crate::blockdata::transaction::Transaction;
553    use crate::consensus::encode::{deserialize, deserialize_partial, serialize};
554    use crate::p2p::address::AddrV2;
555    use crate::p2p::message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory};
556    use crate::p2p::message_bloom::{BloomFlags, FilterAdd, FilterLoad};
557    use crate::p2p::message_compact_blocks::{GetBlockTxn, SendCmpct};
558    use crate::p2p::message_filter::{
559        CFCheckpt, CFHeaders, CFilter, GetCFCheckpt, GetCFHeaders, GetCFilters,
560    };
561    use crate::p2p::ServiceFlags;
562
563    fn hash(slice: [u8; 32]) -> Hash { Hash::from_slice(&slice).unwrap() }
564
565    #[test]
566    fn full_round_ser_der_raw_network_message_test() {
567        let version_msg: VersionMessage = deserialize(&hex!("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001")).unwrap();
568        let tx: Transaction = deserialize(&hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000")).unwrap();
569        let block: Block = deserialize(&include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw")[..]).unwrap();
570        let header: block::Header = deserialize(&hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b")).unwrap();
571        let script: ScriptBuf =
572            deserialize(&hex!("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac")).unwrap();
573        let merkle_block: MerkleBlock = deserialize(&hex!("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101")).unwrap();
574        let cmptblock = deserialize(&hex!("00000030d923ad36ff2d955abab07f8a0a6e813bc6e066b973e780c5e36674cad5d1cd1f6e265f2a17a0d35cbe701fe9d06e2c6324cfe135f6233e8b767bfa3fb4479b71115dc562ffff7f2006000000000000000000000000010002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0302ee00ffffffff0100f9029500000000015100000000")).unwrap();
575        let blocktxn = deserialize(&hex!("2e93c0cff39ff605020072d96bc3a8d20b8447e294d08092351c8583e08d9b5a01020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402dc0000ffffffff0200f90295000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000")).unwrap();
576
577        let msgs = vec![
578            NetworkMessage::Version(version_msg),
579            NetworkMessage::Verack,
580            NetworkMessage::Addr(vec![(
581                45,
582                Address::new(&([123, 255, 000, 100], 833).into(), ServiceFlags::NETWORK),
583            )]),
584            NetworkMessage::Inv(vec![Inventory::Block(hash([8u8; 32]).into())]),
585            NetworkMessage::GetData(vec![Inventory::Transaction(hash([45u8; 32]).into())]),
586            NetworkMessage::NotFound(vec![Inventory::Error]),
587            NetworkMessage::GetBlocks(GetBlocksMessage::new(
588                vec![hash([1u8; 32]).into(), hash([4u8; 32]).into()],
589                hash([5u8; 32]).into(),
590            )),
591            NetworkMessage::GetHeaders(GetHeadersMessage::new(
592                vec![hash([10u8; 32]).into(), hash([40u8; 32]).into()],
593                hash([50u8; 32]).into(),
594            )),
595            NetworkMessage::MemPool,
596            NetworkMessage::Tx(tx),
597            NetworkMessage::Block(block),
598            NetworkMessage::Headers(vec![header]),
599            NetworkMessage::SendHeaders,
600            NetworkMessage::GetAddr,
601            NetworkMessage::Ping(15),
602            NetworkMessage::Pong(23),
603            NetworkMessage::MerkleBlock(merkle_block),
604            NetworkMessage::FilterLoad(FilterLoad {
605                filter: hex!("03614e9b050000000000000001"),
606                hash_funcs: 1,
607                tweak: 2,
608                flags: BloomFlags::All,
609            }),
610            NetworkMessage::FilterAdd(FilterAdd { data: script.as_bytes().to_vec() }),
611            NetworkMessage::FilterAdd(FilterAdd {
612                data: hash([29u8; 32]).as_byte_array().to_vec(),
613            }),
614            NetworkMessage::FilterClear,
615            NetworkMessage::GetCFilters(GetCFilters {
616                filter_type: 2,
617                start_height: 52,
618                stop_hash: hash([42u8; 32]).into(),
619            }),
620            NetworkMessage::CFilter(CFilter {
621                filter_type: 7,
622                block_hash: hash([25u8; 32]).into(),
623                filter: vec![1, 2, 3],
624            }),
625            NetworkMessage::GetCFHeaders(GetCFHeaders {
626                filter_type: 4,
627                start_height: 102,
628                stop_hash: hash([47u8; 32]).into(),
629            }),
630            NetworkMessage::CFHeaders(CFHeaders {
631                filter_type: 13,
632                stop_hash: hash([53u8; 32]).into(),
633                previous_filter_header: hash([12u8; 32]).into(),
634                filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()],
635            }),
636            NetworkMessage::GetCFCheckpt(GetCFCheckpt {
637                filter_type: 17,
638                stop_hash: hash([25u8; 32]).into(),
639            }),
640            NetworkMessage::CFCheckpt(CFCheckpt {
641                filter_type: 27,
642                stop_hash: hash([77u8; 32]).into(),
643                filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()],
644            }),
645            NetworkMessage::Alert(vec![45, 66, 3, 2, 6, 8, 9, 12, 3, 130]),
646            NetworkMessage::Reject(Reject {
647                message: "Test reject".into(),
648                ccode: RejectReason::Duplicate,
649                reason: "Cause".into(),
650                hash: hash([255u8; 32]),
651            }),
652            NetworkMessage::FeeFilter(1000),
653            NetworkMessage::WtxidRelay,
654            NetworkMessage::AddrV2(vec![AddrV2Message {
655                addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)),
656                port: 0,
657                services: ServiceFlags::NONE,
658                time: 0,
659            }]),
660            NetworkMessage::SendAddrV2,
661            NetworkMessage::CmpctBlock(cmptblock),
662            NetworkMessage::GetBlockTxn(GetBlockTxn {
663                txs_request: BlockTransactionsRequest {
664                    block_hash: hash([11u8; 32]).into(),
665                    indexes: vec![0, 1, 2, 3, 10, 3002],
666                },
667            }),
668            NetworkMessage::BlockTxn(blocktxn),
669            NetworkMessage::SendCmpct(SendCmpct { send_compact: true, version: 8333 }),
670        ];
671
672        for msg in msgs {
673            let raw_msg = RawNetworkMessage::new(Magic::from_bytes([57, 0, 0, 0]), msg);
674            assert_eq!(deserialize::<RawNetworkMessage>(&serialize(&raw_msg)).unwrap(), raw_msg);
675        }
676    }
677
678    #[test]
679    fn commandstring_test() {
680        // Test converting.
681        assert_eq!(
682            CommandString::try_from_static("AndrewAndrew").unwrap().as_ref(),
683            "AndrewAndrew"
684        );
685        assert!(CommandString::try_from_static("AndrewAndrewA").is_err());
686
687        // Test serializing.
688        let cs = CommandString("Andrew".into());
689        assert_eq!(serialize(&cs), vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
690
691        // Test deserializing
692        let cs: Result<CommandString, _> =
693            deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
694        assert!(cs.is_ok());
695        assert_eq!(cs.as_ref().unwrap().to_string(), "Andrew".to_owned());
696        assert_eq!(cs.unwrap(), CommandString::try_from_static("Andrew").unwrap());
697
698        let short_cs: Result<CommandString, _> =
699            deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
700        assert!(short_cs.is_err());
701    }
702
703    #[test]
704    #[rustfmt::skip]
705    fn serialize_verack_test() {
706        assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::Verack)),
707                   vec![0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61,
708                        0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709                        0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
710    }
711
712    #[test]
713    #[rustfmt::skip]
714    fn serialize_ping_test() {
715        assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::Ping(100))),
716                   vec![0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67,
717                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718                        0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d,
719                        0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
720    }
721
722    #[test]
723    #[rustfmt::skip]
724    fn serialize_mempool_test() {
725        assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::MemPool)),
726                   vec![0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70,
727                        0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
728                        0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
729    }
730
731    #[test]
732    #[rustfmt::skip]
733    fn serialize_getaddr_test() {
734        assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::GetAddr)),
735                   vec![0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
736                        0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
737                        0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
738    }
739
740    #[test]
741    fn deserialize_getaddr_test() {
742        #[rustfmt::skip]
743        let msg = deserialize(&[
744            0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
745            0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
746            0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2
747        ]);
748        let preimage = RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::GetAddr);
749        assert!(msg.is_ok());
750        let msg: RawNetworkMessage = msg.unwrap();
751        assert_eq!(preimage.magic, msg.magic);
752        assert_eq!(preimage.payload, msg.payload);
753    }
754
755    #[test]
756    fn deserialize_version_test() {
757        #[rustfmt::skip]
758        let msg = deserialize::<RawNetworkMessage>(&[
759            0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73,
760            0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
761            0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27,
762            0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00,
763            0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c,
764            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
767            0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04,
768            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771            0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1,
772            0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68,
773            0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31,
774            0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01
775        ]);
776
777        assert!(msg.is_ok());
778        let msg = msg.unwrap();
779        assert_eq!(msg.magic, Magic::BITCOIN);
780        if let NetworkMessage::Version(version_msg) = msg.payload {
781            assert_eq!(version_msg.version, 70015);
782            assert_eq!(
783                version_msg.services,
784                ServiceFlags::NETWORK
785                    | ServiceFlags::BLOOM
786                    | ServiceFlags::WITNESS
787                    | ServiceFlags::NETWORK_LIMITED
788            );
789            assert_eq!(version_msg.timestamp, 1548554224);
790            assert_eq!(version_msg.nonce, 13952548347456104954);
791            assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
792            assert_eq!(version_msg.start_height, 560275);
793            assert!(version_msg.relay);
794        } else {
795            panic!("Wrong message type");
796        }
797    }
798
799    #[test]
800    fn deserialize_partial_message_test() {
801        #[rustfmt::skip]
802        let data = [
803            0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73,
804            0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
805            0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27,
806            0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00,
807            0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c,
808            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
809            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
810            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
811            0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04,
812            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815            0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1,
816            0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68,
817            0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31,
818            0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01, 0x00, 0x00
819        ];
820        let msg = deserialize_partial::<RawNetworkMessage>(&data);
821        assert!(msg.is_ok());
822
823        let (msg, consumed) = msg.unwrap();
824        assert_eq!(consumed, data.to_vec().len() - 2);
825        assert_eq!(msg.magic, Magic::BITCOIN);
826        if let NetworkMessage::Version(version_msg) = msg.payload {
827            assert_eq!(version_msg.version, 70015);
828            assert_eq!(
829                version_msg.services,
830                ServiceFlags::NETWORK
831                    | ServiceFlags::BLOOM
832                    | ServiceFlags::WITNESS
833                    | ServiceFlags::NETWORK_LIMITED
834            );
835            assert_eq!(version_msg.timestamp, 1548554224);
836            assert_eq!(version_msg.nonce, 13952548347456104954);
837            assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
838            assert_eq!(version_msg.start_height, 560275);
839            assert!(version_msg.relay);
840        } else {
841            panic!("Wrong message type");
842        }
843    }
844}