Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Merge branch 'dp/chore/extricate-state-backend' into dp/chore/extract…
Browse files Browse the repository at this point in the history
…-state-db

* dp/chore/extricate-state-backend:
  Sort out the merge
  EIP-1702: Generalized Account Versioning Scheme (#10771)
  • Loading branch information
dvdplm committed Jul 8, 2019
2 parents 0b1a692 + 994424e commit cd9167e
Show file tree
Hide file tree
Showing 27 changed files with 308 additions and 107 deletions.
54 changes: 35 additions & 19 deletions ethcore/account-state/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use kvdb::DBValue;
use log::{trace, warn};
use lru_cache::LruCache;
use parity_bytes::{Bytes, ToPretty};
use rlp::{DecoderError, encode, RlpStream};
use rlp::{DecoderError, encode};
use trie_db::{Recorder, Trie};

use common_types::basic_account::BasicAccount;
Expand Down Expand Up @@ -72,6 +72,8 @@ pub struct Account {
code_size: Option<usize>,
// Code cache of the account.
code_cache: Arc<Bytes>,
// Version of the account.
code_version: U256,
// Account code new or has been modified.
code_filth: Filth,
// Cached address hash.
Expand All @@ -90,6 +92,7 @@ impl From<BasicAccount> for Account {
code_hash: basic.code_hash,
code_size: None,
code_cache: Arc::new(vec![]),
code_version: basic.code_version,
code_filth: Filth::Clean,
address_hash: Cell::new(None),
}
Expand All @@ -99,7 +102,7 @@ impl From<BasicAccount> for Account {
impl Account {
#[cfg(test)]
/// General constructor.
pub fn new(balance: U256, nonce: U256, storage: HashMap<H256, H256>, code: Bytes) -> Account {
pub fn new(balance: U256, nonce: U256, storage: HashMap<H256, H256>, code: Bytes, version: U256) -> Account {
Account {
balance: balance,
nonce: nonce,
Expand All @@ -110,6 +113,7 @@ impl Account {
code_hash: keccak(&code),
code_size: Some(code.len()),
code_cache: Arc::new(code),
code_version: version,
code_filth: Filth::Dirty,
address_hash: Cell::new(None),
}
Expand All @@ -132,6 +136,7 @@ impl Account {
code_filth: Filth::Dirty,
code_size: Some(pod.code.as_ref().map_or(0, |c| c.len())),
code_cache: Arc::new(pod.code.map_or_else(|| { warn!("POD account with unknown code is being created! Assuming no code."); vec![] }, |c| c)),
code_version: pod.version,
address_hash: Cell::new(None),
}
}
Expand All @@ -147,6 +152,7 @@ impl Account {
m
}),
code: self.code().map(|x| x.to_vec()),
version: self.code_version,
}
}

Expand All @@ -162,6 +168,7 @@ impl Account {
code_hash: KECCAK_EMPTY,
code_cache: Arc::new(vec![]),
code_size: Some(0),
code_version: U256::zero(),
code_filth: Filth::Clean,
address_hash: Cell::new(None),
}
Expand All @@ -175,10 +182,10 @@ impl Account {

/// Create a new contract account.
/// NOTE: make sure you use `init_code` on this before `commit`ing.
pub fn new_contract(balance: U256, nonce: U256, original_storage_root: H256) -> Account {
pub fn new_contract(balance: U256, nonce: U256, version: U256, original_storage_root: H256) -> Account {
Account {
balance: balance,
nonce: nonce,
balance,
nonce,
storage_root: KECCAK_NULL_RLP,
storage_cache: Self::empty_storage_cache(),
original_storage_cache: if original_storage_root == KECCAK_NULL_RLP {
Expand All @@ -190,6 +197,7 @@ impl Account {
code_hash: KECCAK_EMPTY,
code_cache: Arc::new(vec![]),
code_size: None,
code_version: version,
code_filth: Filth::Clean,
address_hash: Cell::new(None),
}
Expand Down Expand Up @@ -320,6 +328,9 @@ impl Account {
/// return the nonce associated with this account.
pub fn nonce(&self) -> &U256 { &self.nonce }

/// return the code version associated with this account.
pub fn code_version(&self) -> &U256 { &self.code_version }

/// return the code hash associated with this account.
pub fn code_hash(&self) -> H256 {
self.code_hash.clone()
Expand Down Expand Up @@ -530,12 +541,15 @@ impl Account {

/// Export to RLP.
pub fn rlp(&self) -> Bytes {
let mut stream = RlpStream::new_list(4);
stream.append(&self.nonce);
stream.append(&self.balance);
stream.append(&self.storage_root);
stream.append(&self.code_hash);
stream.out()
let basic = BasicAccount {
nonce: self.nonce,
balance: self.balance,
storage_root: self.storage_root,
code_hash: self.code_hash,
code_version: self.code_version,
};

rlp::encode(&basic)
}

/// Clone basic account data
Expand All @@ -550,6 +564,7 @@ impl Account {
code_hash: self.code_hash.clone(),
code_size: self.code_size.clone(),
code_cache: self.code_cache.clone(),
code_version: self.code_version,
code_filth: self.code_filth,
address_hash: self.address_hash.clone(),
}
Expand Down Expand Up @@ -580,6 +595,7 @@ impl Account {
self.code_filth = other.code_filth;
self.code_cache = other.code_cache;
self.code_size = other.code_size;
self.code_version = other.code_version;
self.address_hash = other.address_hash;
if self.storage_root == other.storage_root {
let mut cache = self.storage_cache.borrow_mut();
Expand Down Expand Up @@ -653,7 +669,7 @@ mod tests {
let mut db = new_memory_db();
let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero()));
let rlp = {
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
let mut a = Account::new_contract(69.into(), 0.into(), 0.into(), KECCAK_NULL_RLP);
a.set_storage(H256::zero(), H256::from_low_u64_be(0x1234));
a.commit_storage(&Default::default(), &mut db).unwrap();
a.init_code(vec![]);
Expand All @@ -673,7 +689,7 @@ mod tests {
let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero()));

let rlp = {
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
let mut a = Account::new_contract(69.into(), 0.into(), 0.into(), KECCAK_NULL_RLP);
a.init_code(vec![0x55, 0x44, 0xffu8]);
a.commit_code(&mut db);
a.rlp()
Expand All @@ -688,7 +704,7 @@ mod tests {

#[test]
fn commit_storage() {
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
let mut a = Account::new_contract(69.into(), 0.into(), 0.into(), KECCAK_NULL_RLP);
let mut db = new_memory_db();
let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero()));
a.set_storage(H256::from_low_u64_be(0), H256::from_low_u64_be(0x1234));
Expand All @@ -699,7 +715,7 @@ mod tests {

#[test]
fn commit_remove_commit_storage() {
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
let mut a = Account::new_contract(69.into(), 0.into(), 0.into(), KECCAK_NULL_RLP);
let mut db = new_memory_db();
let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero()));
a.set_storage(H256::from_low_u64_be(0), H256::from_low_u64_be(0x1234));
Expand All @@ -713,7 +729,7 @@ mod tests {

#[test]
fn commit_code() {
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
let mut a = Account::new_contract(69.into(), 0.into(), 0.into(), KECCAK_NULL_RLP);
let mut db = new_memory_db();
let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero()));
a.init_code(vec![0x55, 0x44, 0xffu8]);
Expand All @@ -725,7 +741,7 @@ mod tests {

#[test]
fn reset_code() {
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
let mut a = Account::new_contract(69.into(), 0.into(), 0.into(), KECCAK_NULL_RLP);
let mut db = new_memory_db();
let mut db = AccountDBMut::from_hash(&mut db, keccak(&Address::zero()));
a.init_code(vec![0x55, 0x44, 0xffu8]);
Expand All @@ -741,7 +757,7 @@ mod tests {

#[test]
fn rlpio() {
let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new());
let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new(), 0.into());
let b = Account::from_rlp(&a.rlp()).unwrap();
assert_eq!(a.balance(), b.balance());
assert_eq!(a.nonce(), b.nonce());
Expand All @@ -751,7 +767,7 @@ mod tests {

#[test]
fn new_account() {
let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new());
let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new(), 0.into());
assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
assert_eq!(*a.balance(), 69u8.into());
assert_eq!(*a.nonce(), 0u8.into());
Expand Down
21 changes: 14 additions & 7 deletions ethcore/account-state/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,13 +392,13 @@ impl<B: Backend> State<B> {

/// 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, balance: U256, nonce_offset: U256) -> TrieResult<()> {
pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256, version: U256) -> TrieResult<()> {
let original_storage_root = self.original_storage_root(contract)?;
let (nonce, overflow) = self.account_start_nonce.overflowing_add(nonce_offset);
if overflow {
return Err(Box::new(TrieError::DecoderError(H256::from(*contract), rlp::DecoderError::Custom("Nonce overflow".into()))));
}
self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, nonce, original_storage_root))));
self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, nonce, version, original_storage_root))));
Ok(())
}

Expand Down Expand Up @@ -627,6 +627,12 @@ impl<B: Backend> State<B> {
|a| a.as_ref().map(|a| a.code_hash()))
}

/// Get an account's code version.
pub fn code_version(&self, a: &Address) -> TrieResult<U256> {
self.ensure_cached(a, RequireCache::None, true,
|a| a.as_ref().map(|a| *a.code_version()).unwrap_or(U256::zero()))
}

/// Get accounts' code size.
pub fn code_size(&self, a: &Address) -> TrieResult<Option<usize>> {
self.ensure_cached(a, RequireCache::CodeSize, true,
Expand Down Expand Up @@ -685,13 +691,13 @@ impl<B: Backend> State<B> {
/// Initialise the code of account `a` so that it is `code`.
/// NOTE: Account should have been created with `new_contract`.
pub fn init_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> {
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce, KECCAK_NULL_RLP), |_| {})?.init_code(code);
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce, 0.into(),KECCAK_NULL_RLP), |_| {})?.init_code(code);
Ok(())
}

/// Reset the code of account `a` so that it is `code`.
pub fn reset_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> {
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce, KECCAK_NULL_RLP), |_| {})?.reset_code(code);
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce, 0.into(), KECCAK_NULL_RLP), |_| {})?.reset_code(code);
Ok(())
}

Expand Down Expand Up @@ -890,11 +896,11 @@ impl<B: Backend> State<B> {
};

// Storage must be fetched after ensure_cached to avoid borrow problem.
(*acc.balance(), *acc.nonce(), all_keys, acc.code().map(|x| x.to_vec()))
(*acc.balance(), *acc.nonce(), all_keys, acc.code().map(|x| x.to_vec()), *acc.code_version())
})
})?;

