block/
header.rs

1use rlp::{self, Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp};
2use bigint::{Address, Gas, H256, U256, B256, H64};
3use bloom::LogsBloom;
4use std::cmp::Ordering;
5use sha3::{Keccak256, Digest};
6use super::RlpHash;
7
8pub trait HeaderHash<H: Copy> {
9    fn parent_hash(&self) -> Option<H>;
10    fn header_hash(&self) -> H;
11}
12
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct TotalHeader(pub Header, U256);
15
16impl TotalHeader {
17    pub fn from_genesis(header: Header) -> TotalHeader {
18        let diff = header.difficulty;
19        TotalHeader(header, diff)
20    }
21
22    pub fn from_parent(header: Header, parent: &TotalHeader) -> TotalHeader {
23        let diff = header.difficulty + parent.1;
24        TotalHeader(header, diff)
25    }
26
27    pub fn total_difficulty(&self) -> U256 {
28        self.1
29    }
30}
31
32impl HeaderHash<H256> for TotalHeader {
33    fn parent_hash(&self) -> Option<H256> {
34        self.0.parent_hash()
35    }
36
37    fn header_hash(&self) -> H256 {
38        self.0.header_hash()
39    }
40}
41
42impl Into<Header> for TotalHeader {
43    fn into(self) -> Header {
44        self.0
45    }
46}
47
48impl Ord for TotalHeader {
49    fn cmp(&self, other: &TotalHeader) -> Ordering {
50        self.1.cmp(&other.1)
51    }
52}
53
54impl PartialOrd for TotalHeader {
55    fn partial_cmp(&self, other: &TotalHeader) -> Option<Ordering> {
56        Some(self.cmp(other))
57    }
58}
59
60#[derive(Clone, Debug, PartialEq, Eq)]
61pub struct Header {
62    pub parent_hash: H256,
63    pub ommers_hash: H256,
64    pub beneficiary: Address,
65    pub state_root: H256,
66    pub transactions_root: H256,
67    pub receipts_root: H256,
68    pub logs_bloom: LogsBloom,
69    pub difficulty: U256,
70    pub number: U256,
71    pub gas_limit: Gas,
72    pub gas_used: Gas,
73    pub timestamp: u64,
74    pub extra_data: B256,
75    pub mix_hash: H256,
76    pub nonce: H64,
77}
78
79impl HeaderHash<H256> for Header {
80    fn parent_hash(&self) -> Option<H256> {
81        if self.number == U256::zero() {
82            None
83        } else {
84            Some(self.parent_hash)
85        }
86    }
87
88    fn header_hash(&self) -> H256 {
89        H256::from(Keccak256::digest(&rlp::encode(self).to_vec()).as_slice())
90    }
91}
92
93impl Header {
94    pub fn partial_rlp_append(&self, s: &mut RlpStream) {
95        s.begin_list(13);
96        s.append(&self.parent_hash);
97        s.append(&self.ommers_hash);
98        s.append(&self.beneficiary);
99        s.append(&self.state_root);
100        s.append(&self.transactions_root);
101        s.append(&self.receipts_root);
102        s.append(&self.logs_bloom);
103        s.append(&self.difficulty);
104        s.append(&self.number);
105        s.append(&self.gas_limit);
106        s.append(&self.gas_used);
107        s.append(&self.timestamp);
108        s.append(&self.extra_data);
109    }
110
111    pub fn partial_hash(&self) -> H256 {
112        let mut stream = RlpStream::new();
113        self.partial_rlp_append(&mut stream);
114        H256::from(Keccak256::digest(&stream.drain()).as_slice())
115    }
116}
117
118impl Encodable for Header {
119    fn rlp_append(&self, s: &mut RlpStream) {
120        s.begin_list(15);
121        s.append(&self.parent_hash);
122        s.append(&self.ommers_hash);
123        s.append(&self.beneficiary);
124        s.append(&self.state_root);
125        s.append(&self.transactions_root);
126        s.append(&self.receipts_root);
127        s.append(&self.logs_bloom);
128        s.append(&self.difficulty);
129        s.append(&self.number);
130        s.append(&self.gas_limit);
131        s.append(&self.gas_used);
132        s.append(&self.timestamp);
133        s.append(&self.extra_data);
134        s.append(&self.mix_hash);
135        s.append(&self.nonce);
136    }
137}
138
139impl Decodable for Header {
140    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
141        Ok(Self {
142            parent_hash: rlp.val_at(0)?,
143            ommers_hash: rlp.val_at(1)?,
144            beneficiary: rlp.val_at(2)?,
145            state_root: rlp.val_at(3)?,
146            transactions_root: rlp.val_at(4)?,
147            receipts_root: rlp.val_at(5)?,
148            logs_bloom: rlp.val_at(6)?,
149            difficulty: rlp.val_at(7)?,
150            number: rlp.val_at(8)?,
151            gas_limit: rlp.val_at(9)?,
152            gas_used: rlp.val_at(10)?,
153            timestamp: rlp.val_at(11)?,
154            extra_data: rlp.val_at(12)?,
155            mix_hash: rlp.val_at(13)?,
156            nonce: rlp.val_at(14)?,
157        })
158    }
159}
160
161impl RlpHash for Header {
162    fn rlp_hash(&self) -> H256 {
163        H256::from(Keccak256::digest(&rlp::encode(self)).as_slice())
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    use rlp::{encode, decode, Rlp};
170    use hexutil::read_hex;
171    use bigint::{U256, H256, Address, Gas};
172    use bloom::LogsBloom;
173    use header::Header;
174    use std::str::FromStr;
175
176    #[test]
177    fn block_0_rlp() {
178        let raw = read_hex("f90219f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000850400000000808213888080a011bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82faa00000000000000000000000000000000000000000000000000000000000000000880000000000000042c0c0").unwrap();
179        let block_raw = Rlp::new(&raw);
180        let block: Header = block_raw.val_at(0);
181        assert_eq!(block.number, U256::from(0u64));
182
183        let encoded = encode(&block).to_vec();
184        let encoded_ref: &[u8] = encoded.as_ref();
185        assert_eq!(encoded_ref, block_raw.at(0).as_raw());
186    }
187
188    #[test]
189    fn block_1_rlp() {
190        let raw = read_hex("f90216f90211a0d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479405a56e2d52c817161883f50c441c3228cfe54d9fa0d67e4d450343046425ae4271474353857ab860dbc0a1dde64b41b5cd3a532bf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008503ff80000001821388808455ba422499476574682f76312e302e302f6c696e75782f676f312e342e32a0969b900de27b6ac6a67742365dd65f55a0526c41fd18e1b16f1a1215c2e66f5988539bd4979fef1ec4c0c0").unwrap();
191        let block_raw = Rlp::new(&raw);
192        let block: Header = block_raw.val_at(0);
193        assert_eq!(block.parent_hash, H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap());
194        assert_eq!(block.ommers_hash, H256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap());
195        assert_eq!(block.beneficiary, Address::from_str("05a56e2d52c817161883f50c441c3228cfe54d9f").unwrap());
196        assert_eq!(block.state_root, H256::from_str("d67e4d450343046425ae4271474353857ab860dbc0a1dde64b41b5cd3a532bf3").unwrap());
197        assert_eq!(block.transactions_root, H256::from_str("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap());
198        assert_eq!(block.logs_bloom, LogsBloom::default());
199        assert_eq!(block.difficulty, U256::from(17171480576u64));
200        assert_eq!(block.number, U256::from(1u64));
201        assert_eq!(block.gas_limit, Gas::from(5000u64));
202        assert_eq!(block.gas_used, Gas::zero());
203        assert_eq!(block.timestamp, 1438269988u64);
204        assert_eq!(block, decode(&encode(&block).to_vec()));
205
206        let encoded = encode(&block).to_vec();
207        let encoded_ref: &[u8] = encoded.as_ref();
208        assert_eq!(encoded_ref, block_raw.at(0).as_raw());
209    }
210}