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}