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

Commit

Permalink
Merge branch 'master' into dp/chore/extricate-state-backend
Browse files Browse the repository at this point in the history
* master:
  EIP-1702: Generalized Account Versioning Scheme (#10771)
  • Loading branch information
dvdplm committed Jul 8, 2019
2 parents a57517c + 141f6a0 commit 75efc47
Show file tree
Hide file tree
Showing 26 changed files with 1,217 additions and 121 deletions.
48 changes: 32 additions & 16 deletions ethcore/account-state/src/account.rs
Original file line number Diff line number Diff line change
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,7 +182,7 @@ 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,
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
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
30 changes: 17 additions & 13 deletions ethcore/factories/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
use trie_db::TrieFactory;
use ethtrie::RlpCodec;
use account_db::Factory as AccountFactory;
use ethereum_types::U256;
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 +32,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
29 changes: 23 additions & 6 deletions ethcore/pod/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pub struct PodAccount {
pub code: Option<Bytes>,
/// The storage of the account.
pub storage: BTreeMap<H256, H256>,
/// The version of the account.
#[serde(default)]
pub version: U256,
}

fn opt_bytes_to_hex<S>(opt_bytes: &Option<Bytes>, serializer: S) -> Result<S::Ok, S::Error>
Expand Down Expand Up @@ -93,6 +96,7 @@ impl From<ethjson::blockchain::Account> for PodAccount {
let value: U256 = value.into();
(BigEndianHash::from_uint(&key), BigEndianHash::from_uint(&value))
}).collect(),
version: a.version.into(),
}
}
}
Expand All @@ -108,6 +112,7 @@ impl From<ethjson::spec::Account> for PodAccount {
let value: U256 = value.into();
(BigEndianHash::from_uint(&key), BigEndianHash::from_uint(&value))
}).collect()),
version: a.version.map_or_else(U256::zero, Into::into),
}
}
}
Expand Down Expand Up @@ -165,7 +170,9 @@ mod test {

#[test]
fn existence() {
let a = PodAccount{balance: 69.into(), nonce: 0.into(), code: Some(vec![]), storage: map![]};
let a = PodAccount {
balance: 69.into(), nonce: 0.into(), code: Some(vec![]), storage: map![], version: 0.into(),
};
assert_eq!(diff_pod(Some(&a), Some(&a)), None);
assert_eq!(diff_pod(None, Some(&a)), Some(AccountDiff{
balance: Diff::Born(69.into()),
Expand All @@ -177,8 +184,12 @@ mod test {

#[test]
fn basic() {
let a = PodAccount{balance: 69.into(), nonce: 0.into(), code: Some(vec![]), storage: map![]};
let b = PodAccount{balance: 42.into(), nonce: 1.into(), code: Some(vec![]), storage: map![]};
let a = PodAccount {
balance: 69.into(), nonce: 0.into(), code: Some(vec![]), storage: map![], version: 0.into(),
};
let b = PodAccount {
balance: 42.into(), nonce: 1.into(), code: Some(vec![]), storage: map![], version: 0.into(),
};
assert_eq!(diff_pod(Some(&a), Some(&b)), Some(AccountDiff {
balance: Diff::Changed(69.into(), 42.into()),
nonce: Diff::Changed(0.into(), 1.into()),
Expand All @@ -189,8 +200,12 @@ mod test {

#[test]
fn code() {
let a = PodAccount{balance: 0.into(), nonce: 0.into(), code: Some(vec![]), storage: map![]};
let b = PodAccount{balance: 0.into(), nonce: 1.into(), code: Some(vec![0]), storage: map![]};
let a = PodAccount {
balance: 0.into(), nonce: 0.into(), code: Some(vec![]), storage: map![], version: 0.into(),
};
let b = PodAccount {
balance: 0.into(), nonce: 1.into(), code: Some(vec![0]), storage: map![], version: 0.into(),
};
assert_eq!(diff_pod(Some(&a), Some(&b)), Some(AccountDiff {
balance: Diff::Same,
nonce: Diff::Changed(0.into(), 1.into()),
Expand All @@ -214,6 +229,7 @@ mod test {
H256::from_low_u64_be(6) => H256::from_low_u64_be(0),
H256::from_low_u64_be(7) => H256::from_low_u64_be(0)
],
version: 0.into(),
};
let b = PodAccount {
balance: 0.into(),
Expand All @@ -227,7 +243,8 @@ mod test {
H256::from_low_u64_be(7) => H256::from_low_u64_be(7),
H256::from_low_u64_be(8) => H256::from_low_u64_be(0),
H256::from_low_u64_be(9) => H256::from_low_u64_be(9)
]
],
version: 0.into(),
};
assert_eq!(diff_pod(Some(&a), Some(&b)), Some(AccountDiff {
balance: Diff::Same,
Expand Down
Loading

0 comments on commit 75efc47

Please sign in to comment.