cs_mwc_bch/messages/
block_header.rs

1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use std::cmp::min;
3use std::io;
4use std::io::{Read, Write};
5use util::{sha256d, Error, Hash256, Result, Serializable};
6
7/// Block header
8#[derive(Debug, Default, PartialEq, Eq, Hash, Clone)]
9pub struct BlockHeader {
10    /// Block version specifying which validation rules to use
11    pub version: u32,
12    /// Hash of the previous block
13    pub prev_hash: Hash256,
14    /// Root of the merkle tree of this block's transaction hashes
15    pub merkle_root: Hash256,
16    /// Timestamp when this block was created as recorded by the miner
17    pub timestamp: u32,
18    /// Target difficulty bits
19    pub bits: u32,
20    /// Nonce used to mine the block
21    pub nonce: u32,
22}
23
24impl BlockHeader {
25    /// Size of the BlockHeader in bytes
26    pub const SIZE: usize = 80;
27
28    /// Returns the size of the block header in bytes
29    pub fn size(&self) -> usize {
30        BlockHeader::SIZE
31    }
32
33    /// Calculates the hash for this block header
34    pub fn hash(&self) -> Hash256 {
35        let mut v = Vec::with_capacity(80);
36        v.write_u32::<LittleEndian>(self.version).unwrap();
37        self.prev_hash.write(&mut v).unwrap();
38        self.merkle_root.write(&mut v).unwrap();
39        v.write_u32::<LittleEndian>(self.timestamp).unwrap();
40        v.write_u32::<LittleEndian>(self.bits).unwrap();
41        v.write_u32::<LittleEndian>(self.nonce).unwrap();
42        sha256d(&v)
43    }
44
45    /// Checks that the block header is valid
46    pub fn validate(&self, hash: &Hash256, prev_headers: &[BlockHeader]) -> Result<()> {
47        // Timestamp > median timestamp of last 11 blocks
48        if prev_headers.len() > 0 {
49            let h = &prev_headers[prev_headers.len() - min(prev_headers.len(), 11)..];
50            let mut timestamps: Vec<u32> = h.iter().map(|x| x.timestamp).collect();
51            timestamps.sort();
52            if self.timestamp < timestamps[timestamps.len() / 2] {
53                let msg = format!("Timestamp is too old: {}", self.timestamp);
54                return Err(Error::BadData(msg));
55            }
56        }
57
58        // POW
59        let target = self.difficulty_target()?;
60        if hash > &target {
61            return Err(Error::BadData("Invalid POW".to_string()));
62        }
63
64        Ok(())
65    }
66
67    /// Calculates the target difficulty hash
68    fn difficulty_target(&self) -> Result<Hash256> {
69        let exp = (self.bits >> 24) as usize;
70        if exp < 3 || exp > 32 {
71            let msg = format!("Difficulty exponent out of range: {:?}", self.bits);
72            return Err(Error::BadArgument(msg));
73        }
74        let mut difficulty = [0_u8; 32];
75        difficulty[exp - 1] = ((self.bits >> 16) & 0xff) as u8;
76        difficulty[exp - 2] = ((self.bits >> 08) & 0xff) as u8;
77        difficulty[exp - 3] = ((self.bits >> 00) & 0xff) as u8;
78        Ok(Hash256(difficulty))
79    }
80}
81
82impl Serializable<BlockHeader> for BlockHeader {
83    fn read(reader: &mut dyn Read) -> Result<BlockHeader> {
84        let version = reader.read_u32::<LittleEndian>()?;
85        let prev_hash = Hash256::read(reader)?;
86        let merkle_root = Hash256::read(reader)?;
87        let ts = reader.read_u32::<LittleEndian>()?;
88        let bits = reader.read_u32::<LittleEndian>()?;
89        let nonce = reader.read_u32::<LittleEndian>()?;
90        Ok(BlockHeader {
91            version,
92            prev_hash,
93            merkle_root,
94            timestamp: ts,
95            bits,
96            nonce,
97        })
98    }
99
100    fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
101        writer.write_u32::<LittleEndian>(self.version)?;
102        self.prev_hash.write(writer)?;
103        self.merkle_root.write(writer)?;
104        writer.write_u32::<LittleEndian>(self.timestamp)?;
105        writer.write_u32::<LittleEndian>(self.bits)?;
106        writer.write_u32::<LittleEndian>(self.nonce)?;
107        Ok(())
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114    use std::io::Cursor;
115
116    #[test]
117    fn write_read() {
118        let mut v = Vec::new();
119        let block_header = BlockHeader {
120            version: 12345,
121            prev_hash: Hash256::decode(
122                "7766009988776600998877660099887766009988776600998877660099887766",
123            ).unwrap(),
124            merkle_root: Hash256::decode(
125                "2211554433221155443322115544332211554433221155443322115544332211",
126            ).unwrap(),
127            timestamp: 66,
128            bits: 4488,
129            nonce: 9999,
130        };
131        block_header.write(&mut v).unwrap();
132        assert!(v.len() == block_header.size());
133        assert!(BlockHeader::read(&mut Cursor::new(&v)).unwrap() == block_header);
134    }
135
136    #[test]
137    fn hash() {
138        let block_header = BlockHeader {
139            version: 0x00000001,
140            prev_hash: Hash256::decode(
141                "00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81",
142            ).unwrap(),
143            merkle_root: Hash256::decode(
144                "2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3",
145            ).unwrap(),
146            timestamp: 0x4dd7f5c7,
147            bits: 0x1a44b9f2,
148            nonce: 0x9546a142,
149        };
150        let str_hash = block_header.hash().encode();
151        let expected_hash = "00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d";
152        assert!(str_hash == expected_hash);
153    }
154
155    #[test]
156    fn validate() {
157        let prev_hash =
158            Hash256::decode("00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81")
159                .unwrap();
160
161        let mut headers = Vec::new();
162        for i in 0..11 {
163            headers.push(BlockHeader {
164                timestamp: i * 10,
165                ..Default::default()
166            });
167        }
168
169        let valid = BlockHeader {
170            version: 0x00000001,
171            prev_hash,
172            merkle_root: Hash256::decode(
173                "2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3",
174            ).unwrap(),
175            timestamp: 0x4dd7f5c7,
176            bits: 0x1a44b9f2,
177            nonce: 0x9546a142,
178        };
179        assert!(valid.validate(&valid.hash(), &headers).is_ok());
180
181        // Bad timestamp
182        let h = valid.clone();
183        for header in headers.iter_mut() {
184            header.timestamp = valid.timestamp + 1;
185        }
186        assert!(h.validate(&h.hash(), &headers).is_err());
187
188        // Bad POW
189        let mut h = valid.clone();
190        h.nonce = 0;
191        assert!(h.validate(&h.hash(), &headers).is_err());
192    }
193}