diff --git a/src/account.rs b/src/account.rs index 657f1d23b..8509438f7 100644 --- a/src/account.rs +++ b/src/account.rs @@ -70,8 +70,15 @@ impl Account { } } + /// Reset this account to the status of a not-yet-initialised contract. + /// NOTE: Account should have `init_code()` called on it later. + pub fn reset_code(&mut self) { + self.code_hash = None; + self.code_cache = vec![]; + } + /// Set this account's code to the given code. - /// NOTE: Account should have been created with `new_contract`. + /// NOTE: Account should have been created with `new_contract()` or have `reset_code()` called on it. pub fn init_code(&mut self, code: Bytes) { assert!(self.code_hash.is_none()); self.code_cache = code; diff --git a/src/ethash.rs b/src/ethash.rs index 219d0f870..8ab0e0a06 100644 --- a/src/ethash.rs +++ b/src/ethash.rs @@ -36,5 +36,5 @@ fn playpen() { let genesis_header = engine.spec().genesis_header(); let mut db = OverlayDB::new_temp(); engine.spec().ensure_db_good(&mut db); - let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()]); +// let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()]); } \ No newline at end of file diff --git a/src/spec.rs b/src/spec.rs index a3fafa60f..edcafd6af 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -206,15 +206,16 @@ impl Spec { Spec { engine_name: "Ethash".to_string(), engine_params: vec![ - ("block_reward", encode(&(finney() * U256::from(1500u64)))), - ("maximum_extra_data_size", encode(&U256::from(1024u64))), - ("account_start_nonce", encode(&U256::from(0u64))), - ("gas_limit_bounds_divisor", encode(&1024u64)), - ("minimum_difficulty", encode(&131_072u64)), - ("difficulty_bound_divisor", encode(&2048u64)), - ("duration_limit", encode(&8u64)), - ("min_gas_limit", encode(&125_000u64)), - ("gas_floor_target", encode(&3_141_592u64)), + ("blockReward", encode(&(finney() * U256::from(1500u64)))), + ("frontierCompatibilityModeLimit", encode(&0xffffffffu64)), + ("maximumExtraDataSize", encode(&U256::from(1024u64))), + ("accountStartNonce", encode(&U256::from(0u64))), + ("gasLimitBoundsDivisor", encode(&1024u64)), + ("minimumDifficulty", encode(&131_072u64)), + ("difficultyBoundDivisor", encode(&2048u64)), + ("durationLimit", encode(&8u64)), + ("minGasLimit", encode(&125_000u64)), + ("gasFloorTarget", encode(&3_141_592u64)), ].into_iter().fold(HashMap::new(), | mut acc, vec | { acc.insert(vec.0.to_string(), vec.1); acc @@ -244,15 +245,16 @@ impl Spec { Spec { engine_name: "Ethash".to_string(), engine_params: vec![ - ("block_reward", encode(&(ether() * U256::from(5u64)))), - ("maximum_extra_data_size", encode(&U256::from(32u64))), - ("account_start_nonce", encode(&U256::from(0u64))), - ("gas_limit_bounds_divisor", encode(&1024u64)), - ("minimum_difficulty", encode(&131_072u64)), - ("difficulty_bound_divisor", encode(&2048u64)), - ("duration_limit", encode(&13u64)), - ("min_gas_limit", encode(&5000u64)), - ("gas_floor_target", encode(&3_141_592u64)), + ("blockReward", encode(&(ether() * U256::from(5u64)))), + ("frontierCompatibilityModeLimit", encode(&0xfffa2990u64)), + ("maximumExtraDataSize", encode(&U256::from(32u64))), + ("accountStartNonce", encode(&U256::from(0u64))), + ("gasLimitBoundsDivisor", encode(&1024u64)), + ("minimumDifficulty", encode(&131_072u64)), + ("difficultyBoundDivisor", encode(&2048u64)), + ("durationLimit", encode(&13u64)), + ("minGasLimit", encode(&5000u64)), + ("gasFloorTarget", encode(&3_141_592u64)), ].into_iter().fold(HashMap::new(), | mut acc, vec | { acc.insert(vec.0.to_string(), vec.1); acc @@ -282,15 +284,16 @@ impl Spec { Spec { engine_name: "Ethash".to_string(), engine_params: vec![ - ("block_reward", encode(&(ether() * U256::from(5u64)))), - ("maximum_extra_data_size", encode(&U256::from(32u64))), - ("account_start_nonce", encode(&(U256::from(1u64) << 20))), - ("gas_limit_bounds_divisor", encode(&1024u64)), - ("minimum_difficulty", encode(&131_072u64)), - ("difficulty_bound_divisor", encode(&2048u64)), - ("duration_limit", encode(&13u64)), - ("min_gas_limit", encode(&5000u64)), - ("gas_floor_target", encode(&3_141_592u64)), + ("blockReward", encode(&(ether() * U256::from(5u64)))), + ("frontierCompatibilityModeLimit", encode(&0xfffa2990u64)), + ("maximumExtraDataSize", encode(&U256::from(32u64))), + ("accountStartNonce", encode(&(U256::from(1u64) << 20))), + ("gasLimitBoundsDivisor", encode(&1024u64)), + ("minimumDifficulty", encode(&131_072u64)), + ("difficultyBoundDivisor", encode(&2048u64)), + ("durationLimit", encode(&13u64)), + ("minGasLimit", encode(&5000u64)), + ("gasFloorTarget", encode(&3_141_592u64)), ].into_iter().fold(HashMap::new(), | mut acc, vec | { acc.insert(vec.0.to_string(), vec.1); acc diff --git a/src/state.rs b/src/state.rs index 80c8276fc..63cf4f347 100644 --- a/src/state.rs +++ b/src/state.rs @@ -73,6 +73,12 @@ impl State { &mut self.db } + /// Create a new contract at address `contract`. If there is already an account at the address + /// it will have its code reset, ready for `init_code()`. + pub fn new_contract(&mut self, contract: &Address) { + self.require_or_from(contract, false, || Account::new_contract(U256::from(0u8)), |r| r.reset_code()); + } + /// Get the balance of account `a`. pub fn balance(&self, a: &Address) -> U256 { self.get(a, false).as_ref().map(|account| account.balance().clone()).unwrap_or(U256::from(0u8)) @@ -122,7 +128,7 @@ impl State { /// Initialise the code of account `a` so that it is `value` for `key`. /// NOTE: Account should have been created with `new_contract`. pub fn init_code(&mut self, a: &Address, code: Bytes) { - self.require_or_from(a, true, || Account::new_contract(U256::from(0u8))).init_code(code); + self.require_or_from(a, true, || Account::new_contract(U256::from(0u8)), |_|{}).init_code(code); } /// Execute a given transaction. @@ -188,18 +194,20 @@ impl State { } /// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too. - /// `force_create` creates a new, empty basic account if there is not currently an active account. fn require(&self, a: &Address, require_code: bool) -> RefMut { - self.require_or_from(a, require_code, || Account::new_basic(U256::from(0u8), self.account_start_nonce)) + self.require_or_from(a, require_code, || Account::new_basic(U256::from(0u8), self.account_start_nonce), |_|{}) } /// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too. - /// `force_create` creates a new, empty basic account if there is not currently an active account. - fn require_or_from Account>(&self, a: &Address, require_code: bool, default: F) -> RefMut { + /// If it doesn't exist, make account equal the evaluation of `default`. + fn require_or_from Account, G: FnOnce(&mut Account)>(&self, a: &Address, require_code: bool, default: F, not_default: G) -> RefMut { self.cache.borrow_mut().entry(a.clone()).or_insert_with(|| TrieDB::new(&self.db, &self.root).get(&a).map(|rlp| Account::from_rlp(rlp))); - if self.cache.borrow().get(a).unwrap().is_none() { + let preexists = self.cache.borrow().get(a).unwrap().is_none(); + if preexists { self.cache.borrow_mut().insert(a.clone(), Some(default())); + } else { + not_default(self.cache.borrow_mut().get_mut(a).unwrap().as_mut().unwrap()); } let b = self.cache.borrow_mut(); @@ -228,7 +236,7 @@ fn code_from_database() { let a = Address::from_str("0000000000000000000000000000000000000000").unwrap(); let (r, db) = { let mut s = State::new_temp(); - s.require_or_from(&a, false, ||Account::new_contract(U256::from(42u32))); + s.require_or_from(&a, false, ||Account::new_contract(U256::from(42u32)), |_|{}); s.init_code(&a, vec![1, 2, 3]); assert_eq!(s.code(&a), Some([1u8, 2, 3].to_vec())); s.commit();