diff --git a/src/account.rs b/src/account.rs index cd5a310e8..095380116 100644 --- a/src/account.rs +++ b/src/account.rs @@ -4,26 +4,25 @@ use itertools::Itertools; pub const SHA3_EMPTY: H256 = H256( [0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70] ); #[derive(Debug,Clone,PartialEq,Eq)] -pub struct Diff where T: Eq { - pub pre: T, - pub post_opt: Option, +pub enum Diff where T: Eq { + Same, + Born(T), + Changed(T, T), + Died(T), +} + +#[derive(Debug,Clone,PartialEq,Eq)] +pub enum Existance { + Born, + Alive, + Died, } impl Diff where T: Eq { - pub fn new_opt(pre: T, post: T) -> Option { if pre == post { None } else { Some(Self::new(pre, post)) } } - pub fn one_opt(t: T) -> Option { Some(Self::one(t)) } - - pub fn new(pre: T, post: T) -> Self { Diff { pre: pre, post_opt: Some(post) }} - pub fn one(t: T) -> Self { Diff { pre: t, post_opt: None }} - - pub fn pre(&self) -> &T { &self.pre } - pub fn post(&self) -> &T { match self.post_opt { Some(ref x) => x, None => &self.pre } } -} - -impl From for Diff where T: Eq { - fn from(t: T) -> Diff { - Diff::one(t) - } + pub fn new(pre: T, post: T) -> Self { if pre == post { Diff::Same } else { Diff::Changed(pre, post) } } + pub fn pre(&self) -> Option<&T> { match self { &Diff::Died(ref x) | &Diff::Changed(ref x, _) => Some(x), _ => None } } + pub fn post(&self) -> Option<&T> { match self { &Diff::Born(ref x) | &Diff::Changed(_, ref x) => Some(x), _ => None } } + pub fn is_same(&self) -> bool { match self { &Diff::Same => true, _ => false }} } #[derive(Debug,Clone,PartialEq,Eq)] @@ -39,42 +38,62 @@ pub struct PodAccount { #[derive(Debug,Clone,PartialEq,Eq)] pub struct AccountDiff { - pub exists: Diff, - pub balance: Option>, - pub nonce: Option>, - pub code: Option>, - pub storage: BTreeMap>, + pub balance: Diff, // Allowed to be Same + pub nonce: Diff, // Allowed to be Same + pub code: Diff, // Allowed to be Same + pub storage: BTreeMap>,// Not allowed to be Same } +impl AccountDiff { + pub fn existance(&self) -> Existance { + match self.balance { + Diff::Born(_) => Existance::Born, + Diff::Died(_) => Existance::Died, + _ => Existance::Alive, + } + } +} + +/*impl Debug for AccountDiff { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", PodAccount::from_account(self)) + } +}*/ + pub type StateDiff = BTreeMap; pub fn pod_diff(pre: Option<&PodAccount>, post: Option<&PodAccount>) -> Option { match (pre, post) { - (Some(x), None) | (None, Some(x)) => Some(AccountDiff { - exists: Diff::new(pre.is_some(), post.is_some()), - balance: Diff::one_opt(x.balance.clone()), - nonce: Diff::one_opt(x.nonce.clone()), - code: Diff::one_opt(x.code.clone()), - storage: x.storage.iter().fold(BTreeMap::new(), |mut m, (k, v)| {m.insert(k.clone(), Diff::one(v.clone())); m}) + (None, Some(x)) => Some(AccountDiff { + balance: Diff::Born(x.balance.clone()), + nonce: Diff::Born(x.nonce.clone()), + code: Diff::Born(x.code.clone()), + storage: x.storage.iter().map(|(k, v)| (k.clone(), Diff::Born(v.clone()))).collect(), + }), + (Some(x), None) => Some(AccountDiff { + balance: Diff::Died(x.balance.clone()), + nonce: Diff::Died(x.nonce.clone()), + code: Diff::Died(x.code.clone()), + storage: x.storage.iter().map(|(k, v)| (k.clone(), Diff::Died(v.clone()))).collect(), }), (Some(pre), Some(post)) => { let storage: Vec<_> = pre.storage.keys().merge(post.storage.keys()) .filter(|k| pre.storage.get(k).unwrap_or(&H256::new()) != post.storage.get(k).unwrap_or(&H256::new())) .collect(); - if pre.balance != post.balance || pre.nonce != post.nonce || pre.code != post.code || storage.len() > 0 { - Some(AccountDiff { - exists: Diff::one(true), - balance: Diff::new_opt(pre.balance.clone(), post.balance.clone()), - nonce: Diff::new_opt(pre.nonce.clone(), post.nonce.clone()), - code: Diff::new_opt(pre.code.clone(), post.code.clone()), - storage: storage.into_iter().fold(BTreeMap::new(), |mut m, k| { - let v = Diff::new(pre.storage.get(&k).cloned().unwrap_or(H256::new()), post.storage.get(&k).cloned().unwrap_or(H256::new())); - m.insert((*k).clone(), v); - m - }), - }) - } else { + let r = AccountDiff { + balance: Diff::new(pre.balance.clone(), post.balance.clone()), + nonce: Diff::new(pre.nonce.clone(), post.nonce.clone()), + code: Diff::new(pre.code.clone(), post.code.clone()), + storage: storage.into_iter().map(|k| + (k.clone(), Diff::new( + pre.storage.get(&k).cloned().unwrap_or(H256::new()), + post.storage.get(&k).cloned().unwrap_or(H256::new()) + ))).collect(), + }; + if r.balance.is_same() && r.nonce.is_same() && r.code.is_same() && r.storage.len() == 0 { None + } else { + Some(r) } }, _ => None, @@ -82,28 +101,7 @@ pub fn pod_diff(pre: Option<&PodAccount>, post: Option<&PodAccount>) -> Option, post: &BTreeMap) -> StateDiff { - pre.keys() - .merge(post.keys()) - .filter_map(|acc| pod_diff(pre.get(acc), post.get(acc)).map(|d|(acc.clone(), d))) - .collect::>() -} - -macro_rules! map { - ( $( $x:expr => $y:expr ),* ) => { - vec![ $( ($x, $y) ),* ].into_iter().collect::>() - } -} - -macro_rules! x { - ( $x:expr ) => { - From::from($x) - } -} - -macro_rules! xx { - ( $x:expr ) => { - From::from(From::from($x)) - } + pre.keys().merge(post.keys()).filter_map(|acc| pod_diff(pre.get(acc), post.get(acc)).map(|d|(acc.clone(), d))).collect() } #[test] @@ -118,19 +116,17 @@ fn state_diff_create_delete() { ]; assert_eq!(pod_map_diff(&a, &map![]), map![ x!(1) => AccountDiff{ - exists: Diff::new(true, false), - balance: Diff::one_opt(x!(69)), - nonce: Diff::one_opt(x!(0)), - code: Diff::one_opt(vec![]), + balance: Diff::Died(x!(69)), + nonce: Diff::Died(x!(0)), + code: Diff::Died(vec![]), storage: map![], } ]); assert_eq!(pod_map_diff(&map![], &a), map![ x!(1) => AccountDiff{ - exists: Diff::new(false, true), - balance: Diff::one_opt(x!(69)), - nonce: Diff::one_opt(x!(0)), - code: Diff::one_opt(vec![]), + balance: Diff::Born(x!(69)), + nonce: Diff::Born(x!(0)), + code: Diff::Born(vec![]), storage: map![], } ]); @@ -162,19 +158,17 @@ fn state_diff_cretae_delete_with_unchanged() { ]; assert_eq!(pod_map_diff(&a, &b), map![ x!(2) => AccountDiff{ - exists: Diff::new(false, true), - balance: Diff::one_opt(x!(69)), - nonce: Diff::one_opt(x!(0)), - code: Diff::one_opt(vec![]), + balance: Diff::Born(x!(69)), + nonce: Diff::Born(x!(0)), + code: Diff::Born(vec![]), storage: map![], } ]); assert_eq!(pod_map_diff(&b, &a), map![ x!(2) => AccountDiff{ - exists: Diff::new(true, false), - balance: Diff::one_opt(x!(69)), - nonce: Diff::one_opt(x!(0)), - code: Diff::one_opt(vec![]), + balance: Diff::Died(x!(69)), + nonce: Diff::Died(x!(0)), + code: Diff::Died(vec![]), storage: map![], } ]); @@ -212,10 +206,9 @@ fn state_diff_change_with_unchanged() { ]; assert_eq!(pod_map_diff(&a, &b), map![ x!(1) => AccountDiff{ - exists: Diff::one(true), - balance: None, - nonce: Diff::new_opt(x!(0), x!(1)), - code: None, + balance: Diff::Same, + nonce: Diff::Changed(x!(0), x!(1)), + code: Diff::Same, storage: map![], } ]); @@ -226,62 +219,62 @@ fn account_diff_existence() { let a = PodAccount{balance: x!(69), nonce: x!(0), code: vec![], storage: map![]}; assert_eq!(pod_diff(Some(&a), Some(&a)), None); assert_eq!(pod_diff(None, Some(&a)), Some(AccountDiff{ - exists: Diff::new(false, true), - balance: Diff::one_opt(x!(69)), - nonce: Diff::one_opt(x!(0)), - code: Diff::one_opt(vec![]), + balance: Diff::Born(x!(69)), + nonce: Diff::Born(x!(0)), + code: Diff::Born(vec![]), storage: map![], })); } #[test] fn account_diff_basic() { - let a = PodAccount{balance: U256::from(69u64), nonce: U256::zero(), code: vec![], storage: BTreeMap::new()}; - let b = PodAccount{balance: U256::from(42u64), nonce: U256::from(1u64), code: vec![], storage: BTreeMap::new()}; + let a = PodAccount{balance: x!(69), nonce: x!(0), code: vec![], storage: map![]}; + let b = PodAccount{balance: x!(42), nonce: x!(1), code: vec![], storage: map![]}; assert_eq!(pod_diff(Some(&a), Some(&b)), Some(AccountDiff { - exists: Diff::one(true), - balance: Diff::new_opt(U256::from(69u64), U256::from(42u64)), - nonce: Diff::new_opt(U256::zero(), U256::from(1u64)), - code: None, - storage: BTreeMap::new(), + balance: Diff::Changed(x!(69), x!(42)), + nonce: Diff::Changed(x!(0), x!(1)), + code: Diff::Same, + storage: map![], })); } #[test] fn account_diff_code() { - let a = PodAccount{balance: U256::zero(), nonce: U256::zero(), code: vec![], storage: BTreeMap::new()}; - let b = PodAccount{balance: U256::zero(), nonce: U256::from(1u64), code: vec![0x00u8], storage: BTreeMap::new()}; + let a = PodAccount{balance: x!(0), nonce: x!(0), code: vec![], storage: map![]}; + let b = PodAccount{balance: x!(0), nonce: x!(1), code: vec![0], storage: map![]}; assert_eq!(pod_diff(Some(&a), Some(&b)), Some(AccountDiff { - exists: Diff::one(true), - balance: None, - nonce: Diff::new_opt(U256::zero(), U256::from(1u64)), - code: Diff::new_opt(vec![], vec![0x00u8]), - storage: BTreeMap::new(), + balance: Diff::Same, + nonce: Diff::Changed(x!(0), x!(1)), + code: Diff::Changed(vec![], vec![0]), + storage: map![], })); } -pub fn h256_from_u8(v: u8) -> H256 { - let mut r = H256::new(); - r[31] = v; - r -} - #[test] fn account_diff_storage() { - let a = PodAccount{balance: U256::zero(), nonce: U256::zero(), code: vec![], storage: vec![(1u8, 1u8), (2, 2), (3, 3), (4, 4), (5, 0), (6, 0), (7, 0)].into_iter().fold(BTreeMap::new(), |mut m, (k, v)|{m.insert(h256_from_u8(k), h256_from_u8(v)); m})}; - let b = PodAccount{balance: U256::zero(), nonce: U256::zero(), code: vec![], storage: vec![(1u8, 1u8), (2, 3), (3, 0), (5, 0), (7, 7), (8, 0), (9, 9)].into_iter().fold(BTreeMap::new(), |mut m, (k, v)|{m.insert(h256_from_u8(k), h256_from_u8(v)); m})}; + let a = PodAccount { + balance: x!(0), + nonce: x!(0), + code: vec![], + storage: mapx![1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 0, 6 => 0, 7 => 0] + }; + let b = PodAccount { + balance: x!(0), + nonce: x!(0), + code: vec![], + storage: mapx![1 => 1, 2 => 3, 3 => 0, 5 => 0, 7 => 7, 8 => 0, 9 => 9] + }; assert_eq!(pod_diff(Some(&a), Some(&b)), Some(AccountDiff { - exists: Diff::one(true), - balance: None, - nonce: None, - code: None, - storage: vec![ - (2u8, Diff::new(h256_from_u8(2), h256_from_u8(3))), - (3, Diff::new(h256_from_u8(3), H256::new())), - (4, Diff::new(h256_from_u8(4), H256::new())), - (7, Diff::new(H256::new(), h256_from_u8(7))), - (9, Diff::new(H256::new(), h256_from_u8(9))), - ].into_iter().fold(BTreeMap::new(), |mut m, (k, v)|{m.insert(h256_from_u8(k), v); m}) + balance: Diff::Same, + nonce: Diff::Same, + code: Diff::Same, + storage: map![ + x!(2) => Diff::new(x!(2), x!(3)), + x!(3) => Diff::new(x!(3), x!(0)), + x!(4) => Diff::new(x!(4), x!(0)), + x!(7) => Diff::new(x!(0), x!(7)), + x!(9) => Diff::new(x!(0), x!(9)) + ], })); } diff --git a/src/evm/schedule.rs b/src/evm/schedule.rs index 0f46bba12..d02fedc91 100644 --- a/src/evm/schedule.rs +++ b/src/evm/schedule.rs @@ -50,7 +50,7 @@ impl Schedule { exceptional_failed_code_deposit: efcd, have_delegate_call: hdc, stack_limit: 1024, - tier_step_gas: [0usize, 2, 3, 4, 5, 6, 10, 20], + tier_step_gas: [0usize, 2, 3, 4, 5, 8, 10, 20], exp_gas: 10, exp_byte_gas: 10, sha3_gas: 30, diff --git a/src/lib.rs b/src/lib.rs index 5cecba2b8..8610404d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,7 +84,7 @@ extern crate time; extern crate env_logger; #[cfg(feature = "jit" )] extern crate evmjit; -extern crate ethcore_util as util; +#[macro_use] extern crate ethcore_util as util; pub mod common; pub mod basic_types; diff --git a/src/tests/state.rs b/src/tests/state.rs index b9666a836..6ae01a334 100644 --- a/src/tests/state.rs +++ b/src/tests/state.rs @@ -2,13 +2,6 @@ use super::test_common::*; use state::*; use ethereum; -pub fn hashmap_h256_h256_from_json(json: &Json) -> HashMap { - json.as_object().unwrap().iter().fold(HashMap::new(), |mut m, (key, value)| { - m.insert(H256::from(&u256_from_str(key)), H256::from(&u256_from_json(value))); - m - }) -} - pub fn map_h256_h256_from_json(json: &Json) -> BTreeMap { json.as_object().unwrap().iter().fold(BTreeMap::new(), |mut m, (key, value)| { m.insert(H256::from(&u256_from_str(key)), H256::from(&u256_from_json(value)));