1use 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
24pub const MAX_INV_SIZE: usize = 50_000;
28
29pub const MAX_MSG_SIZE: usize = 5_000_000;
32
33#[derive(PartialEq, Eq, Clone, Debug)]
35pub struct CommandString(Cow<'static, str>);
36
37impl CommandString {
38 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#[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#[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#[derive(Clone, PartialEq, Eq, Debug)]
163pub enum NetworkMessage {
164 Version(message_network::VersionMessage),
166 Verack,
168 Addr(Vec<(u32, Address)>),
170 Inv(Vec<message_blockdata::Inventory>),
172 GetData(Vec<message_blockdata::Inventory>),
174 NotFound(Vec<message_blockdata::Inventory>),
176 GetBlocks(message_blockdata::GetBlocksMessage),
178 GetHeaders(message_blockdata::GetHeadersMessage),
180 MemPool,
182 Tx(transaction::Transaction),
184 Block(block::Block),
186 Headers(Vec<block::Header>),
188 SendHeaders,
190 GetAddr,
192 Ping(u64),
194 Pong(u64),
196 MerkleBlock(MerkleBlock),
198 FilterLoad(message_bloom::FilterLoad),
200 FilterAdd(message_bloom::FilterAdd),
202 FilterClear,
204 GetCFilters(message_filter::GetCFilters),
206 CFilter(message_filter::CFilter),
208 GetCFHeaders(message_filter::GetCFHeaders),
210 CFHeaders(message_filter::CFHeaders),
212 GetCFCheckpt(message_filter::GetCFCheckpt),
214 CFCheckpt(message_filter::CFCheckpt),
216 SendCmpct(message_compact_blocks::SendCmpct),
218 CmpctBlock(message_compact_blocks::CmpctBlock),
220 GetBlockTxn(message_compact_blocks::GetBlockTxn),
222 BlockTxn(message_compact_blocks::BlockTxn),
224 Alert(Vec<u8>),
226 Reject(message_network::Reject),
228 FeeFilter(i64),
230 WtxidRelay,
232 AddrV2(Vec<AddrV2Message>),
234 SendAddrV2,
236
237 Unknown {
239 command: CommandString,
241 payload: Vec<u8>,
243 },
244}
245
246impl NetworkMessage {
247 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 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 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 pub fn into_payload(self) -> NetworkMessage { self.payload }
316
317 pub fn payload(&self) -> &NetworkMessage { &self.payload }
319
320 pub fn magic(&self) -> &Magic { &self.magic }
322
323 pub fn cmd(&self) -> &'static str { self.payload.cmd() }
329
330 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 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 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 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 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}