1use messages::addr::Addr;
2use messages::block::Block;
3use messages::block_locator::BlockLocator;
4use messages::fee_filter::FeeFilter;
5use messages::filter_add::FilterAdd;
6use messages::filter_load::FilterLoad;
7use messages::headers::Headers;
8use messages::inv::Inv;
9use messages::merkle_block::MerkleBlock;
10use messages::message_header::MessageHeader;
11use messages::ping::Ping;
12use messages::reject::Reject;
13use messages::send_cmpct::SendCmpct;
14use messages::tx::Tx;
15use messages::version::Version;
16use ring::digest;
17use std::fmt;
18use std::io;
19use std::io::{Cursor, Read, Write};
20use util::{Error, Result, Serializable};
21
22pub const NO_CHECKSUM: [u8; 4] = [0x5d, 0xf6, 0xe0, 0xe2];
24
25pub const MAX_PAYLOAD_SIZE: u32 = 0x02000000;
27
28pub mod commands {
30 pub const ADDR: [u8; 12] = *b"addr\0\0\0\0\0\0\0\0";
32
33 pub const ALERT: [u8; 12] = *b"alert\0\0\0\0\0\0\0";
35
36 pub const BLOCK: [u8; 12] = *b"block\0\0\0\0\0\0\0";
38
39 pub const BLOCKTXN: [u8; 12] = *b"blocktxn\0\0\0\0";
41
42 pub const CMPCTBLOCK: [u8; 12] = *b"cmpctblock\0\0";
44
45 pub const INV: [u8; 12] = *b"inv\0\0\0\0\0\0\0\0\0";
47
48 pub const FEEFILTER: [u8; 12] = *b"feefilter\0\0\0";
50
51 pub const FILTERADD: [u8; 12] = *b"filteradd\0\0\0";
53
54 pub const FILTERCLEAR: [u8; 12] = *b"filterclear\0";
56
57 pub const FILTERLOAD: [u8; 12] = *b"filterload\0\0";
59
60 pub const GETADDR: [u8; 12] = *b"getaddr\0\0\0\0\0";
62
63 pub const GETBLOCKS: [u8; 12] = *b"getblocks\0\0\0";
65
66 pub const GETBLOCKTXN: [u8; 12] = *b"getblocktxn\0";
68
69 pub const GETDATA: [u8; 12] = *b"getdata\0\0\0\0\0";
71
72 pub const GETHEADERS: [u8; 12] = *b"getheaders\0\0";
74
75 pub const HEADERS: [u8; 12] = *b"headers\0\0\0\0\0";
77
78 pub const MEMPOOL: [u8; 12] = *b"mempool\0\0\0\0\0";
80
81 pub const MERKLEBLOCK: [u8; 12] = *b"merkleblock\0";
83
84 pub const NOTFOUND: [u8; 12] = *b"notfound\0\0\0\0";
86
87 pub const PING: [u8; 12] = *b"ping\0\0\0\0\0\0\0\0";
89
90 pub const PONG: [u8; 12] = *b"pong\0\0\0\0\0\0\0\0";
92
93 pub const REJECT: [u8; 12] = *b"reject\0\0\0\0\0\0";
95
96 pub const SENDCMPCT: [u8; 12] = *b"sendcmpct\0\0\0";
98
99 pub const SENDHEADERS: [u8; 12] = *b"sendheaders\0";
101
102 pub const TX: [u8; 12] = *b"tx\0\0\0\0\0\0\0\0\0\0";
104
105 pub const VERSION: [u8; 12] = *b"version\0\0\0\0\0";
107
108 pub const VERACK: [u8; 12] = *b"verack\0\0\0\0\0\0";
110}
111
112#[derive(PartialEq, Eq, Hash, Clone)]
114pub enum Message {
115 Addr(Addr),
116 Block(Block),
117 FeeFilter(FeeFilter),
118 FilterAdd(FilterAdd),
119 FilterClear,
120 FilterLoad(FilterLoad),
121 GetAddr,
122 GetBlocks(BlockLocator),
123 GetData(Inv),
124 GetHeaders(BlockLocator),
125 Headers(Headers),
126 Inv(Inv),
127 Mempool,
128 MerkleBlock(MerkleBlock),
129 NotFound(Inv),
130 Other(String),
131 Partial(MessageHeader),
132 Ping(Ping),
133 Pong(Ping),
134 Reject(Reject),
135 SendHeaders,
136 SendCmpct(SendCmpct),
137 Tx(Tx),
138 Verack,
139 Version(Version),
140}
141
142impl Message {
143 pub fn read(reader: &mut dyn Read, magic: [u8; 4]) -> Result<Self> {
149 let header = MessageHeader::read(reader)?;
150 header.validate(magic, MAX_PAYLOAD_SIZE)?;
151 match Message::read_partial(reader, &header) {
152 Ok(msg) => Ok(msg),
153 Err(e) => {
154 if let Error::IOError(ref e) = e {
155 if e.kind() == io::ErrorKind::TimedOut || e.kind() == io::ErrorKind::WouldBlock
157 {
158 return Ok(Message::Partial(header));
159 }
160 }
161 return Err(e);
162 }
163 }
164 }
165
166 pub fn read_partial(reader: &mut dyn Read, header: &MessageHeader) -> Result<Self> {
170 if header.command == commands::ADDR {
172 let payload = header.payload(reader)?;
173 let addr = Addr::read(&mut Cursor::new(payload))?;
174 return Ok(Message::Addr(addr));
175 }
176
177 if header.command == commands::BLOCK {
179 let payload = header.payload(reader)?;
180 let block = Block::read(&mut Cursor::new(payload))?;
181 return Ok(Message::Block(block));
182 }
183
184 if header.command == commands::FEEFILTER {
186 let payload = header.payload(reader)?;
187 let feefilter = FeeFilter::read(&mut Cursor::new(payload))?;
188 return Ok(Message::FeeFilter(feefilter));
189 }
190
191 if header.command == commands::FILTERADD {
193 let payload = header.payload(reader)?;
194 let filter_add = FilterAdd::read(&mut Cursor::new(payload))?;
195 filter_add.validate()?;
196 return Ok(Message::FilterAdd(filter_add));
197 }
198
199 if header.command == commands::FILTERCLEAR {
201 if header.payload_size != 0 {
202 return Err(Error::BadData("Bad payload".to_string()));
203 }
204 return Ok(Message::FilterClear);
205 }
206
207 if header.command == commands::FILTERLOAD {
209 let payload = header.payload(reader)?;
210 let filter_load = FilterLoad::read(&mut Cursor::new(payload))?;
211 filter_load.validate()?;
212 return Ok(Message::FilterLoad(filter_load));
213 }
214
215 if header.command == commands::GETADDR {
217 if header.payload_size != 0 {
218 return Err(Error::BadData("Bad payload".to_string()));
219 }
220 return Ok(Message::GetAddr);
221 }
222
223 if header.command == commands::GETBLOCKS {
225 let payload = header.payload(reader)?;
226 let block_locator = BlockLocator::read(&mut Cursor::new(payload))?;
227 return Ok(Message::GetBlocks(block_locator));
228 }
229
230 if header.command == commands::GETDATA {
232 let payload = header.payload(reader)?;
233 let inv = Inv::read(&mut Cursor::new(payload))?;
234 return Ok(Message::GetData(inv));
235 }
236
237 if header.command == commands::GETHEADERS {
239 let payload = header.payload(reader)?;
240 let block_locator = BlockLocator::read(&mut Cursor::new(payload))?;
241 return Ok(Message::GetHeaders(block_locator));
242 }
243
244 if header.command == commands::HEADERS {
246 let payload = header.payload(reader)?;
247 let headers = Headers::read(&mut Cursor::new(payload))?;
248 return Ok(Message::Headers(headers));
249 }
250
251 if header.command == commands::INV {
253 let payload = header.payload(reader)?;
254 let inv = Inv::read(&mut Cursor::new(payload))?;
255 return Ok(Message::Inv(inv));
256 }
257
258 if header.command == commands::MEMPOOL {
260 if header.payload_size != 0 {
261 return Err(Error::BadData("Bad payload".to_string()));
262 }
263 return Ok(Message::Mempool);
264 }
265
266 if header.command == commands::MERKLEBLOCK {
268 let payload = header.payload(reader)?;
269 let merkle_block = MerkleBlock::read(&mut Cursor::new(payload))?;
270 return Ok(Message::MerkleBlock(merkle_block));
271 }
272
273 if header.command == commands::NOTFOUND {
275 let payload = header.payload(reader)?;
276 let inv = Inv::read(&mut Cursor::new(payload))?;
277 return Ok(Message::NotFound(inv));
278 }
279
280 if header.command == commands::PING {
282 let payload = header.payload(reader)?;
283 let ping = Ping::read(&mut Cursor::new(payload))?;
284 return Ok(Message::Ping(ping));
285 }
286
287 if header.command == commands::PONG {
289 let payload = header.payload(reader)?;
290 let pong = Ping::read(&mut Cursor::new(payload))?;
291 return Ok(Message::Pong(pong));
292 }
293
294 if header.command == commands::REJECT {
296 let payload = header.payload(reader)?;
297 let reject = Reject::read(&mut Cursor::new(payload))?;
298 return Ok(Message::Reject(reject));
299 }
300
301 if header.command == commands::SENDCMPCT {
303 let payload = header.payload(reader)?;
304 let sendcmpct = SendCmpct::read(&mut Cursor::new(payload))?;
305 return Ok(Message::SendCmpct(sendcmpct));
306 }
307
308 if header.command == commands::SENDHEADERS {
310 if header.payload_size != 0 {
311 return Err(Error::BadData("Bad payload".to_string()));
312 }
313 return Ok(Message::SendHeaders);
314 }
315
316 if header.command == commands::TX {
318 let payload = header.payload(reader)?;
319 let tx = Tx::read(&mut Cursor::new(payload))?;
320 return Ok(Message::Tx(tx));
321 }
322
323 if header.command == commands::VERSION {
325 let payload = header.payload(reader)?;
326 let version = Version::read(&mut Cursor::new(payload))?;
327 version.validate()?;
328 return Ok(Message::Version(version));
329 }
330
331 if header.command == commands::VERACK {
333 if header.payload_size != 0 {
334 return Err(Error::BadData("Bad payload".to_string()));
335 }
336 return Ok(Message::Verack);
337 }
338
339 if header.payload_size > 0 {
341 header.payload(reader)?;
342 }
343 let command = String::from_utf8(header.command.to_vec()).unwrap_or("Unknown".to_string());
344 return Ok(Message::Other(command));
345 }
346
347 pub fn write(&self, writer: &mut dyn Write, magic: [u8; 4]) -> io::Result<()> {
349 use self::commands::*;
350 match self {
351 Message::Addr(p) => write_with_payload(writer, ADDR, p, magic),
352 Message::Block(p) => write_with_payload(writer, BLOCK, p, magic),
353 Message::FeeFilter(p) => write_with_payload(writer, FEEFILTER, p, magic),
354 Message::FilterAdd(p) => write_with_payload(writer, FILTERADD, p, magic),
355 Message::FilterClear => write_without_payload(writer, FILTERCLEAR, magic),
356 Message::FilterLoad(p) => write_with_payload(writer, FILTERLOAD, p, magic),
357 Message::GetAddr => write_without_payload(writer, GETADDR, magic),
358 Message::GetBlocks(p) => write_with_payload(writer, GETBLOCKS, p, magic),
359 Message::GetData(p) => write_with_payload(writer, GETDATA, p, magic),
360 Message::GetHeaders(p) => write_with_payload(writer, GETHEADERS, p, magic),
361 Message::Headers(p) => write_with_payload(writer, HEADERS, p, magic),
362 Message::Mempool => write_without_payload(writer, MEMPOOL, magic),
363 Message::MerkleBlock(p) => write_with_payload(writer, MERKLEBLOCK, p, magic),
364 Message::NotFound(p) => write_with_payload(writer, NOTFOUND, p, magic),
365 Message::Inv(p) => write_with_payload(writer, INV, p, magic),
366 Message::Other(s) => Err(io::Error::new(io::ErrorKind::InvalidData, s.as_str())),
367 Message::Partial(_) => Err(io::Error::new(
368 io::ErrorKind::InvalidData,
369 "Cannot write partial message".to_string(),
370 )),
371 Message::Ping(p) => write_with_payload(writer, PING, p, magic),
372 Message::Pong(p) => write_with_payload(writer, PONG, p, magic),
373 Message::Reject(p) => write_with_payload(writer, REJECT, p, magic),
374 Message::SendHeaders => write_without_payload(writer, SENDHEADERS, magic),
375 Message::SendCmpct(p) => write_with_payload(writer, SENDCMPCT, p, magic),
376 Message::Tx(p) => write_with_payload(writer, TX, p, magic),
377 Message::Verack => write_without_payload(writer, VERACK, magic),
378 Message::Version(v) => write_with_payload(writer, VERSION, v, magic),
379 }
380 }
381}
382
383impl fmt::Debug for Message {
384 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
385 match self {
386 Message::Addr(p) => f.write_str(&format!("{:#?}", p)),
387 Message::Block(p) => f.write_str(&format!("{:#?}", p)),
388 Message::FeeFilter(p) => f.write_str(&format!("{:#?}", p)),
389 Message::FilterAdd(p) => f.write_str(&format!("{:#?}", p)),
390 Message::FilterClear => f.write_str("FilterClear"),
391 Message::FilterLoad(p) => f.write_str(&format!("{:#?}", p)),
392 Message::GetAddr => f.write_str("GetAddr"),
393 Message::GetBlocks(p) => f
394 .debug_struct("GetBlocks")
395 .field("version", &p.version)
396 .field("block_locator_hashes", &p.block_locator_hashes)
397 .field("hash_stop", &p.hash_stop)
398 .finish(),
399 Message::GetData(p) => f.debug_struct("GetData").field("inv", &p).finish(),
400 Message::GetHeaders(p) => f
401 .debug_struct("GetHeaders")
402 .field("version", &p.version)
403 .field("block_locator_hashes", &p.block_locator_hashes)
404 .field("hash_stop", &p.hash_stop)
405 .finish(),
406 Message::Headers(p) => f.write_str(&format!("{:#?}", p)),
407 Message::Inv(p) => f.write_str(&format!("{:#?}", p)),
408 Message::Mempool => f.write_str("Mempool"),
409 Message::MerkleBlock(p) => f.write_str(&format!("{:#?}", p)),
410 Message::NotFound(p) => f.debug_struct("NotFound").field("inv", &p).finish(),
411 Message::Other(p) => f.write_str(&format!("{:#?}", p)),
412 Message::Partial(h) => f.write_str(&format!("Partial {:#?}", h)),
413 Message::Ping(p) => f.write_str(&format!("{:#?}", p)),
414 Message::Pong(p) => f.debug_struct("Pong").field("nonce", &p.nonce).finish(),
415 Message::Reject(p) => f.write_str(&format!("{:#?}", p)),
416 Message::SendHeaders => f.write_str("SendHeaders"),
417 Message::SendCmpct(p) => f.write_str(&format!("{:#?}", p)),
418 Message::Tx(p) => f.write_str(&format!("{:#?}", p)),
419 Message::Verack => f.write_str("Verack"),
420 Message::Version(p) => f.write_str(&format!("{:#?}", p)),
421 }
422 }
423}
424
425fn write_without_payload(
426 writer: &mut dyn Write,
427 command: [u8; 12],
428 magic: [u8; 4],
429) -> io::Result<()> {
430 let header = MessageHeader {
431 magic,
432 command,
433 payload_size: 0,
434 checksum: NO_CHECKSUM,
435 };
436 header.write(writer)
437}
438
439fn write_with_payload<T: Serializable<T>>(
440 writer: &mut dyn Write,
441 command: [u8; 12],
442 payload: &dyn Payload<T>,
443 magic: [u8; 4],
444) -> io::Result<()> {
445 let mut bytes = Vec::with_capacity(payload.size());
446 payload.write(&mut bytes)?;
447 let hash = digest::digest(&digest::SHA256, bytes.as_ref());
448 let hash = digest::digest(&digest::SHA256, &hash.as_ref());
449 let h = &hash.as_ref();
450 let checksum = [h[0], h[1], h[2], h[3]];
451
452 let header = MessageHeader {
453 magic,
454 command,
455 payload_size: payload.size() as u32,
456 checksum: checksum,
457 };
458
459 header.write(writer)?;
460 payload.write(writer)
461}
462
463pub trait Payload<T>: Serializable<T> + fmt::Debug {
465 fn size(&self) -> usize;
466}
467
468#[cfg(test)]
469mod tests {
470 use super::*;
471 use messages::block_header::BlockHeader;
472 use messages::inv_vect::{InvVect, INV_VECT_TX};
473 use messages::node_addr::NodeAddr;
474 use messages::node_addr_ex::NodeAddrEx;
475 use messages::out_point::OutPoint;
476 use messages::tx_in::TxIn;
477 use messages::tx_out::TxOut;
478 use messages::version::MIN_SUPPORTED_PROTOCOL_VERSION;
479 use messages::REJECT_INVALID;
480 use script::Script;
481 use std::io::Cursor;
482 use std::net::Ipv6Addr;
483 use std::time::UNIX_EPOCH;
484 use util::{secs_since, Amount, BloomFilter, Hash256};
485
486 #[test]
487 fn write_read() {
488 let magic = [7, 8, 9, 0];
489
490 let mut v = Vec::new();
492 let a = NodeAddrEx {
493 last_connected_time: 700,
494 addr: NodeAddr {
495 services: 900,
496 ip: Ipv6Addr::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 9, 8, 7, 6, 5]),
497 port: 4000,
498 },
499 };
500 let p = Addr { addrs: vec![a] };
501 let m = Message::Addr(p);
502 m.write(&mut v, magic).unwrap();
503 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
504
505 let mut v = Vec::new();
507 let p = Block {
508 header: BlockHeader {
509 version: 0x00000001,
510 prev_hash: Hash256::decode(
511 "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234",
512 )
513 .unwrap(),
514 merkle_root: Hash256::decode(
515 "2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3",
516 )
517 .unwrap(),
518 timestamp: 0x4dd7f5c7,
519 bits: 0x1a44b9f2,
520 nonce: 0x9546a142,
521 },
522 txns: vec![
523 Tx {
524 version: 0x44556677,
525 inputs: vec![TxIn {
526 prev_output: OutPoint {
527 hash: Hash256([5; 32]),
528 index: 3,
529 },
530 sig_script: Script(vec![5; 5]),
531 sequence: 2,
532 }],
533 outputs: vec![TxOut {
534 amount: Amount(42),
535 pk_script: Script(vec![9; 21]),
536 }],
537 lock_time: 0x12ff34aa,
538 },
539 Tx {
540 version: 0x99881122,
541 inputs: vec![TxIn {
542 prev_output: OutPoint {
543 hash: Hash256([6; 32]),
544 index: 4,
545 },
546 sig_script: Script(vec![4; 4]),
547 sequence: 3,
548 }],
549 outputs: vec![TxOut {
550 amount: Amount(43),
551 pk_script: Script(vec![10; 22]),
552 }],
553 lock_time: 0x44550011,
554 },
555 ],
556 };
557 let m = Message::Block(p);
558 m.write(&mut v, magic).unwrap();
559 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
560
561 let mut v = Vec::new();
563 let p = FeeFilter { minfee: 1234 };
564 let m = Message::FeeFilter(p);
565 m.write(&mut v, magic).unwrap();
566 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
567
568 let mut v = Vec::new();
570 let p = FilterAdd { data: vec![15; 45] };
571 let m = Message::FilterAdd(p);
572 m.write(&mut v, magic).unwrap();
573 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
574
575 let mut v = Vec::new();
577 let m = Message::FilterClear;
578 m.write(&mut v, magic).unwrap();
579 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
580
581 let mut v = Vec::new();
583 let p = FilterLoad {
584 bloom_filter: BloomFilter {
585 filter: vec![1, 2, 3],
586 num_hash_funcs: 2,
587 tweak: 1,
588 },
589 flags: 0,
590 };
591 let m = Message::FilterLoad(p);
592 m.write(&mut v, magic).unwrap();
593 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
594
595 let mut v = Vec::new();
597 let m = Message::GetAddr;
598 m.write(&mut v, magic).unwrap();
599 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
600
601 let mut v = Vec::new();
603 let p = BlockLocator {
604 version: 567,
605 block_locator_hashes: vec![Hash256([3; 32]), Hash256([4; 32])],
606 hash_stop: Hash256([6; 32]),
607 };
608 let m = Message::GetBlocks(p);
609 m.write(&mut v, magic).unwrap();
610 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
611
612 let mut v = Vec::new();
614 let p = Inv {
615 objects: vec![InvVect {
616 obj_type: INV_VECT_TX,
617 hash: Hash256([0; 32]),
618 }],
619 };
620 let m = Message::GetData(p);
621 m.write(&mut v, magic).unwrap();
622 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
623
624 let mut v = Vec::new();
626 let p = BlockLocator {
627 version: 345,
628 block_locator_hashes: vec![Hash256([1; 32]), Hash256([2; 32])],
629 hash_stop: Hash256([3; 32]),
630 };
631 let m = Message::GetHeaders(p);
632 m.write(&mut v, magic).unwrap();
633 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
634
635 let mut v = Vec::new();
637 let p = Headers {
638 headers: vec![BlockHeader {
639 ..Default::default()
640 }],
641 };
642 let m = Message::Headers(p);
643 m.write(&mut v, magic).unwrap();
644 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
645
646 let mut v = Vec::new();
648 let m = Message::Mempool;
649 m.write(&mut v, magic).unwrap();
650 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
651
652 let mut v = Vec::new();
654 let p = MerkleBlock {
655 header: BlockHeader {
656 version: 12345,
657 prev_hash: Hash256::decode(
658 "7766009988776600998877660099887766009988776600998877660099887766",
659 )
660 .unwrap(),
661 merkle_root: Hash256::decode(
662 "2211554433221155443322115544332211554433221155443322115544332211",
663 )
664 .unwrap(),
665 timestamp: 66,
666 bits: 4488,
667 nonce: 9999,
668 },
669 total_transactions: 14,
670 hashes: vec![Hash256([1; 32]), Hash256([3; 32]), Hash256([5; 32])],
671 flags: vec![24, 125, 199],
672 };
673 let m = Message::MerkleBlock(p);
674 m.write(&mut v, magic).unwrap();
675 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
676
677 let mut v = Vec::new();
679 let p = Inv {
680 objects: vec![InvVect {
681 obj_type: INV_VECT_TX,
682 hash: Hash256([0; 32]),
683 }],
684 };
685 let m = Message::NotFound(p);
686 m.write(&mut v, magic).unwrap();
687 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
688
689 let mut v = Vec::new();
691 let p = Inv {
692 objects: vec![InvVect {
693 obj_type: INV_VECT_TX,
694 hash: Hash256([0; 32]),
695 }],
696 };
697 let m = Message::Inv(p);
698 m.write(&mut v, magic).unwrap();
699 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
700
701 let mut v = Vec::new();
703 let p = Ping { nonce: 7890 };
704 let m = Message::Ping(p);
705 m.write(&mut v, magic).unwrap();
706 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
707
708 let mut v = Vec::new();
710 let p = Ping { nonce: 7890 };
711 let m = Message::Pong(p);
712 m.write(&mut v, magic).unwrap();
713 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
714
715 let mut v = Vec::new();
717 let p = Reject {
718 message: "getaddr\0\0\0\0\0".to_string(),
719 code: REJECT_INVALID,
720 reason: "womp womp".to_string(),
721 data: vec![],
722 };
723 let m = Message::Reject(p);
724 m.write(&mut v, magic).unwrap();
725 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
726
727 let mut v = Vec::new();
729 let m = Message::SendHeaders;
730 m.write(&mut v, magic).unwrap();
731 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
732
733 let mut v = Vec::new();
735 let p = SendCmpct {
736 enable: 1,
737 version: 1,
738 };
739 let m = Message::SendCmpct(p);
740 m.write(&mut v, magic).unwrap();
741 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
742
743 let mut v = Vec::new();
745 let p = Tx {
746 version: 0x44556677,
747 inputs: vec![TxIn {
748 prev_output: OutPoint {
749 hash: Hash256([5; 32]),
750 index: 3,
751 },
752 sig_script: Script(vec![7; 7]),
753 sequence: 2,
754 }],
755 outputs: vec![TxOut {
756 amount: Amount(42),
757 pk_script: Script(vec![8; 8]),
758 }],
759 lock_time: 0x12ff34aa,
760 };
761 let m = Message::Tx(p);
762 m.write(&mut v, magic).unwrap();
763 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
764
765 let mut v = Vec::new();
767 let m = Message::Verack;
768 m.write(&mut v, magic).unwrap();
769 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
770
771 let mut v = Vec::new();
773 let p = Version {
774 version: MIN_SUPPORTED_PROTOCOL_VERSION,
775 services: 77,
776 timestamp: secs_since(UNIX_EPOCH) as i64,
777 recv_addr: NodeAddr {
778 ..Default::default()
779 },
780 tx_addr: NodeAddr {
781 ..Default::default()
782 },
783 nonce: 99,
784 user_agent: "dummy".to_string(),
785 start_height: 22,
786 relay: true,
787 };
788 let m = Message::Version(p);
789 m.write(&mut v, magic).unwrap();
790 assert!(Message::read(&mut Cursor::new(&v), magic).unwrap() == m);
791 }
792
793 #[test]
794 #[should_panic]
795 fn write_other_errors() {
796 let mut v = Vec::new();
797 let m = Message::Other("Unknown message".to_string());
798 m.write(&mut v, [7, 8, 9, 0]).unwrap();
799 }
800
801 #[test]
802 fn read_other() {
803 let magic = [7, 8, 9, 0];
804 let command = *b"unknowncmd\0\0";
805 let header = MessageHeader {
806 magic,
807 command,
808 payload_size: 0,
809 checksum: NO_CHECKSUM,
810 };
811 let mut v = Vec::new();
812 header.write(&mut v).unwrap();
813 let mut cursor = Cursor::new(&v);
814 let m = Message::read(&mut cursor, magic).unwrap();
815 if let Message::Other(_) = m {
816 } else {
818 assert!(false);
819 }
820 }
821}