use std::cmp;
use std::sync::Arc;
use hash::keccak;
use ethereum_types::{U256, H256, Address};
use ethjson;
type BlockNumber = u64;
pub type LastHashes = Vec<H256>;
#[derive(Debug, Clone)]
pub struct EnvInfo {
pub number: BlockNumber,
pub author: Address,
pub timestamp: u64,
pub difficulty: U256,
pub gas_limit: U256,
pub last_hashes: Arc<LastHashes>,
pub gas_used: U256,
}
impl Default for EnvInfo {
fn default() -> Self {
EnvInfo {
number: 0,
author: Address::zero(),
timestamp: 0,
difficulty: 0.into(),
gas_limit: 0.into(),
last_hashes: Arc::new(vec![]),
gas_used: 0.into(),
}
}
}
impl From<ethjson::vm::Env> for EnvInfo {
fn from(e: ethjson::vm::Env) -> Self {
let number = e.number.into();
EnvInfo {
number,
author: e.author.into(),
difficulty: e.difficulty.into(),
gas_limit: e.gas_limit.into(),
timestamp: e.timestamp.into(),
last_hashes: Arc::new((1..cmp::min(number + 1, 257)).map(|i| keccak(format!("{}", number - i).as_bytes())).collect()),
gas_used: U256::default(),
}
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use super::*;
use ethereum_types::{U256, Address};
use ethjson;
#[test]
fn it_serializes_from_json() {
let env_info = EnvInfo::from(ethjson::vm::Env {
author: ethjson::hash::Address(Address::from_str("000000f00000000f000000000000f00000000f00").unwrap()),
number: ethjson::uint::Uint(U256::from(1_112_339)),
difficulty: ethjson::uint::Uint(U256::from(50_000)),
gas_limit: ethjson::uint::Uint(U256::from(40_000)),
timestamp: ethjson::uint::Uint(U256::from(1_100))
});
assert_eq!(env_info.number, 1112339);
assert_eq!(env_info.author, Address::from_str("000000f00000000f000000000000f00000000f00").unwrap());
assert_eq!(env_info.gas_limit, 40000.into());
assert_eq!(env_info.difficulty, 50000.into());
assert_eq!(env_info.gas_used, 0.into());
}
#[test]
fn it_can_be_created_as_default() {
let default_env_info = EnvInfo::default();
assert_eq!(default_env_info.difficulty, 0.into());
}
}