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 {
316 self.payload
317 }
318
319 pub fn payload(&self) -> &NetworkMessage { &self.payload }
321
322 pub fn magic(&self) -> &Magic { &self.magic }
324
325 pub fn cmd(&self) -> &'static str { self.payload.cmd() }
331
332 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 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 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 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 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}