cs_mwc_bch/messages/
headers.rs

1use byteorder::{ReadBytesExt, WriteBytesExt};
2use messages::block_header::BlockHeader;
3use messages::message::Payload;
4use std::fmt;
5use std::io;
6use std::io::{Read, Write};
7use util::{var_int, Error, Hash256, Result, Serializable};
8
9/// Collection of block headers
10#[derive(Default, PartialEq, Eq, Hash, Clone)]
11pub struct Headers {
12    /// List of sequential block headers
13    pub headers: Vec<BlockHeader>,
14}
15
16impl Serializable<Headers> for Headers {
17    fn read(reader: &mut dyn Read) -> Result<Headers> {
18        let n = var_int::read(reader)?;
19        let mut headers = Vec::new();
20        for _i in 0..n {
21            headers.push(BlockHeader::read(reader)?);
22            let _txn_count = reader.read_u8();
23        }
24        Ok(Headers { headers })
25    }
26
27    fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
28        var_int::write(self.headers.len() as u64, writer)?;
29        for header in self.headers.iter() {
30            header.write(writer)?;
31            writer.write_u8(0)?;
32        }
33        Ok(())
34    }
35}
36
37impl Payload<Headers> for Headers {
38    fn size(&self) -> usize {
39        var_int::size(self.headers.len() as u64) + (BlockHeader::SIZE + 1) * self.headers.len()
40    }
41}
42
43impl fmt::Debug for Headers {
44    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45        let h = format!("[<{} block headers>]", self.headers.len());
46        f.debug_struct("Headers").field("headers", &h).finish()
47    }
48}
49
50/// Returns the hash for a header at a particular index utilizing prev_hash if possible
51pub fn header_hash(i: usize, headers: &Vec<BlockHeader>) -> Result<Hash256> {
52    if i + 1 < headers.len() {
53        return Ok(headers[i + 1].prev_hash);
54    } else if i + 1 == headers.len() {
55        return Ok(headers[i].hash());
56    } else {
57        return Err(Error::BadArgument("Index out of range".to_string()));
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64    use std::io::Cursor;
65    use util::Hash256;
66
67    #[test]
68    fn write_read() {
69        let mut v = Vec::new();
70        let p = Headers {
71            headers: vec![
72                BlockHeader {
73                    version: 12345,
74                    prev_hash: Hash256::decode(
75                        "7766009988776600998877660099887766009988776600998877660099887766",
76                    ).unwrap(),
77                    merkle_root: Hash256::decode(
78                        "2211554433221155443322115544332211554433221155443322115544332211",
79                    ).unwrap(),
80                    timestamp: 66,
81                    bits: 4488,
82                    nonce: 9999,
83                },
84                BlockHeader {
85                    version: 67890,
86                    prev_hash: Hash256::decode(
87                        "1122334455112233445511223344551122334455112233445511223344551122",
88                    ).unwrap(),
89                    merkle_root: Hash256::decode(
90                        "6677889900667788990066778899006677889900667788990066778899006677",
91                    ).unwrap(),
92                    timestamp: 77,
93                    bits: 5599,
94                    nonce: 1111,
95                },
96            ],
97        };
98        p.write(&mut v).unwrap();
99        assert!(v.len() == p.size());
100        assert!(Headers::read(&mut Cursor::new(&v)).unwrap() == p);
101    }
102
103    #[test]
104    fn header_hash_test() {
105        let header1 = BlockHeader {
106            version: 12345,
107            prev_hash: Hash256::decode(
108                "7766009988776600998877660099887766009988776600998877660099887766",
109            ).unwrap(),
110            merkle_root: Hash256::decode(
111                "2211554433221155443322115544332211554433221155443322115544332211",
112            ).unwrap(),
113            timestamp: 66,
114            bits: 4488,
115            nonce: 9999,
116        };
117
118        let header2 = BlockHeader {
119            version: 67890,
120            prev_hash: header1.hash(),
121            merkle_root: Hash256::decode(
122                "6677889900667788990066778899006677889900667788990066778899006677",
123            ).unwrap(),
124            timestamp: 77,
125            bits: 5599,
126            nonce: 1111,
127        };
128
129        assert!(header_hash(0, &vec![]).is_err());
130
131        let headers = vec![header1.clone()];
132        assert!(header_hash(0, &headers).unwrap() == header1.hash());
133        assert!(header_hash(1, &headers).is_err());
134
135        let headers = vec![header1.clone(), header2.clone()];
136        assert!(header_hash(0, &headers).unwrap() == header1.hash());
137        assert!(header_hash(1, &headers).unwrap() == header2.hash());
138        assert!(header_hash(2, &headers).is_err());
139    }
140}