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 {
316        self.payload
317    }
318
319    /// The actual message data
320    pub fn payload(&self) -> &NetworkMessage { &self.payload }
321
322    /// Magic bytes to identify the network these messages are meant for
323    pub fn magic(&self) -> &Magic { &self.magic }
324
325    /// Return the message command as a static string reference.
326    ///
327    /// This returns `"unknown"` for [NetworkMessage::Unknown],
328    /// regardless of the actual command in the unknown message.
329    /// Use the [Self::command] method to get the command for unknown messages.
330    pub fn cmd(&self) -> &'static str { self.payload.cmd() }
331
332    /// Return the CommandString for the message command.
333    pub fn command(&self) -> CommandString { self.payload.command() }
334}
335
336struct HeaderSerializationWrapper<'a>(&'a Vec<block::Header>);
337
338impl<'a> Encodable for HeaderSerializationWrapper<'a> {
339    #[inline]
340    fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
341        let mut len = 0;
342        len += VarInt::from(self.0.len()).consensus_encode(w)?;
343        for header in self.0.iter() {
344            len += header.consensus_encode(w)?;
345            len += 0u8.consensus_encode(w)?;
346        }
347        Ok(len)
348    }
349}
350
351impl Encodable for NetworkMessage {
352    fn consensus_encode<W: Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> {
353        match self {
354            NetworkMessage::Version(ref dat) => dat.consensus_encode(writer),
355            NetworkMessage::Addr(ref dat) => dat.consensus_encode(writer),
356            NetworkMessage::Inv(ref dat) => dat.consensus_encode(writer),
357            NetworkMessage::GetData(ref dat) => dat.consensus_encode(writer),
358            NetworkMessage::NotFound(ref dat) => dat.consensus_encode(writer),
359            NetworkMessage::GetBlocks(ref dat) => dat.consensus_encode(writer),
360            NetworkMessage::GetHeaders(ref dat) => dat.consensus_encode(writer),
361            NetworkMessage::Tx(ref dat) => dat.consensus_encode(writer),
362            NetworkMessage::Block(ref dat) => dat.consensus_encode(writer),
363            NetworkMessage::Headers(ref dat) =>
364                HeaderSerializationWrapper(dat).consensus_encode(writer),
365            NetworkMessage::Ping(ref dat) => dat.consensus_encode(writer),
366            NetworkMessage::Pong(ref dat) => dat.consensus_encode(writer),
367            NetworkMessage::MerkleBlock(ref dat) => dat.consensus_encode(writer),
368            NetworkMessage::FilterLoad(ref dat) => dat.consensus_encode(writer),
369            NetworkMessage::FilterAdd(ref dat) => dat.consensus_encode(writer),
370            NetworkMessage::GetCFilters(ref dat) => dat.consensus_encode(writer),
371            NetworkMessage::CFilter(ref dat) => dat.consensus_encode(writer),
372            NetworkMessage::GetCFHeaders(ref dat) => dat.consensus_encode(writer),
373            NetworkMessage::CFHeaders(ref dat) => dat.consensus_encode(writer),
374            NetworkMessage::GetCFCheckpt(ref dat) => dat.consensus_encode(writer),
375            NetworkMessage::CFCheckpt(ref dat) => dat.consensus_encode(writer),
376            NetworkMessage::SendCmpct(ref dat) => dat.consensus_encode(writer),
377            NetworkMessage::CmpctBlock(ref dat) => dat.consensus_encode(writer),
378            NetworkMessage::GetBlockTxn(ref dat) => dat.consensus_encode(writer),
379            NetworkMessage::BlockTxn(ref dat) => dat.consensus_encode(writer),
380            NetworkMessage::Alert(ref dat) => dat.consensus_encode(writer),
381            NetworkMessage::Reject(ref dat) => dat.consensus_encode(writer),
382            NetworkMessage::FeeFilter(ref dat) => dat.consensus_encode(writer),
383            NetworkMessage::AddrV2(ref dat) => dat.consensus_encode(writer),
384            NetworkMessage::Verack
385            | NetworkMessage::SendHeaders
386            | NetworkMessage::MemPool
387            | NetworkMessage::GetAddr
388            | NetworkMessage::WtxidRelay
389            | NetworkMessage::FilterClear
390            | NetworkMessage::SendAddrV2 => Ok(0),
391            NetworkMessage::Unknown { payload: ref data, .. } => data.consensus_encode(writer),
392        }
393    }
394}
395
396impl Encodable for RawNetworkMessage {
397    fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
398        let mut len = 0;
399        len += self.magic.consensus_encode(w)?;
400        len += self.command().consensus_encode(w)?;
401        len += self.payload_len.consensus_encode(w)?;
402        len += self.checksum.consensus_encode(w)?;
403        len += self.payload().consensus_encode(w)?;
404        Ok(len)
405    }
406}
407
408struct HeaderDeserializationWrapper(Vec<block::Header>);
409
410impl Decodable for HeaderDeserializationWrapper {
411    #[inline]
412    fn consensus_decode_from_finite_reader<R: Read + ?Sized>(
413        r: &mut R,
414    ) -> Result<Self, encode::Error> {
415        let len = VarInt::consensus_decode(r)?.0;
416        // should be above usual number of items to avoid
417        // allocation
418        let mut ret = Vec::with_capacity(core::cmp::min(1024 * 16, len as usize));
419        for _ in 0..len {
420            ret.push(Decodable::consensus_decode(r)?);
421            if u8::consensus_decode(r)? != 0u8 {
422                return Err(encode::Error::ParseFailed(
423                    "Headers message should not contain transactions",
424                ));
425            }
426        }
427        Ok(HeaderDeserializationWrapper(ret))
428    }
429
430    #[inline]
431    fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
432        Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE as u64))
433    }
434}
435
436impl Decodable for RawNetworkMessage {
437    fn consensus_decode_from_finite_reader<R: Read + ?Sized>(
438        r: &mut R,
439    ) -> Result<Self, encode::Error> {
440        let magic = Decodable::consensus_decode_from_finite_reader(r)?;
441        let cmd = CommandString::consensus_decode_from_finite_reader(r)?;
442        let checked_data = CheckedData::consensus_decode_from_finite_reader(r)?;
443        let checksum = checked_data.checksum();
444        let raw_payload = checked_data.into_data();
445        let payload_len = raw_payload.len() as u32;
446
447        let mut mem_d = raw_payload.as_slice();
448        let payload = match &cmd.0[..] {
449            "version" =>
450                NetworkMessage::Version(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
451            "verack" => NetworkMessage::Verack,
452            "addr" =>
453                NetworkMessage::Addr(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
454            "inv" =>
455                NetworkMessage::Inv(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
456            "getdata" =>
457                NetworkMessage::GetData(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
458            "notfound" => NetworkMessage::NotFound(Decodable::consensus_decode_from_finite_reader(
459                &mut mem_d,
460            )?),
461            "getblocks" => NetworkMessage::GetBlocks(
462                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
463            ),
464            "getheaders" => NetworkMessage::GetHeaders(
465                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
466            ),
467            "mempool" => NetworkMessage::MemPool,
468            "block" =>
469                NetworkMessage::Block(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
470            "headers" => NetworkMessage::Headers(
471                HeaderDeserializationWrapper::consensus_decode_from_finite_reader(&mut mem_d)?.0,
472            ),
473            "sendheaders" => NetworkMessage::SendHeaders,
474            "getaddr" => NetworkMessage::GetAddr,
475            "ping" =>
476                NetworkMessage::Ping(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
477            "pong" =>
478                NetworkMessage::Pong(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
479            "merkleblock" => NetworkMessage::MerkleBlock(
480                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
481            ),
482            "filterload" => NetworkMessage::FilterLoad(
483                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
484            ),
485            "filteradd" => NetworkMessage::FilterAdd(
486                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
487            ),
488            "filterclear" => NetworkMessage::FilterClear,
489            "tx" => NetworkMessage::Tx(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
490            "getcfilters" => NetworkMessage::GetCFilters(
491                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
492            ),
493            "cfilter" =>
494                NetworkMessage::CFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
495            "getcfheaders" => NetworkMessage::GetCFHeaders(
496                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
497            ),
498            "cfheaders" => NetworkMessage::CFHeaders(
499                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
500            ),
501            "getcfcheckpt" => NetworkMessage::GetCFCheckpt(
502                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
503            ),
504            "cfcheckpt" => NetworkMessage::CFCheckpt(
505                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
506            ),
507            "reject" =>
508                NetworkMessage::Reject(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
509            "alert" =>
510                NetworkMessage::Alert(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
511            "feefilter" => NetworkMessage::FeeFilter(
512                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
513            ),
514            "sendcmpct" => NetworkMessage::SendCmpct(
515                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
516            ),
517            "cmpctblock" => NetworkMessage::CmpctBlock(
518                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
519            ),
520            "getblocktxn" => NetworkMessage::GetBlockTxn(
521                Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
522            ),
523            "blocktxn" => NetworkMessage::BlockTxn(Decodable::consensus_decode_from_finite_reader(
524                &mut mem_d,
525            )?),
526            "wtxidrelay" => NetworkMessage::WtxidRelay,
527            "addrv2" =>
528                NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
529            "sendaddrv2" => NetworkMessage::SendAddrV2,
530            _ => NetworkMessage::Unknown { command: cmd, payload: raw_payload },
531        };
532        Ok(RawNetworkMessage { magic, payload, payload_len, checksum })
533    }
534
535    #[inline]
536    fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
537        Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE as u64))
538    }
539}
540
541#[cfg(test)]
542mod test {
543    use std::net::Ipv4Addr;
544
545    use hashes::sha256d::Hash;
546    use hashes::Hash as HashTrait;
547    use hex::test_hex_unwrap as hex;
548
549    use super::message_network::{Reject, RejectReason, VersionMessage};
550    use super::*;
551    use crate::bip152::BlockTransactionsRequest;
552    use crate::blockdata::block::Block;
553    use crate::blockdata::script::ScriptBuf;
554    use crate::blockdata::transaction::Transaction;
555    use crate::consensus::encode::{deserialize, deserialize_partial, serialize};
556    use crate::p2p::address::AddrV2;
557    use crate::p2p::message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory};
558    use crate::p2p::message_bloom::{BloomFlags, FilterAdd, FilterLoad};
559    use crate::p2p::message_compact_blocks::{GetBlockTxn, SendCmpct};
560    use crate::p2p::message_filter::{
561        CFCheckpt, CFHeaders, CFilter, GetCFCheckpt, GetCFHeaders, GetCFilters,
562    };
563    use crate::p2p::ServiceFlags;
564
565    fn hash(slice: [u8; 32]) -> Hash { Hash::from_slice(&slice).unwrap() }
566
567    #[test]
568    fn full_round_ser_der_raw_network_message_test() {
569        let version_msg: VersionMessage = deserialize(&hex!("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001")).unwrap();
570        let tx: Transaction = deserialize(&hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000")).unwrap();
571        let block: Block = deserialize(&include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw")[..]).unwrap();
572        let header: block::Header = deserialize(&hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b")).unwrap();
573        let script: ScriptBuf =
574            deserialize(&hex!("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac")).unwrap();
575        let merkle_block: MerkleBlock = deserialize(&hex!("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101")).unwrap();
576        let cmptblock = deserialize(&hex!("00000030d923ad36ff2d955abab07f8a0a6e813bc6e066b973e780c5e36674cad5d1cd1f6e265f2a17a0d35cbe701fe9d06e2c6324cfe135f6233e8b767bfa3fb4479b71115dc562ffff7f2006000000000000000000000000010002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0302ee00ffffffff0100f9029500000000015100000000")).unwrap();
577        let blocktxn = deserialize(&hex!("2e93c0cff39ff605020072d96bc3a8d20b8447e294d08092351c8583e08d9b5a01020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402dc0000ffffffff0200f90295000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000")).unwrap();
578
579        let msgs = vec![
580            NetworkMessage::Version(version_msg),
581            NetworkMessage::Verack,
582            NetworkMessage::Addr(vec![(
583                45,
584                Address::new(&([123, 255, 000, 100], 833).into(), ServiceFlags::NETWORK),
585            )]),
586            NetworkMessage::Inv(vec![Inventory::Block(hash([8u8; 32]).into())]),
587            NetworkMessage::GetData(vec![Inventory::Transaction(hash([45u8; 32]).into())]),
588            NetworkMessage::NotFound(vec![Inventory::Error]),
589            NetworkMessage::GetBlocks(GetBlocksMessage::new(
590                vec![hash([1u8; 32]).into(), hash([4u8; 32]).into()],
591                hash([5u8; 32]).into(),
592            )),
593            NetworkMessage::GetHeaders(GetHeadersMessage::new(
594                vec![hash([10u8; 32]).into(), hash([40u8; 32]).into()],
595                hash([50u8; 32]).into(),
596            )),
597            NetworkMessage::MemPool,
598            NetworkMessage::Tx(tx),
599            NetworkMessage::Block(block),
600            NetworkMessage::Headers(vec![header]),
601            NetworkMessage::SendHeaders,
602            NetworkMessage::GetAddr,
603            NetworkMessage::Ping(15),
604            NetworkMessage::Pong(23),
605            NetworkMessage::MerkleBlock(merkle_block),
606            NetworkMessage::FilterLoad(FilterLoad {
607                filter: hex!("03614e9b050000000000000001"),
608                hash_funcs: 1,
609                tweak: 2,
610                flags: BloomFlags::All,
611            }),
612            NetworkMessage::FilterAdd(FilterAdd { data: script.as_bytes().to_vec() }),
613            NetworkMessage::FilterAdd(FilterAdd {
614                data: hash([29u8; 32]).as_byte_array().to_vec(),
615            }),
616            NetworkMessage::FilterClear,
617            NetworkMessage::GetCFilters(GetCFilters {
618                filter_type: 2,
619                start_height: 52,
620                stop_hash: hash([42u8; 32]).into(),
621            }),
622            NetworkMessage::CFilter(CFilter {
623                filter_type: 7,
624                block_hash: hash([25u8; 32]).into(),
625                filter: vec![1, 2, 3],
626            }),
627            NetworkMessage::GetCFHeaders(GetCFHeaders {
628                filter_type: 4,
629                start_height: 102,
630                stop_hash: hash([47u8; 32]).into(),
631            }),
632            NetworkMessage::CFHeaders(CFHeaders {
633                filter_type: 13,
634                stop_hash: hash([53u8; 32]).into(),
635                previous_filter_header: hash([12u8; 32]).into(),
636                filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()],
637            }),
638            NetworkMessage::GetCFCheckpt(GetCFCheckpt {
639                filter_type: 17,
640                stop_hash: hash([25u8; 32]).into(),
641            }),
642            NetworkMessage::CFCheckpt(CFCheckpt {
643                filter_type: 27,
644                stop_hash: hash([77u8; 32]).into(),
645                filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()],
646            }),
647            NetworkMessage::Alert(vec![45, 66, 3, 2, 6, 8, 9, 12, 3, 130]),
648            NetworkMessage::Reject(Reject {
649                message: "Test reject".into(),
650                ccode: RejectReason::Duplicate,
651                reason: "Cause".into(),
652                hash: hash([255u8; 32]),
653            }),
654            NetworkMessage::FeeFilter(1000),
655            NetworkMessage::WtxidRelay,
656            NetworkMessage::AddrV2(vec![AddrV2Message {
657                addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)),
658                port: 0,
659                services: ServiceFlags::NONE,
660                time: 0,
661            }]),
662            NetworkMessage::SendAddrV2,
663            NetworkMessage::CmpctBlock(cmptblock),
664            NetworkMessage::GetBlockTxn(GetBlockTxn {
665                txs_request: BlockTransactionsRequest {
666                    block_hash: hash([11u8; 32]).into(),
667                    indexes: vec![0, 1, 2, 3, 10, 3002],
668                },
669            }),
670            NetworkMessage::BlockTxn(blocktxn),
671            NetworkMessage::SendCmpct(SendCmpct { send_compact: true, version: 8333 }),
672        ];
673
674        for msg in msgs {
675            let raw_msg = RawNetworkMessage::new(Magic::from_bytes([57, 0, 0, 0]), msg);
676            assert_eq!(deserialize::<RawNetworkMessage>(&serialize(&raw_msg)).unwrap(), raw_msg);
677        }
678    }
679
680    #[test]
681    fn commandstring_test() {
682        // Test converting.
683        assert_eq!(
684            CommandString::try_from_static("AndrewAndrew").unwrap().as_ref(),
685            "AndrewAndrew"
686        );
687        assert!(CommandString::try_from_static("AndrewAndrewA").is_err());
688
689        // Test serializing.
690        let cs = CommandString("Andrew".into());
691        assert_eq!(serialize(&cs), vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
692
693        // Test deserializing
694        let cs: Result<CommandString, _> =
695            deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
696        assert!(cs.is_ok());
697        assert_eq!(cs.as_ref().unwrap().to_string(), "Andrew".to_owned());
698        assert_eq!(cs.unwrap(), CommandString::try_from_static("Andrew").unwrap());
699
700        let short_cs: Result<CommandString, _> =
701            deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
702        assert!(short_cs.is_err());
703    }
704
705    #[test]
706    #[rustfmt::skip]
707    fn serialize_verack_test() {
708        assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::Verack)),
709                   vec![0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61,
710                        0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711                        0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
712    }
713
714    #[test]
715    #[rustfmt::skip]
716    fn serialize_ping_test() {
717        assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::Ping(100))),
718                   vec![0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67,
719                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720                        0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d,
721                        0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
722    }
723
724    #[test]
725    #[rustfmt::skip]
726    fn serialize_mempool_test() {
727        assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::MemPool)),
728                   vec![0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70,
729                        0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
730                        0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
731    }
732
733    #[test]
734    #[rustfmt::skip]
735    fn serialize_getaddr_test() {
736        assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::GetAddr)),
737                   vec![0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
738                        0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
739                        0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
740    }
741
742    #[test]
743    fn deserialize_getaddr_test() {
744        #[rustfmt::skip]
745        let msg = deserialize(&[
746            0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
747            0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
748            0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2
749        ]);
750        let preimage = RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::GetAddr);
751        assert!(msg.is_ok());
752        let msg: RawNetworkMessage = msg.unwrap();
753        assert_eq!(preimage.magic, msg.magic);
754        assert_eq!(preimage.payload, msg.payload);
755    }
756
757    #[test]
758    fn deserialize_version_test() {
759        #[rustfmt::skip]
760        let msg = deserialize::<RawNetworkMessage>(&[
761            0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73,
762            0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
763            0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27,
764            0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00,
765            0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c,
766            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
769            0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04,
770            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773            0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1,
774            0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68,
775            0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31,
776            0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01
777        ]);
778
779        assert!(msg.is_ok());
780        let msg = msg.unwrap();
781        assert_eq!(msg.magic, Magic::BITCOIN);
782        if let NetworkMessage::Version(version_msg) = msg.payload {
783            assert_eq!(version_msg.version, 70015);
784            assert_eq!(
785                version_msg.services,
786                ServiceFlags::NETWORK
787                    | ServiceFlags::BLOOM
788                    | ServiceFlags::WITNESS
789                    | ServiceFlags::NETWORK_LIMITED
790            );
791            assert_eq!(version_msg.timestamp, 1548554224);
792            assert_eq!(version_msg.nonce, 13952548347456104954);
793            assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
794            assert_eq!(version_msg.start_height, 560275);
795            assert!(version_msg.relay);
796        } else {
797            panic!("Wrong message type");
798        }
799    }
800
801    #[test]
802    fn deserialize_partial_message_test() {
803        #[rustfmt::skip]
804        let data = [
805            0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73,
806            0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
807            0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27,
808            0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00,
809            0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c,
810            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
811            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
812            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
813            0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04,
814            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817            0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1,
818            0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68,
819            0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31,
820            0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01, 0x00, 0x00
821        ];
822        let msg = deserialize_partial::<RawNetworkMessage>(&data);
823        assert!(msg.is_ok());
824
825        let (msg, consumed) = msg.unwrap();
826        assert_eq!(consumed, data.to_vec().len() - 2);
827        assert_eq!(msg.magic, Magic::BITCOIN);
828        if let NetworkMessage::Version(version_msg) = msg.payload {
829            assert_eq!(version_msg.version, 70015);
830            assert_eq!(
831                version_msg.services,
832                ServiceFlags::NETWORK
833                    | ServiceFlags::BLOOM
834                    | ServiceFlags::WITNESS
835                    | ServiceFlags::NETWORK_LIMITED
836            );
837            assert_eq!(version_msg.timestamp, 1548554224);
838            assert_eq!(version_msg.nonce, 13952548347456104954);
839            assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
840            assert_eq!(version_msg.start_height, 560275);
841            assert!(version_msg.relay);
842        } else {
843            panic!("Wrong message type");
844        }
845    }
846}