1use std::cmp;
20use std::sync::Arc;
21use hash::keccak;
22use ethereum_types::{U256, H256, Address};
23use ethjson;
24
25type BlockNumber = u64;
26
27pub type LastHashes = Vec<H256>;
30
31#[derive(Debug, Clone)]
33pub struct EnvInfo {
34	pub number: BlockNumber,
36	pub author: Address,
38	pub timestamp: u64,
40	pub difficulty: U256,
42	pub gas_limit: U256,
44	pub last_hashes: Arc<LastHashes>,
46	pub gas_used: U256,
48}
49
50impl Default for EnvInfo {
51	fn default() -> Self {
52		EnvInfo {
53			number: 0,
54			author: Address::zero(),
55			timestamp: 0,
56			difficulty: 0.into(),
57			gas_limit: 0.into(),
58			last_hashes: Arc::new(vec![]),
59			gas_used: 0.into(),
60		}
61	}
62}
63
64impl From<ethjson::vm::Env> for EnvInfo {
65	fn from(e: ethjson::vm::Env) -> Self {
66		let number = e.number.into();
67		EnvInfo {
68			number,
69			author: e.author.into(),
70			difficulty: e.difficulty.into(),
71			gas_limit: e.gas_limit.into(),
72			timestamp: e.timestamp.into(),
73			last_hashes: Arc::new((1..cmp::min(number + 1, 257)).map(|i| keccak(format!("{}", number - i).as_bytes())).collect()),
74			gas_used: U256::default(),
75		}
76	}
77}
78
79#[cfg(test)]
80mod tests {
81	use std::str::FromStr;
82	use super::*;
83	use ethereum_types::{U256, Address};
84	use ethjson;
85
86	#[test]
87	fn it_serializes_from_json() {
88		let env_info = EnvInfo::from(ethjson::vm::Env {
89			author: ethjson::hash::Address(Address::from_str("000000f00000000f000000000000f00000000f00").unwrap()),
90			number: ethjson::uint::Uint(U256::from(1_112_339)),
91			difficulty: ethjson::uint::Uint(U256::from(50_000)),
92			gas_limit: ethjson::uint::Uint(U256::from(40_000)),
93			timestamp: ethjson::uint::Uint(U256::from(1_100))
94		});
95
96		assert_eq!(env_info.number, 1112339);
97		assert_eq!(env_info.author, Address::from_str("000000f00000000f000000000000f00000000f00").unwrap());
98		assert_eq!(env_info.gas_limit, 40000.into());
99		assert_eq!(env_info.difficulty, 50000.into());
100		assert_eq!(env_info.gas_used, 0.into());
101	}
102
103	#[test]
104	fn it_can_be_created_as_default() {
105		let default_env_info = EnvInfo::default();
106
107		assert_eq!(default_env_info.difficulty, 0.into());
108	}
109}