cs_mwc_bch/messages/
message.rs

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
22/// Checksum to use when there is an empty payload
23pub const NO_CHECKSUM: [u8; 4] = [0x5d, 0xf6, 0xe0, 0xe2];
24
25/// Max message payload size (32MB)
26pub const MAX_PAYLOAD_SIZE: u32 = 0x02000000;
27
28/// Message commands for the header
29pub mod commands {
30    /// [Addr command](https://en.bitcoin.it/wiki/Protocol_documentation#addr)
31    pub const ADDR: [u8; 12] = *b"addr\0\0\0\0\0\0\0\0";
32
33    /// [Alert command](https://en.bitcoin.it/wiki/Protocol_documentation#alert) (deprecated)
34    pub const ALERT: [u8; 12] = *b"alert\0\0\0\0\0\0\0";
35
36    /// [Block command](https://en.bitcoin.it/wiki/Protocol_documentation#block)
37    pub const BLOCK: [u8; 12] = *b"block\0\0\0\0\0\0\0";
38
39    /// [Block transaction command](https://en.bitcoin.it/wiki/Protocol_documentation#blocktxn)
40    pub const BLOCKTXN: [u8; 12] = *b"blocktxn\0\0\0\0";
41
42    /// [Compact block command](https://en.bitcoin.it/wiki/Protocol_documentation#cmpctblock)
43    pub const CMPCTBLOCK: [u8; 12] = *b"cmpctblock\0\0";
44
45    /// [Inventory command](https://en.bitcoin.it/wiki/Protocol_documentation#inv)
46    pub const INV: [u8; 12] = *b"inv\0\0\0\0\0\0\0\0\0";
47
48    /// [Fee filter command](https://en.bitcoin.it/wiki/Protocol_documentation#feefilter)
49    pub const FEEFILTER: [u8; 12] = *b"feefilter\0\0\0";
50
51    /// [Filter add command](https://en.bitcoin.it/wiki/Protocol_documentation#filterload.2C_filteradd.2C_filterclear.2C_merkleblock)
52    pub const FILTERADD: [u8; 12] = *b"filteradd\0\0\0";
53
54    /// [Filter clear command](https://en.bitcoin.it/wiki/Protocol_documentation#filterload.2C_filteradd.2C_filterclear.2C_merkleblock)
55    pub const FILTERCLEAR: [u8; 12] = *b"filterclear\0";
56
57    /// [Filter load command](https://en.bitcoin.it/wiki/Protocol_documentation#filterload.2C_filteradd.2C_filterclear.2C_merkleblock)
58    pub const FILTERLOAD: [u8; 12] = *b"filterload\0\0";
59
60    /// [Get addr command](https://en.bitcoin.it/wiki/Protocol_documentation#getaddr)
61    pub const GETADDR: [u8; 12] = *b"getaddr\0\0\0\0\0";
62
63    /// [Get blocks command](https://en.bitcoin.it/wiki/Protocol_documentation#getblocks)
64    pub const GETBLOCKS: [u8; 12] = *b"getblocks\0\0\0";
65
66    /// [Get block transaction command](https://en.bitcoin.it/wiki/Protocol_documentation#getblocktxn)
67    pub const GETBLOCKTXN: [u8; 12] = *b"getblocktxn\0";
68
69    /// [Get data command](https://en.bitcoin.it/wiki/Protocol_documentation#getdata)
70    pub const GETDATA: [u8; 12] = *b"getdata\0\0\0\0\0";
71
72    /// [Get headers command](https://en.bitcoin.it/wiki/Protocol_documentation#getheaders)
73    pub const GETHEADERS: [u8; 12] = *b"getheaders\0\0";
74
75    /// [Headers command](https://en.bitcoin.it/wiki/Protocol_documentation#headers)
76    pub const HEADERS: [u8; 12] = *b"headers\0\0\0\0\0";
77
78    /// [Mempool command](https://en.bitcoin.it/wiki/Protocol_documentation#mempool)
79    pub const MEMPOOL: [u8; 12] = *b"mempool\0\0\0\0\0";
80
81    /// [Merkle block](https://en.bitcoin.it/wiki/Protocol_documentation#filterload.2C_filteradd.2C_filterclear.2C_merkleblock)
82    pub const MERKLEBLOCK: [u8; 12] = *b"merkleblock\0";
83
84    /// [Not found command](https://en.bitcoin.it/wiki/Protocol_documentation#notfound)
85    pub const NOTFOUND: [u8; 12] = *b"notfound\0\0\0\0";
86
87    /// [Ping command](https://en.bitcoin.it/wiki/Protocol_documentation#ping)
88    pub const PING: [u8; 12] = *b"ping\0\0\0\0\0\0\0\0";
89
90    /// [Pong command](https://en.bitcoin.it/wiki/Protocol_documentation#pong)
91    pub const PONG: [u8; 12] = *b"pong\0\0\0\0\0\0\0\0";
92
93    /// [Reject command](https://en.bitcoin.it/wiki/Protocol_documentation#reject)
94    pub const REJECT: [u8; 12] = *b"reject\0\0\0\0\0\0";
95
96    /// [Send compact command](https://en.bitcoin.it/wiki/Protocol_documentation#sendcmpct)
97    pub const SENDCMPCT: [u8; 12] = *b"sendcmpct\0\0\0";
98
99    /// [Send headers command](https://en.bitcoin.it/wiki/Protocol_documentation#sendheaders)
100    pub const SENDHEADERS: [u8; 12] = *b"sendheaders\0";
101
102    /// [Transaction command](https://en.bitcoin.it/wiki/Protocol_documentation#tx)
103    pub const TX: [u8; 12] = *b"tx\0\0\0\0\0\0\0\0\0\0";
104
105    /// [Version command](https://en.bitcoin.it/wiki/Protocol_documentation#version)
106    pub const VERSION: [u8; 12] = *b"version\0\0\0\0\0";
107
108    /// [Version acknowledgement command](https://en.bitcoin.it/wiki/Protocol_documentation#verack)
109    pub const VERACK: [u8; 12] = *b"verack\0\0\0\0\0\0";
110}
111
112/// Bitcoin peer-to-peer message with its payload
113#[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    /// Reads a Bitcoin P2P message with its payload from bytes
144    ///
145    /// It's possible for a message's header to be read but not its payload. In this case, the
146    /// return value is not an Error but a Partial message, and the complete message may be read
147    /// later using read_partial.
148    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                    // Depending on platform, either TimedOut or WouldBlock may be returned to indicate a non-error timeout
156                    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    /// Reads the complete message given a message header
167    ///
168    /// It may be used after read() returns Message::Partial.
169    pub fn read_partial(reader: &mut dyn Read, header: &MessageHeader) -> Result<Self> {
170        // Addr
171        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        // Block
178        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        // Feefilter
185        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        // FilterAdd
192        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        // FilterClear
200        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        // FilterLoad
208        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        // Getaddr
216        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        // Getblocks
224        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        // Getdata
231        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        // Getheaders
238        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        // Headers
245        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        // Inv
252        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        // Mempool
259        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        // MerkleBlock
267        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        // Notfound
274        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        // Ping
281        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        // Pong
288        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        // Reject
295        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        // Sendcmpct
302        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        // Sendheaders
309        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        // Tx
317        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        // Version
324        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        // Verack
332        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        // Unknown message
340        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    /// Writes a Bitcoin P2P message with its payload to bytes
348    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
463/// Message payload that is writable to bytes
464pub 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        // Addr
491        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        // Block
506        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        // FeeFilter
562        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        // FilterAdd
569        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        // FilterClear
576        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        // FilterLoad
582        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        // GetAddr
596        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        // GetBlocks
602        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        // GetData
613        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        // GetHeaders
625        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        // Headers
636        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        // Mempool
647        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        // MerkleBlock
653        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        // NotFound
678        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        // Inv
690        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        // Ping
702        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        // Pong
709        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        // Reject
716        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        // SendHeaders
728        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        // SendCmpct
734        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        // Tx
744        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        // Verack
766        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        // Version
772        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            // Success
817        } else {
818            assert!(false);
819        }
820    }
821}