1use crate::prelude::*;
11
12use core::{fmt, iter};
13use core::convert::TryFrom;
14
15use crate::io;
16use io::Read as _;
17use crate::blockdata::block;
18use crate::blockdata::transaction;
19use crate::network::address::{Address, AddrV2Message};
20use crate::network::{message_network, message_bloom};
21use crate::network::message_blockdata;
22use crate::network::message_filter;
23use crate::network::message_compact_blocks;
24use crate::consensus::encode::{CheckedData, Decodable, Encodable, VarInt};
25use crate::consensus::{encode, serialize};
26use crate::util::merkleblock::MerkleBlock;
27
28pub const MAX_INV_SIZE: usize = 50_000;
32
33pub const MAX_MSG_SIZE: usize = 5_000_000;
36
37#[derive(PartialEq, Eq, Clone, Debug)]
39pub struct CommandString(Cow<'static, str>);
40
41impl CommandString {
42 #[deprecated(note = "Use `TryFrom::try_from` or `CommandString::try_from_static`", since = "0.29.0")]
51 pub fn try_from<S: Into<Cow<'static, str>>>(s: S) -> Result<CommandString, CommandStringError> {
52 Self::try_from_static_cow(s.into())
53 }
54
55 pub fn try_from_static(s: &'static str) -> Result<CommandString, CommandStringError> {
65 Self::try_from_static_cow(s.into())
66 }
67
68 fn try_from_static_cow(cow: Cow<'static, str>) -> Result<CommandString, CommandStringError> {
69 if cow.len() > 12 {
70 Err(CommandStringError { cow })
71 } else {
72 Ok(CommandString(cow))
73 }
74 }
75}
76
77impl TryFrom<String> for CommandString {
78 type Error = CommandStringError;
79
80 fn try_from(value: String) -> Result<Self, Self::Error> {
81 Self::try_from_static_cow(value.into())
82 }
83}
84
85impl TryFrom<Box<str>> for CommandString {
86 type Error = CommandStringError;
87
88 fn try_from(value: Box<str>) -> Result<Self, Self::Error> {
89 Self::try_from_static_cow(String::from(value).into())
90 }
91}
92
93impl<'a> TryFrom<&'a str> for CommandString {
94 type Error = CommandStringError;
95
96 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
97 Self::try_from_static_cow(value.to_owned().into())
98 }
99}
100
101impl core::str::FromStr for CommandString {
102 type Err = CommandStringError;
103
104 fn from_str(s: &str) -> Result<Self, Self::Err> {
105 Self::try_from_static_cow(s.to_owned().into())
106 }
107}
108
109impl fmt::Display for CommandString {
110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111 f.write_str(self.0.as_ref())
112 }
113}
114
115impl AsRef<str> for CommandString {
116 fn as_ref(&self) -> &str {
117 self.0.as_ref()
118 }
119}
120
121impl Encodable for CommandString {
122 #[inline]
123 fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
124 let mut rawbytes = [0u8; 12];
125 let strbytes = self.0.as_bytes();
126 debug_assert!(strbytes.len() <= 12);
127 rawbytes[..strbytes.len()].copy_from_slice(strbytes);
128 rawbytes.consensus_encode(w)
129 }
130}
131
132impl Decodable for CommandString {
133 #[inline]
134 fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
135 let rawbytes: [u8; 12] = Decodable::consensus_decode(r)?;
136 let rv = iter::FromIterator::from_iter(
137 rawbytes
138 .iter()
139 .filter_map(|&u| if u > 0 { Some(u as char) } else { None })
140 );
141 Ok(CommandString(rv))
142 }
143}
144
145#[derive(Clone, Debug)]
149pub struct CommandStringError {
150 cow: Cow<'static, str>,
151}
152
153impl fmt::Display for CommandStringError {
154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155 write!(f, "the command string '{}' has length {} which is larger than 12", self.cow, self.cow.len())
156 }
157}
158
159#[cfg(feature = "std")]
160#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
161impl std::error::Error for CommandStringError {
162 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
163 None
164 }
165}
166
167#[derive(Clone, Debug, PartialEq, Eq)]
169pub struct RawNetworkMessage {
170 pub magic: u32,
172 pub payload: NetworkMessage
174}
175
176#[derive(Clone, PartialEq, Eq, Debug)]
179pub enum NetworkMessage {
180 Version(message_network::VersionMessage),
182 Verack,
184 Addr(Vec<(u32, Address)>),
186 Inv(Vec<message_blockdata::Inventory>),
188 GetData(Vec<message_blockdata::Inventory>),
190 NotFound(Vec<message_blockdata::Inventory>),
192 GetBlocks(message_blockdata::GetBlocksMessage),
194 GetHeaders(message_blockdata::GetHeadersMessage),
196 MemPool,
198 Tx(transaction::Transaction),
200 Block(block::Block),
202 Headers(Vec<block::BlockHeader>),
204 SendHeaders,
206 GetAddr,
208 Ping(u64),
213 Pong(u64),
215 MerkleBlock(MerkleBlock),
217 FilterLoad(message_bloom::FilterLoad),
219 FilterAdd(message_bloom::FilterAdd),
221 FilterClear,
223 GetCFilters(message_filter::GetCFilters),
225 CFilter(message_filter::CFilter),
227 GetCFHeaders(message_filter::GetCFHeaders),
229 CFHeaders(message_filter::CFHeaders),
231 GetCFCheckpt(message_filter::GetCFCheckpt),
233 CFCheckpt(message_filter::CFCheckpt),
235 SendCmpct(message_compact_blocks::SendCmpct),
237 CmpctBlock(message_compact_blocks::CmpctBlock),
239 GetBlockTxn(message_compact_blocks::GetBlockTxn),
241 BlockTxn(message_compact_blocks::BlockTxn),
243 Alert(Vec<u8>),
245 Reject(message_network::Reject),
247 FeeFilter(i64),
249 WtxidRelay,
251 AddrV2(Vec<AddrV2Message>),
253 SendAddrV2,
255
256 Unknown {
258 command: CommandString,
260 payload: Vec<u8>,
262 }
263}
264
265impl NetworkMessage {
266 pub fn cmd(&self) -> &'static str {
272 match *self {
273 NetworkMessage::Version(_) => "version",
274 NetworkMessage::Verack => "verack",
275 NetworkMessage::Addr(_) => "addr",
276 NetworkMessage::Inv(_) => "inv",
277 NetworkMessage::GetData(_) => "getdata",
278 NetworkMessage::NotFound(_) => "notfound",
279 NetworkMessage::GetBlocks(_) => "getblocks",
280 NetworkMessage::GetHeaders(_) => "getheaders",
281 NetworkMessage::MemPool => "mempool",
282 NetworkMessage::Tx(_) => "tx",
283 NetworkMessage::Block(_) => "block",
284 NetworkMessage::Headers(_) => "headers",
285 NetworkMessage::SendHeaders => "sendheaders",
286 NetworkMessage::GetAddr => "getaddr",
287 NetworkMessage::Ping(_) => "ping",
288 NetworkMessage::Pong(_) => "pong",
289 NetworkMessage::MerkleBlock(_) => "merkleblock",
290 NetworkMessage::FilterLoad(_) => "filterload",
291 NetworkMessage::FilterAdd(_) => "filteradd",
292 NetworkMessage::FilterClear => "filterclear",
293 NetworkMessage::GetCFilters(_) => "getcfilters",
294 NetworkMessage::CFilter(_) => "cfilter",
295 NetworkMessage::GetCFHeaders(_) => "getcfheaders",
296 NetworkMessage::CFHeaders(_) => "cfheaders",
297 NetworkMessage::GetCFCheckpt(_) => "getcfcheckpt",
298 NetworkMessage::CFCheckpt(_) => "cfcheckpt",
299 NetworkMessage::SendCmpct(_) => "sendcmpct",
300 NetworkMessage::CmpctBlock(_) => "cmpctblock",
301 NetworkMessage::GetBlockTxn(_) => "getblocktxn",
302 NetworkMessage::BlockTxn(_) => "blocktxn",
303 NetworkMessage::Alert(_) => "alert",
304 NetworkMessage::Reject(_) => "reject",
305 NetworkMessage::FeeFilter(_) => "feefilter",
306 NetworkMessage::WtxidRelay => "wtxidrelay",
307 NetworkMessage::AddrV2(_) => "addrv2",
308 NetworkMessage::SendAddrV2 => "sendaddrv2",
309 NetworkMessage::Unknown { .. } => "unknown",
310 }
311 }
312
313 pub fn command(&self) -> CommandString {
315 match *self {
316 NetworkMessage::Unknown { command: ref c, .. } => c.clone(),
317 _ => CommandString::try_from_static(self.cmd()).expect("cmd returns valid commands")
318 }
319 }
320}
321
322impl RawNetworkMessage {
323 pub fn cmd(&self) -> &'static str {
329 self.payload.cmd()
330 }
331
332 pub fn command(&self) -> CommandString {
334 self.payload.command()
335 }
336}
337
338struct HeaderSerializationWrapper<'a>(&'a Vec<block::BlockHeader>);
339
340impl<'a> Encodable for HeaderSerializationWrapper<'a> {
341 #[inline]
342 fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
343 let mut len = 0;
344 len += VarInt(self.0.len() as u64).consensus_encode(w)?;
345 for header in self.0.iter() {
346 len += header.consensus_encode(w)?;
347 len += 0u8.consensus_encode(w)?;
348 }
349 Ok(len)
350 }
351}
352
353impl Encodable for RawNetworkMessage {
354 fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
355 let mut len = 0;
356 len += self.magic.consensus_encode(w)?;
357 len += self.command().consensus_encode(w)?;
358 len += CheckedData(match self.payload {
359 NetworkMessage::Version(ref dat) => serialize(dat),
360 NetworkMessage::Addr(ref dat) => serialize(dat),
361 NetworkMessage::Inv(ref dat) => serialize(dat),
362 NetworkMessage::GetData(ref dat) => serialize(dat),
363 NetworkMessage::NotFound(ref dat) => serialize(dat),
364 NetworkMessage::GetBlocks(ref dat) => serialize(dat),
365 NetworkMessage::GetHeaders(ref dat) => serialize(dat),
366 NetworkMessage::Tx(ref dat) => serialize(dat),
367 NetworkMessage::Block(ref dat) => serialize(dat),
368 NetworkMessage::Headers(ref dat) => serialize(&HeaderSerializationWrapper(dat)),
369 NetworkMessage::Ping(ref dat) => serialize(dat),
370 NetworkMessage::Pong(ref dat) => serialize(dat),
371 NetworkMessage::MerkleBlock(ref dat) => serialize(dat),
372 NetworkMessage::FilterLoad(ref dat) => serialize(dat),
373 NetworkMessage::FilterAdd(ref dat) => serialize(dat),
374 NetworkMessage::GetCFilters(ref dat) => serialize(dat),
375 NetworkMessage::CFilter(ref dat) => serialize(dat),
376 NetworkMessage::GetCFHeaders(ref dat) => serialize(dat),
377 NetworkMessage::CFHeaders(ref dat) => serialize(dat),
378 NetworkMessage::GetCFCheckpt(ref dat) => serialize(dat),
379 NetworkMessage::CFCheckpt(ref dat) => serialize(dat),
380 NetworkMessage::SendCmpct(ref dat) => serialize(dat),
381 NetworkMessage::CmpctBlock(ref dat) => serialize(dat),
382 NetworkMessage::GetBlockTxn(ref dat) => serialize(dat),
383 NetworkMessage::BlockTxn(ref dat) => serialize(dat),
384 NetworkMessage::Alert(ref dat) => serialize(dat),
385 NetworkMessage::Reject(ref dat) => serialize(dat),
386 NetworkMessage::FeeFilter(ref data) => serialize(data),
387 NetworkMessage::AddrV2(ref dat) => serialize(dat),
388 NetworkMessage::Verack
389 | NetworkMessage::SendHeaders
390 | NetworkMessage::MemPool
391 | NetworkMessage::GetAddr
392 | NetworkMessage::WtxidRelay
393 | NetworkMessage::FilterClear
394 | NetworkMessage::SendAddrV2 => vec![],
395 NetworkMessage::Unknown { payload: ref data, .. } => serialize(data),
396 }).consensus_encode(w)?;
397 Ok(len)
398 }
399}
400
401struct HeaderDeserializationWrapper(Vec<block::BlockHeader>);
402
403impl Decodable for HeaderDeserializationWrapper {
404 #[inline]
405 fn consensus_decode_from_finite_reader<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
406 let len = VarInt::consensus_decode(r)?.0;
407 let mut ret = Vec::with_capacity(core::cmp::min(1024 * 16, len as usize));
410 for _ in 0..len {
411 ret.push(Decodable::consensus_decode(r)?);
412 if u8::consensus_decode(r)? != 0u8 {
413 return Err(encode::Error::ParseFailed("Headers message should not contain transactions"));
414 }
415 }
416 Ok(HeaderDeserializationWrapper(ret))
417 }
418
419 #[inline]
420 fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
421 Self::consensus_decode_from_finite_reader(r.take(MAX_MSG_SIZE as u64).by_ref())
422 }
423}
424
425impl Decodable for RawNetworkMessage {
426 fn consensus_decode_from_finite_reader<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
427 let magic = Decodable::consensus_decode_from_finite_reader(r)?;
428 let cmd = CommandString::consensus_decode_from_finite_reader(r)?;
429 let raw_payload = CheckedData::consensus_decode_from_finite_reader(r)?.0;
430
431 let mut mem_d = io::Cursor::new(raw_payload);
432 let payload = match &cmd.0[..] {
433 "version" => NetworkMessage::Version(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
434 "verack" => NetworkMessage::Verack,
435 "addr" => NetworkMessage::Addr(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
436 "inv" => NetworkMessage::Inv(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
437 "getdata" => NetworkMessage::GetData(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
438 "notfound" => NetworkMessage::NotFound(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
439 "getblocks" => NetworkMessage::GetBlocks(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
440 "getheaders" => NetworkMessage::GetHeaders(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
441 "mempool" => NetworkMessage::MemPool,
442 "block" => NetworkMessage::Block(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
443 "headers" => NetworkMessage::Headers(
444 HeaderDeserializationWrapper::consensus_decode_from_finite_reader(&mut mem_d)?.0
445 ),
446 "sendheaders" => NetworkMessage::SendHeaders,
447 "getaddr" => NetworkMessage::GetAddr,
448 "ping" => NetworkMessage::Ping(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
449 "pong" => NetworkMessage::Pong(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
450 "merkleblock" => NetworkMessage::MerkleBlock(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
451 "filterload" => NetworkMessage::FilterLoad(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
452 "filteradd" => NetworkMessage::FilterAdd(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
453 "filterclear" => NetworkMessage::FilterClear,
454 "tx" => NetworkMessage::Tx(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
455 "getcfilters" => NetworkMessage::GetCFilters(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
456 "cfilter" => NetworkMessage::CFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
457 "getcfheaders" => NetworkMessage::GetCFHeaders(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
458 "cfheaders" => NetworkMessage::CFHeaders(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
459 "getcfcheckpt" => NetworkMessage::GetCFCheckpt(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
460 "cfcheckpt" => NetworkMessage::CFCheckpt(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
461 "reject" => NetworkMessage::Reject(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
462 "alert" => NetworkMessage::Alert(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
463 "feefilter" => NetworkMessage::FeeFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
464 "sendcmpct" => NetworkMessage::SendCmpct(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
465 "cmpctblock" => NetworkMessage::CmpctBlock(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
466 "getblocktxn" => NetworkMessage::GetBlockTxn(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
467 "blocktxn" => NetworkMessage::BlockTxn(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
468 "wtxidrelay" => NetworkMessage::WtxidRelay,
469 "addrv2" => NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
470 "sendaddrv2" => NetworkMessage::SendAddrV2,
471 _ => NetworkMessage::Unknown {
472 command: cmd,
473 payload: mem_d.into_inner(),
474 }
475 };
476 Ok(RawNetworkMessage {
477 magic,
478 payload,
479 })
480 }
481
482 #[inline]
483 fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
484 Self::consensus_decode_from_finite_reader(r.take(MAX_MSG_SIZE as u64).by_ref())
485 }
486}
487
488#[cfg(test)]
489mod test {
490 use std::net::Ipv4Addr;
491 use super::{RawNetworkMessage, NetworkMessage, CommandString};
492 use crate::network::constants::ServiceFlags;
493 use crate::consensus::encode::{deserialize, deserialize_partial, serialize};
494 use crate::hashes::hex::FromHex;
495 use crate::hashes::sha256d::Hash;
496 use crate::hashes::Hash as HashTrait;
497 use crate::network::address::{Address, AddrV2, AddrV2Message};
498 use super::message_network::{Reject, RejectReason, VersionMessage};
499 use crate::network::message_blockdata::{Inventory, GetBlocksMessage, GetHeadersMessage};
500 use crate::blockdata::block::{Block, BlockHeader};
501 use crate::network::message_filter::{GetCFilters, CFilter, GetCFHeaders, CFHeaders, GetCFCheckpt, CFCheckpt};
502 use crate::blockdata::transaction::Transaction;
503 use crate::blockdata::script::Script;
504 use crate::network::message_bloom::{FilterAdd, FilterLoad, BloomFlags};
505 use crate::MerkleBlock;
506 use crate::network::message_compact_blocks::{GetBlockTxn, SendCmpct};
507 use crate::util::bip152::BlockTransactionsRequest;
508
509 fn hash(slice: [u8;32]) -> Hash {
510 Hash::from_slice(&slice).unwrap()
511 }
512
513 #[test]
514 fn full_round_ser_der_raw_network_message_test() {
515 let version_msg: VersionMessage = deserialize(&Vec::from_hex("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001").unwrap()).unwrap();
517 let tx: Transaction = deserialize(&Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap()).unwrap();
518 let block: Block = deserialize(&include_bytes!("../../test_data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw")[..]).unwrap();
519 let header: BlockHeader = deserialize(&Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap()).unwrap();
520 let script: Script = deserialize(&Vec::from_hex("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac").unwrap()).unwrap();
521 let merkle_block: MerkleBlock = deserialize(&Vec::from_hex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101").unwrap()).unwrap();
522 let cmptblock = deserialize(&Vec::from_hex("00000030d923ad36ff2d955abab07f8a0a6e813bc6e066b973e780c5e36674cad5d1cd1f6e265f2a17a0d35cbe701fe9d06e2c6324cfe135f6233e8b767bfa3fb4479b71115dc562ffff7f2006000000000000000000000000010002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0302ee00ffffffff0100f9029500000000015100000000").unwrap()).unwrap();
523 let blocktxn = deserialize(&Vec::from_hex("2e93c0cff39ff605020072d96bc3a8d20b8447e294d08092351c8583e08d9b5a01020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402dc0000ffffffff0200f90295000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()).unwrap();
524
525
526 let msgs = vec![
527 NetworkMessage::Version(version_msg),
528 NetworkMessage::Verack,
529 NetworkMessage::Addr(vec![(45, Address::new(&([123,255,000,100], 833).into(), ServiceFlags::NETWORK))]),
530 NetworkMessage::Inv(vec![Inventory::Block(hash([8u8; 32]).into())]),
531 NetworkMessage::GetData(vec![Inventory::Transaction(hash([45u8; 32]).into())]),
532 NetworkMessage::NotFound(vec![Inventory::Error]),
533 NetworkMessage::GetBlocks(GetBlocksMessage::new(vec![hash([1u8; 32]).into(), hash([4u8; 32]).into()], hash([5u8; 32]).into())),
534 NetworkMessage::GetHeaders(GetHeadersMessage::new(vec![hash([10u8; 32]).into(), hash([40u8; 32]).into()], hash([50u8; 32]).into())),
535 NetworkMessage::MemPool,
536 NetworkMessage::Tx(tx),
537 NetworkMessage::Block(block),
538 NetworkMessage::Headers(vec![header]),
539 NetworkMessage::SendHeaders,
540 NetworkMessage::GetAddr,
541 NetworkMessage::Ping(15),
542 NetworkMessage::Pong(23),
543 NetworkMessage::MerkleBlock(merkle_block),
544 NetworkMessage::FilterLoad(FilterLoad {filter: Vec::from_hex("03614e9b050000000000000001").unwrap(), hash_funcs: 1, tweak: 2, flags: BloomFlags::All}),
545 NetworkMessage::FilterAdd(FilterAdd {data: script.as_bytes().to_vec()}),
546 NetworkMessage::FilterAdd(FilterAdd {data: hash([29u8; 32]).to_vec()}),
547 NetworkMessage::FilterClear,
548 NetworkMessage::GetCFilters(GetCFilters{filter_type: 2, start_height: 52, stop_hash: hash([42u8; 32]).into()}),
549 NetworkMessage::CFilter(CFilter{filter_type: 7, block_hash: hash([25u8; 32]).into(), filter: vec![1,2,3]}),
550 NetworkMessage::GetCFHeaders(GetCFHeaders{filter_type: 4, start_height: 102, stop_hash: hash([47u8; 32]).into()}),
551 NetworkMessage::CFHeaders(CFHeaders{filter_type: 13, stop_hash: hash([53u8; 32]).into(), previous_filter_header: hash([12u8; 32]).into(), filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()]}),
552 NetworkMessage::GetCFCheckpt(GetCFCheckpt{filter_type: 17, stop_hash: hash([25u8; 32]).into()}),
553 NetworkMessage::CFCheckpt(CFCheckpt{filter_type: 27, stop_hash: hash([77u8; 32]).into(), filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()]}),
554 NetworkMessage::Alert(vec![45,66,3,2,6,8,9,12,3,130]),
555 NetworkMessage::Reject(Reject{message: "Test reject".into(), ccode: RejectReason::Duplicate, reason: "Cause".into(), hash: hash([255u8; 32])}),
556 NetworkMessage::FeeFilter(1000),
557 NetworkMessage::WtxidRelay,
558 NetworkMessage::AddrV2(vec![AddrV2Message{ addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), port: 0, services: ServiceFlags::NONE, time: 0 }]),
559 NetworkMessage::SendAddrV2,
560 NetworkMessage::CmpctBlock(cmptblock),
561 NetworkMessage::GetBlockTxn(GetBlockTxn { txs_request: BlockTransactionsRequest { block_hash: hash([11u8; 32]).into(), indexes: vec![0, 1, 2, 3, 10, 3002] } }),
562 NetworkMessage::BlockTxn(blocktxn),
563 NetworkMessage::SendCmpct(SendCmpct{send_compact: true, version: 8333}),
564 ];
565
566 for msg in msgs {
567 let raw_msg = RawNetworkMessage {magic: 57, payload: msg};
568 assert_eq!(deserialize::<RawNetworkMessage>(&serialize(&raw_msg)).unwrap(), raw_msg);
569 }
570
571 }
572
573 #[test]
574 fn commandstring_test() {
575 assert_eq!(CommandString::try_from_static("AndrewAndrew").unwrap().as_ref(), "AndrewAndrew");
577 assert!(CommandString::try_from_static("AndrewAndrewA").is_err());
578
579 let cs = CommandString("Andrew".into());
581 assert_eq!(serialize(&cs), vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
582
583 let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
585 assert!(cs.is_ok());
586 assert_eq!(cs.as_ref().unwrap().to_string(), "Andrew".to_owned());
587 assert_eq!(cs.unwrap(), CommandString::try_from_static("Andrew").unwrap());
588
589 let short_cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
590 assert!(short_cs.is_err());
591 }
592
593 #[test]
594 fn serialize_verack_test() {
595 assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::Verack }),
596 vec![0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61,
597 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
599 }
600
601 #[test]
602 fn serialize_ping_test() {
603 assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::Ping(100) }),
604 vec![0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d,
607 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
608 }
609
610
611 #[test]
612 fn serialize_mempool_test() {
613 assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::MemPool }),
614 vec![0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70,
615 0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
617 }
618
619 #[test]
620 fn serialize_getaddr_test() {
621 assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::GetAddr }),
622 vec![0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
623 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
625 }
626
627 #[test]
628 fn deserialize_getaddr_test() {
629 let msg = deserialize(
630 &[0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
631 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]);
633 let preimage = RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::GetAddr };
634 assert!(msg.is_ok());
635 let msg : RawNetworkMessage = msg.unwrap();
636 assert_eq!(preimage.magic, msg.magic);
637 assert_eq!(preimage.payload, msg.payload);
638 }
639
640 #[test]
641 fn deserialize_version_test() {
642 let msg = deserialize::<RawNetworkMessage>(
643 &[ 0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73,
644 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27,
646 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
651 0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1,
656 0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68,
657 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31,
658 0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01 ]);
659
660 assert!(msg.is_ok());
661 let msg = msg.unwrap();
662 assert_eq!(msg.magic, 0xd9b4bef9);
663 if let NetworkMessage::Version(version_msg) = msg.payload {
664 assert_eq!(version_msg.version, 70015);
665 assert_eq!(version_msg.services, ServiceFlags::NETWORK | ServiceFlags::BLOOM | ServiceFlags::WITNESS | ServiceFlags::NETWORK_LIMITED);
666 assert_eq!(version_msg.timestamp, 1548554224);
667 assert_eq!(version_msg.nonce, 13952548347456104954);
668 assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
669 assert_eq!(version_msg.start_height, 560275);
670 assert!(version_msg.relay);
671 } else {
672 panic!("Wrong message type");
673 }
674 }
675
676 #[test]
677 fn deserialize_partial_message_test() {
678 let data = [ 0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73,
679 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27,
681 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
686 0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1,
691 0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68,
692 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31,
693 0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01, 0, 0 ];
694 let msg = deserialize_partial::<RawNetworkMessage>(&data);
695 assert!(msg.is_ok());
696
697 let (msg, consumed) = msg.unwrap();
698 assert_eq!(consumed, data.to_vec().len() - 2);
699 assert_eq!(msg.magic, 0xd9b4bef9);
700 if let NetworkMessage::Version(version_msg) = msg.payload {
701 assert_eq!(version_msg.version, 70015);
702 assert_eq!(version_msg.services, ServiceFlags::NETWORK | ServiceFlags::BLOOM | ServiceFlags::WITNESS | ServiceFlags::NETWORK_LIMITED);
703 assert_eq!(version_msg.timestamp, 1548554224);
704 assert_eq!(version_msg.nonce, 13952548347456104954);
705 assert_eq!(version_msg.user_agent, "/Satoshi:0.17.1/");
706 assert_eq!(version_msg.start_height, 560275);
707 assert!(version_msg.relay);
708 } else {
709 panic!("Wrong message type");
710 }
711 }
712}