State::new_contract.
This commit is contained in:
parent
23d22db95c
commit
2b022e11e1
@ -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.
|
/// 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) {
|
pub fn init_code(&mut self, code: Bytes) {
|
||||||
assert!(self.code_hash.is_none());
|
assert!(self.code_hash.is_none());
|
||||||
self.code_cache = code;
|
self.code_cache = code;
|
||||||
|
@ -36,5 +36,5 @@ fn playpen() {
|
|||||||
let genesis_header = engine.spec().genesis_header();
|
let genesis_header = engine.spec().genesis_header();
|
||||||
let mut db = OverlayDB::new_temp();
|
let mut db = OverlayDB::new_temp();
|
||||||
engine.spec().ensure_db_good(&mut db);
|
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()]);
|
||||||
}
|
}
|
57
src/spec.rs
57
src/spec.rs
@ -206,15 +206,16 @@ impl Spec {
|
|||||||
Spec {
|
Spec {
|
||||||
engine_name: "Ethash".to_string(),
|
engine_name: "Ethash".to_string(),
|
||||||
engine_params: vec![
|
engine_params: vec![
|
||||||
("block_reward", encode(&(finney() * U256::from(1500u64)))),
|
("blockReward", encode(&(finney() * U256::from(1500u64)))),
|
||||||
("maximum_extra_data_size", encode(&U256::from(1024u64))),
|
("frontierCompatibilityModeLimit", encode(&0xffffffffu64)),
|
||||||
("account_start_nonce", encode(&U256::from(0u64))),
|
("maximumExtraDataSize", encode(&U256::from(1024u64))),
|
||||||
("gas_limit_bounds_divisor", encode(&1024u64)),
|
("accountStartNonce", encode(&U256::from(0u64))),
|
||||||
("minimum_difficulty", encode(&131_072u64)),
|
("gasLimitBoundsDivisor", encode(&1024u64)),
|
||||||
("difficulty_bound_divisor", encode(&2048u64)),
|
("minimumDifficulty", encode(&131_072u64)),
|
||||||
("duration_limit", encode(&8u64)),
|
("difficultyBoundDivisor", encode(&2048u64)),
|
||||||
("min_gas_limit", encode(&125_000u64)),
|
("durationLimit", encode(&8u64)),
|
||||||
("gas_floor_target", encode(&3_141_592u64)),
|
("minGasLimit", encode(&125_000u64)),
|
||||||
|
("gasFloorTarget", encode(&3_141_592u64)),
|
||||||
].into_iter().fold(HashMap::new(), | mut acc, vec | {
|
].into_iter().fold(HashMap::new(), | mut acc, vec | {
|
||||||
acc.insert(vec.0.to_string(), vec.1);
|
acc.insert(vec.0.to_string(), vec.1);
|
||||||
acc
|
acc
|
||||||
@ -244,15 +245,16 @@ impl Spec {
|
|||||||
Spec {
|
Spec {
|
||||||
engine_name: "Ethash".to_string(),
|
engine_name: "Ethash".to_string(),
|
||||||
engine_params: vec![
|
engine_params: vec![
|
||||||
("block_reward", encode(&(ether() * U256::from(5u64)))),
|
("blockReward", encode(&(ether() * U256::from(5u64)))),
|
||||||
("maximum_extra_data_size", encode(&U256::from(32u64))),
|
("frontierCompatibilityModeLimit", encode(&0xfffa2990u64)),
|
||||||
("account_start_nonce", encode(&U256::from(0u64))),
|
("maximumExtraDataSize", encode(&U256::from(32u64))),
|
||||||
("gas_limit_bounds_divisor", encode(&1024u64)),
|
("accountStartNonce", encode(&U256::from(0u64))),
|
||||||
("minimum_difficulty", encode(&131_072u64)),
|
("gasLimitBoundsDivisor", encode(&1024u64)),
|
||||||
("difficulty_bound_divisor", encode(&2048u64)),
|
("minimumDifficulty", encode(&131_072u64)),
|
||||||
("duration_limit", encode(&13u64)),
|
("difficultyBoundDivisor", encode(&2048u64)),
|
||||||
("min_gas_limit", encode(&5000u64)),
|
("durationLimit", encode(&13u64)),
|
||||||
("gas_floor_target", encode(&3_141_592u64)),
|
("minGasLimit", encode(&5000u64)),
|
||||||
|
("gasFloorTarget", encode(&3_141_592u64)),
|
||||||
].into_iter().fold(HashMap::new(), | mut acc, vec | {
|
].into_iter().fold(HashMap::new(), | mut acc, vec | {
|
||||||
acc.insert(vec.0.to_string(), vec.1);
|
acc.insert(vec.0.to_string(), vec.1);
|
||||||
acc
|
acc
|
||||||
@ -282,15 +284,16 @@ impl Spec {
|
|||||||
Spec {
|
Spec {
|
||||||
engine_name: "Ethash".to_string(),
|
engine_name: "Ethash".to_string(),
|
||||||
engine_params: vec![
|
engine_params: vec![
|
||||||
("block_reward", encode(&(ether() * U256::from(5u64)))),
|
("blockReward", encode(&(ether() * U256::from(5u64)))),
|
||||||
("maximum_extra_data_size", encode(&U256::from(32u64))),
|
("frontierCompatibilityModeLimit", encode(&0xfffa2990u64)),
|
||||||
("account_start_nonce", encode(&(U256::from(1u64) << 20))),
|
("maximumExtraDataSize", encode(&U256::from(32u64))),
|
||||||
("gas_limit_bounds_divisor", encode(&1024u64)),
|
("accountStartNonce", encode(&(U256::from(1u64) << 20))),
|
||||||
("minimum_difficulty", encode(&131_072u64)),
|
("gasLimitBoundsDivisor", encode(&1024u64)),
|
||||||
("difficulty_bound_divisor", encode(&2048u64)),
|
("minimumDifficulty", encode(&131_072u64)),
|
||||||
("duration_limit", encode(&13u64)),
|
("difficultyBoundDivisor", encode(&2048u64)),
|
||||||
("min_gas_limit", encode(&5000u64)),
|
("durationLimit", encode(&13u64)),
|
||||||
("gas_floor_target", encode(&3_141_592u64)),
|
("minGasLimit", encode(&5000u64)),
|
||||||
|
("gasFloorTarget", encode(&3_141_592u64)),
|
||||||
].into_iter().fold(HashMap::new(), | mut acc, vec | {
|
].into_iter().fold(HashMap::new(), | mut acc, vec | {
|
||||||
acc.insert(vec.0.to_string(), vec.1);
|
acc.insert(vec.0.to_string(), vec.1);
|
||||||
acc
|
acc
|
||||||
|
22
src/state.rs
22
src/state.rs
@ -73,6 +73,12 @@ impl State {
|
|||||||
&mut self.db
|
&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`.
|
/// Get the balance of account `a`.
|
||||||
pub fn balance(&self, a: &Address) -> U256 {
|
pub fn balance(&self, a: &Address) -> U256 {
|
||||||
self.get(a, false).as_ref().map(|account| account.balance().clone()).unwrap_or(U256::from(0u8))
|
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`.
|
/// Initialise the code of account `a` so that it is `value` for `key`.
|
||||||
/// NOTE: Account should have been created with `new_contract`.
|
/// NOTE: Account should have been created with `new_contract`.
|
||||||
pub fn init_code(&mut self, a: &Address, code: Bytes) {
|
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.
|
/// 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.
|
/// 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<Account> {
|
fn require(&self, a: &Address, require_code: bool) -> RefMut<Account> {
|
||||||
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.
|
/// 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.
|
/// If it doesn't exist, make account equal the evaluation of `default`.
|
||||||
fn require_or_from<F: FnOnce() -> Account>(&self, a: &Address, require_code: bool, default: F) -> RefMut<Account> {
|
fn require_or_from<F: FnOnce() -> Account, G: FnOnce(&mut Account)>(&self, a: &Address, require_code: bool, default: F, not_default: G) -> RefMut<Account> {
|
||||||
self.cache.borrow_mut().entry(a.clone()).or_insert_with(||
|
self.cache.borrow_mut().entry(a.clone()).or_insert_with(||
|
||||||
TrieDB::new(&self.db, &self.root).get(&a).map(|rlp| Account::from_rlp(rlp)));
|
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()));
|
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();
|
let b = self.cache.borrow_mut();
|
||||||
@ -228,7 +236,7 @@ fn code_from_database() {
|
|||||||
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
||||||
let (r, db) = {
|
let (r, db) = {
|
||||||
let mut s = State::new_temp();
|
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]);
|
s.init_code(&a, vec![1, 2, 3]);
|
||||||
assert_eq!(s.code(&a), Some([1u8, 2, 3].to_vec()));
|
assert_eq!(s.code(&a), Some([1u8, 2, 3].to_vec()));
|
||||||
s.commit();
|
s.commit();
|
||||||
|
Loading…
Reference in New Issue
Block a user