if let Some((balance, nonce, storage_keys, code)) = account {
if let Some((balance, nonce, storage_keys, code, version)) = account {
let storage = storage_keys.into_iter().fold(Ok(BTreeMap::new()), |s: TrieResult<_>, key| {
let mut s = s?;

Expand All @@ -903,7 +909,7 @@ impl<B: Backend> State<B> {
})?;

m.insert(address, PodAccount {
balance, nonce, storage, code
balance, nonce, storage, code, version
});
}

Expand Down Expand Up @@ -1091,6 +1097,7 @@ impl<B: Backend> State<B> {
nonce: self.account_start_nonce,
code_hash: KECCAK_EMPTY,
storage_root: KECCAK_NULL_RLP,
code_version: 0.into(),
});

Ok((recorder.drain().into_iter().map(|r| r.data).collect(), account))
Expand Down
5 changes: 4 additions & 1 deletion ethcore/evm/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ struct InterpreterParams {
pub code_address: Address,
/// Hash of currently executed code.
pub code_hash: Option<H256>,
/// Code version.
pub code_version: U256,
/// Receive address. Usually equal to code_address,
/// except when called using CALLCODE.
pub address: Address,
Expand All @@ -144,6 +146,7 @@ impl From<ActionParams> for InterpreterParams {
InterpreterParams {
code_address: params.code_address,
code_hash: params.code_hash,
code_version: params.code_version,
address: params.address,
sender: params.sender,
origin: params.origin,
Expand Down Expand Up @@ -531,7 +534,7 @@ impl<Cost: CostType> Interpreter<Cost> {

let contract_code = self.mem.read_slice(init_off, init_size);

let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme, true);
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, &self.params.code_version, address_scheme, true);
return match create_result {
Ok(ContractCreateResult::Created(address, gas_left)) => {
self.stack.push(address_to_u256(address));
Expand Down
29 changes: 16 additions & 13 deletions ethcore/factories/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use trie_db::TrieFactory;
use ethtrie::RlpCodec;
use account_db::Factory as AccountFactory;
use evm::{Factory as EvmFactory, VMType};
use vm::{Exec, ActionParams, Schedule};
use vm::{Exec, ActionParams, VersionedSchedule, Schedule};
use wasm::WasmInterpreter;
use keccak_hasher::KeccakHasher;

Expand All @@ -31,19 +31,22 @@ pub struct VmFactory {
}

impl VmFactory {
pub fn create(
&self,
params: ActionParams,
schedule: &Schedule,
depth: usize
) -> Box<dyn Exec> {
if schedule.wasm.is_some()
&& params.code.as_ref().map_or(false, |code| {
code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER
}) {
Box::new(WasmInterpreter::new(params))
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Option<Box<dyn Exec>> {
if params.code_version.is_zero() {
Some(if schedule.wasm.is_some() && schedule.versions.is_empty() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
Box::new(WasmInterpreter::new(params))
} else {
self.evm.create(params, schedule, depth)
})
} else {
self.evm.create(params, schedule, depth)
let version_config = schedule.versions.get(&params.code_version);

match version_config {
Some(VersionedSchedule::PWasm) => {
Some(Box::new(WasmInterpreter::new(params)))
},
None => None,
}
}
}

Expand Down
10 changes: 2 additions & 8 deletions ethcore/light/src/on_demand/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use hash_db::HashDB;
use kvdb::DBValue;
use parking_lot::Mutex;
use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field};
use rlp::{RlpStream, Rlp};
use rlp::RlpStream;
use trie::Trie;
use vm::EnvInfo;

Expand Down Expand Up @@ -985,13 +985,7 @@ impl Account {

match TrieDB::new(&db, &state_root).and_then(|t| t.get(keccak(&self.address).as_bytes()))? {
Some(val) => {
let rlp = Rlp::new(&val);
Ok(Some(BasicAccount {
nonce: rlp.val_at(0)?,
balance: rlp.val_at(1)?,
storage_root: rlp.val_at(2)?,
code_hash: rlp.val_at(3)?,
}))
Ok(Some(rlp::decode::<BasicAccount>(&val)?))
},
None => {
trace!(target: "on_demand", "Account {:?} not found", self.address);
Expand Down
Loading

0 comments on commit cd9167e

Please sign in to comment.