1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use primitives::compact::Compact;
use chain::IndexedBlockHeader;
use network::Network;
use work::is_valid_proof_of_work;
use error::Error;
use constants::BLOCK_MAX_FUTURE;

pub struct HeaderVerifier<'a> {
	pub proof_of_work: HeaderProofOfWork<'a>,
	pub timestamp: HeaderTimestamp<'a>,
}

impl<'a> HeaderVerifier<'a> {
	pub fn new(header: &'a IndexedBlockHeader, network: Network, current_time: u32) -> Self {
		HeaderVerifier {
			proof_of_work: HeaderProofOfWork::new(header, network),
			timestamp: HeaderTimestamp::new(header, current_time, BLOCK_MAX_FUTURE as u32),
		}
	}

	pub fn check(&self) -> Result<(), Error> {
		try!(self.proof_of_work.check());
		try!(self.timestamp.check());
		Ok(())
	}
}

pub struct HeaderProofOfWork<'a> {
	header: &'a IndexedBlockHeader,
	max_work_bits: Compact,
}

impl<'a> HeaderProofOfWork<'a> {
	fn new(header: &'a IndexedBlockHeader, network: Network) -> Self {
		HeaderProofOfWork {
			header: header,
			max_work_bits: network.max_bits().into(),
		}
	}

	fn check(&self) -> Result<(), Error> {
		if is_valid_proof_of_work(self.max_work_bits, self.header.raw.bits, &self.header.hash) {
			Ok(())
		} else {
			Err(Error::Pow)
		}
	}
}

pub struct HeaderTimestamp<'a> {
	header: &'a IndexedBlockHeader,
	current_time: u32,
	max_future: u32,
}

impl<'a> HeaderTimestamp<'a> {
	fn new(header: &'a IndexedBlockHeader, current_time: u32, max_future: u32) -> Self {
		HeaderTimestamp {
			header: header,
			current_time: current_time,
			max_future: max_future,
		}
	}

	fn check(&self) -> Result<(), Error> {
		if self.header.raw.time > self.current_time + self.max_future {
			Err(Error::FuturisticTimestamp)
		} else {
			Ok(())
		}
	}
}