parent
3d313d592a
commit
7f7fe33bde
26
Cargo.lock
generated
26
Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
[root]
|
[root]
|
||||||
name = "parity"
|
name = "parity"
|
||||||
version = "1.3.2"
|
version = "1.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"clippy 0.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clippy 0.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -20,7 +20,7 @@ dependencies = [
|
|||||||
"ethcore-logger 1.3.0",
|
"ethcore-logger 1.3.0",
|
||||||
"ethcore-rpc 1.3.0",
|
"ethcore-rpc 1.3.0",
|
||||||
"ethcore-signer 1.3.0",
|
"ethcore-signer 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"ethsync 1.3.0",
|
"ethsync 1.3.0",
|
||||||
"fdlimit 0.1.0",
|
"fdlimit 0.1.0",
|
||||||
"hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -269,7 +269,7 @@ dependencies = [
|
|||||||
"ethcore-ipc 1.3.0",
|
"ethcore-ipc 1.3.0",
|
||||||
"ethcore-ipc-codegen 1.3.0",
|
"ethcore-ipc-codegen 1.3.0",
|
||||||
"ethcore-ipc-nano 1.3.0",
|
"ethcore-ipc-nano 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"ethjson 0.1.0",
|
"ethjson 0.1.0",
|
||||||
"ethstore 0.1.0",
|
"ethstore 0.1.0",
|
||||||
"evmjit 1.3.0",
|
"evmjit 1.3.0",
|
||||||
@ -293,7 +293,7 @@ version = "1.3.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clippy 0.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clippy 0.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-rpc 1.3.0",
|
"ethcore-rpc 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
||||||
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)",
|
"jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)",
|
||||||
@ -335,7 +335,7 @@ name = "ethcore-ipc"
|
|||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore-devtools 1.3.0",
|
"ethcore-devtools 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -380,7 +380,7 @@ dependencies = [
|
|||||||
"ethcore-ipc 1.3.0",
|
"ethcore-ipc 1.3.0",
|
||||||
"ethcore-ipc-codegen 1.3.0",
|
"ethcore-ipc-codegen 1.3.0",
|
||||||
"ethcore-ipc-nano 1.3.0",
|
"ethcore-ipc-nano 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||||
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -392,7 +392,7 @@ name = "ethcore-logger"
|
|||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -407,7 +407,7 @@ dependencies = [
|
|||||||
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-devtools 1.3.0",
|
"ethcore-devtools 1.3.0",
|
||||||
"ethcore-io 1.3.0",
|
"ethcore-io 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -431,7 +431,7 @@ dependencies = [
|
|||||||
"ethcore-devtools 1.3.0",
|
"ethcore-devtools 1.3.0",
|
||||||
"ethcore-io 1.3.0",
|
"ethcore-io 1.3.0",
|
||||||
"ethcore-ipc 1.3.0",
|
"ethcore-ipc 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"ethjson 0.1.0",
|
"ethjson 0.1.0",
|
||||||
"ethsync 1.3.0",
|
"ethsync 1.3.0",
|
||||||
"json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)",
|
"json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)",
|
||||||
@ -454,7 +454,7 @@ dependencies = [
|
|||||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-io 1.3.0",
|
"ethcore-io 1.3.0",
|
||||||
"ethcore-rpc 1.3.0",
|
"ethcore-rpc 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-dapps-signer 1.4.0 (git+https://github.com/ethcore/parity-ui.git)",
|
"parity-dapps-signer 1.4.0 (git+https://github.com/ethcore/parity-ui.git)",
|
||||||
@ -465,7 +465,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ethcore-util"
|
name = "ethcore-util"
|
||||||
version = "1.3.2"
|
version = "1.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -498,7 +498,7 @@ dependencies = [
|
|||||||
name = "ethjson"
|
name = "ethjson"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -546,7 +546,7 @@ dependencies = [
|
|||||||
"ethcore-ipc-codegen 1.3.0",
|
"ethcore-ipc-codegen 1.3.0",
|
||||||
"ethcore-ipc-nano 1.3.0",
|
"ethcore-ipc-nano 1.3.0",
|
||||||
"ethcore-network 1.3.0",
|
"ethcore-network 1.3.0",
|
||||||
"ethcore-util 1.3.2",
|
"ethcore-util 1.3.3",
|
||||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
description = "Ethcore client."
|
description = "Ethcore client."
|
||||||
name = "parity"
|
name = "parity"
|
||||||
version = "1.3.2"
|
version = "1.3.3"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
authors = ["Ethcore <admin@ethcore.io>"]
|
authors = ["Ethcore <admin@ethcore.io>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
@ -40,14 +40,16 @@ pub struct Account {
|
|||||||
// Modified storage. Accumulates changes to storage made in `set_storage`
|
// Modified storage. Accumulates changes to storage made in `set_storage`
|
||||||
// Takes precedence over `storage_cache`.
|
// Takes precedence over `storage_cache`.
|
||||||
storage_changes: HashMap<H256, H256>,
|
storage_changes: HashMap<H256, H256>,
|
||||||
// Code hash of the account. If None, means that it's a contract whose code has not yet been set.
|
// Code hash of the account.
|
||||||
code_hash: Option<H256>,
|
code_hash: H256,
|
||||||
// Size of the accoun code.
|
// Size of the accoun code.
|
||||||
code_size: Option<u64>,
|
code_size: Option<u64>,
|
||||||
// Code cache of the account.
|
// Code cache of the account.
|
||||||
code_cache: Bytes,
|
code_cache: Arc<Bytes>,
|
||||||
// Account is new or has been modified
|
// Account is new or has been modified.
|
||||||
filth: Filth,
|
filth: Filth,
|
||||||
|
// Account code new or has been modified.
|
||||||
|
code_filth: Filth,
|
||||||
// Cached address hash.
|
// Cached address hash.
|
||||||
address_hash: Cell<Option<H256>>,
|
address_hash: Cell<Option<H256>>,
|
||||||
}
|
}
|
||||||
@ -62,10 +64,11 @@ impl Account {
|
|||||||
storage_root: SHA3_NULL_RLP,
|
storage_root: SHA3_NULL_RLP,
|
||||||
storage_cache: Self::empty_storage_cache(),
|
storage_cache: Self::empty_storage_cache(),
|
||||||
storage_changes: storage,
|
storage_changes: storage,
|
||||||
code_hash: Some(code.sha3()),
|
code_hash: code.sha3(),
|
||||||
code_size: Some(code.len() as u64),
|
code_size: Some(code.len() as u64),
|
||||||
code_cache: code,
|
code_cache: Arc::new(code),
|
||||||
filth: Filth::Dirty,
|
filth: Filth::Dirty,
|
||||||
|
code_filth: Filth::Dirty,
|
||||||
address_hash: Cell::new(None),
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,9 +85,10 @@ impl Account {
|
|||||||
storage_root: SHA3_NULL_RLP,
|
storage_root: SHA3_NULL_RLP,
|
||||||
storage_cache: Self::empty_storage_cache(),
|
storage_cache: Self::empty_storage_cache(),
|
||||||
storage_changes: pod.storage.into_iter().collect(),
|
storage_changes: pod.storage.into_iter().collect(),
|
||||||
code_hash: pod.code.as_ref().map(|c| c.sha3()),
|
code_hash: pod.code.as_ref().map_or(SHA3_EMPTY, |c| c.sha3()),
|
||||||
|
code_filth: Filth::Dirty,
|
||||||
code_size: Some(pod.code.as_ref().map_or(0, |c| c.len() as u64)),
|
code_size: Some(pod.code.as_ref().map_or(0, |c| c.len() as u64)),
|
||||||
code_cache: pod.code.map_or_else(|| { warn!("POD account with unknown code is being created! Assuming no code."); vec![] }, |c| c),
|
code_cache: Arc::new(pod.code.map_or_else(|| { warn!("POD account with unknown code is being created! Assuming no code."); vec![] }, |c| c)),
|
||||||
filth: Filth::Dirty,
|
filth: Filth::Dirty,
|
||||||
address_hash: Cell::new(None),
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
@ -98,10 +102,11 @@ impl Account {
|
|||||||
storage_root: SHA3_NULL_RLP,
|
storage_root: SHA3_NULL_RLP,
|
||||||
storage_cache: Self::empty_storage_cache(),
|
storage_cache: Self::empty_storage_cache(),
|
||||||
storage_changes: HashMap::new(),
|
storage_changes: HashMap::new(),
|
||||||
code_hash: Some(SHA3_EMPTY),
|
code_hash: SHA3_EMPTY,
|
||||||
code_cache: vec![],
|
code_cache: Arc::new(vec![]),
|
||||||
code_size: Some(0),
|
code_size: Some(0),
|
||||||
filth: Filth::Dirty,
|
filth: Filth::Dirty,
|
||||||
|
code_filth: Filth::Clean,
|
||||||
address_hash: Cell::new(None),
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,10 +120,11 @@ impl Account {
|
|||||||
storage_root: r.val_at(2),
|
storage_root: r.val_at(2),
|
||||||
storage_cache: Self::empty_storage_cache(),
|
storage_cache: Self::empty_storage_cache(),
|
||||||
storage_changes: HashMap::new(),
|
storage_changes: HashMap::new(),
|
||||||
code_hash: Some(r.val_at(3)),
|
code_hash: r.val_at(3),
|
||||||
code_cache: vec![],
|
code_cache: Arc::new(vec![]),
|
||||||
code_size: None,
|
code_size: None,
|
||||||
filth: Filth::Clean,
|
filth: Filth::Clean,
|
||||||
|
code_filth: Filth::Clean,
|
||||||
address_hash: Cell::new(None),
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,10 +138,11 @@ impl Account {
|
|||||||
storage_root: SHA3_NULL_RLP,
|
storage_root: SHA3_NULL_RLP,
|
||||||
storage_cache: Self::empty_storage_cache(),
|
storage_cache: Self::empty_storage_cache(),
|
||||||
storage_changes: HashMap::new(),
|
storage_changes: HashMap::new(),
|
||||||
code_hash: None,
|
code_hash: SHA3_EMPTY,
|
||||||
code_cache: vec![],
|
code_cache: Arc::new(vec![]),
|
||||||
code_size: None,
|
code_size: None,
|
||||||
filth: Filth::Dirty,
|
filth: Filth::Dirty,
|
||||||
|
code_filth: Filth::Clean,
|
||||||
address_hash: Cell::new(None),
|
address_hash: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,16 +150,15 @@ impl Account {
|
|||||||
/// 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()`
|
||||||
pub fn init_code(&mut self, code: Bytes) {
|
pub fn init_code(&mut self, code: Bytes) {
|
||||||
assert!(self.code_hash.is_none());
|
self.code_hash = code.sha3();
|
||||||
self.code_cache = code;
|
self.code_cache = Arc::new(code);
|
||||||
self.code_size = Some(self.code_cache.len() as u64);
|
self.code_size = Some(self.code_cache.len() as u64);
|
||||||
self.filth = Filth::Dirty;
|
self.filth = Filth::Dirty;
|
||||||
|
self.code_filth = Filth::Dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset this account's code to the given code.
|
/// Reset this account's code to the given code.
|
||||||
pub fn reset_code(&mut self, code: Bytes) {
|
pub fn reset_code(&mut self, code: Bytes) {
|
||||||
self.code_hash = None;
|
|
||||||
self.code_size = Some(0);
|
|
||||||
self.init_code(code);
|
self.init_code(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,10 +215,9 @@ impl Account {
|
|||||||
/// return the nonce associated with this account.
|
/// return the nonce associated with this account.
|
||||||
pub fn nonce(&self) -> &U256 { &self.nonce }
|
pub fn nonce(&self) -> &U256 { &self.nonce }
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
/// return the code hash associated with this account.
|
/// return the code hash associated with this account.
|
||||||
pub fn code_hash(&self) -> H256 {
|
pub fn code_hash(&self) -> H256 {
|
||||||
self.code_hash.clone().unwrap_or(SHA3_EMPTY)
|
self.code_hash.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return the code hash associated with this account.
|
/// return the code hash associated with this account.
|
||||||
@ -227,13 +232,11 @@ impl Account {
|
|||||||
|
|
||||||
/// returns the account's code. If `None` then the code cache isn't available -
|
/// returns the account's code. If `None` then the code cache isn't available -
|
||||||
/// get someone who knows to call `note_code`.
|
/// get someone who knows to call `note_code`.
|
||||||
pub fn code(&self) -> Option<&[u8]> {
|
pub fn code(&self) -> Option<Arc<Bytes>> {
|
||||||
match self.code_hash {
|
if self.code_hash != SHA3_EMPTY && self.code_cache.is_empty() {
|
||||||
Some(c) if c == SHA3_EMPTY && self.code_cache.is_empty() => Some(&self.code_cache),
|
return None;
|
||||||
Some(_) if !self.code_cache.is_empty() => Some(&self.code_cache),
|
|
||||||
None => Some(&self.code_cache),
|
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
|
Some(self.code_cache.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the account's code size. If `None` then the code cache or code size cache isn't available -
|
/// returns the account's code size. If `None` then the code cache or code size cache isn't available -
|
||||||
@ -246,24 +249,23 @@ impl Account {
|
|||||||
/// Provide a byte array which hashes to the `code_hash`. returns the hash as a result.
|
/// Provide a byte array which hashes to the `code_hash`. returns the hash as a result.
|
||||||
pub fn note_code(&mut self, code: Bytes) -> Result<(), H256> {
|
pub fn note_code(&mut self, code: Bytes) -> Result<(), H256> {
|
||||||
let h = code.sha3();
|
let h = code.sha3();
|
||||||
match self.code_hash {
|
if self.code_hash == h {
|
||||||
Some(ref i) if h == *i => {
|
self.code_cache = Arc::new(code);
|
||||||
self.code_cache = code;
|
|
||||||
self.code_size = Some(self.code_cache.len() as u64);
|
self.code_size = Some(self.code_cache.len() as u64);
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
} else {
|
||||||
_ => Err(h)
|
Err(h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is `code_cache` valid; such that code is going to return Some?
|
/// Is `code_cache` valid; such that code is going to return Some?
|
||||||
pub fn is_cached(&self) -> bool {
|
pub fn is_cached(&self) -> bool {
|
||||||
!self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == Some(SHA3_EMPTY))
|
!self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == SHA3_EMPTY)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this a new or modified account?
|
/// Is this a new or modified account?
|
||||||
pub fn is_dirty(&self) -> bool {
|
pub fn is_dirty(&self) -> bool {
|
||||||
self.filth == Filth::Dirty || !self.storage_is_clean()
|
self.filth == Filth::Dirty || self.code_filth == Filth::Dirty || !self.storage_is_clean()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark account as clean.
|
/// Mark account as clean.
|
||||||
@ -277,19 +279,16 @@ impl Account {
|
|||||||
// TODO: fill out self.code_cache;
|
// TODO: fill out self.code_cache;
|
||||||
trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
||||||
self.is_cached() ||
|
self.is_cached() ||
|
||||||
match self.code_hash {
|
match db.get(&self.code_hash) {
|
||||||
Some(ref h) => match db.get(h) {
|
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
self.code_cache = x.to_vec();
|
self.code_cache = Arc::new(x.to_vec());
|
||||||
self.code_size = Some(x.len() as u64);
|
self.code_size = Some(x.len() as u64);
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
warn!("Failed reverse get of {}", h);
|
warn!("Failed reverse get of {}", self.code_hash);
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
},
|
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,18 +297,19 @@ impl Account {
|
|||||||
// TODO: fill out self.code_cache;
|
// TODO: fill out self.code_cache;
|
||||||
trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
||||||
self.code_size.is_some() ||
|
self.code_size.is_some() ||
|
||||||
match self.code_hash {
|
if self.code_hash != SHA3_EMPTY {
|
||||||
Some(ref h) if h != &SHA3_EMPTY => match db.get(h) {
|
match db.get(&self.code_hash) {
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
self.code_size = Some(x.len() as u64);
|
self.code_size = Some(x.len() as u64);
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
warn!("Failed reverse get of {}", h);
|
warn!("Failed reverse get of {}", self.code_hash);
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
_ => false,
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,15 +370,16 @@ impl Account {
|
|||||||
|
|
||||||
/// Commit any unsaved code. `code_hash` will always return the hash of the `code_cache` after this.
|
/// Commit any unsaved code. `code_hash` will always return the hash of the `code_cache` after this.
|
||||||
pub fn commit_code(&mut self, db: &mut AccountDBMut) {
|
pub fn commit_code(&mut self, db: &mut AccountDBMut) {
|
||||||
trace!("Commiting code of {:?} - {:?}, {:?}", self, self.code_hash.is_none(), self.code_cache.is_empty());
|
trace!("Commiting code of {:?} - {:?}, {:?}", self, self.code_filth == Filth::Dirty, self.code_cache.is_empty());
|
||||||
match (self.code_hash.is_none(), self.code_cache.is_empty()) {
|
match (self.code_filth == Filth::Dirty, self.code_cache.is_empty()) {
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
self.code_hash = Some(SHA3_EMPTY);
|
|
||||||
self.code_size = Some(0);
|
self.code_size = Some(0);
|
||||||
|
self.code_filth = Filth::Clean;
|
||||||
},
|
},
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
self.code_hash = Some(db.insert(&self.code_cache));
|
db.emplace(self.code_hash.clone(), (*self.code_cache).clone());
|
||||||
self.code_size = Some(self.code_cache.len() as u64);
|
self.code_size = Some(self.code_cache.len() as u64);
|
||||||
|
self.code_filth = Filth::Clean;
|
||||||
},
|
},
|
||||||
(false, _) => {},
|
(false, _) => {},
|
||||||
}
|
}
|
||||||
@ -390,7 +391,7 @@ impl Account {
|
|||||||
stream.append(&self.nonce);
|
stream.append(&self.nonce);
|
||||||
stream.append(&self.balance);
|
stream.append(&self.balance);
|
||||||
stream.append(&self.storage_root);
|
stream.append(&self.storage_root);
|
||||||
stream.append(self.code_hash.as_ref().unwrap_or(&SHA3_EMPTY));
|
stream.append(&self.code_hash);
|
||||||
stream.out()
|
stream.out()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,8 +405,9 @@ impl Account {
|
|||||||
storage_changes: HashMap::new(),
|
storage_changes: HashMap::new(),
|
||||||
code_hash: self.code_hash.clone(),
|
code_hash: self.code_hash.clone(),
|
||||||
code_size: self.code_size.clone(),
|
code_size: self.code_size.clone(),
|
||||||
code_cache: Bytes::new(),
|
code_cache: self.code_cache.clone(),
|
||||||
filth: self.filth,
|
filth: self.filth,
|
||||||
|
code_filth: self.code_filth,
|
||||||
address_hash: self.address_hash.clone(),
|
address_hash: self.address_hash.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,6 +435,7 @@ impl Account {
|
|||||||
self.nonce = other.nonce;
|
self.nonce = other.nonce;
|
||||||
self.storage_root = other.storage_root;
|
self.storage_root = other.storage_root;
|
||||||
self.code_hash = other.code_hash;
|
self.code_hash = other.code_hash;
|
||||||
|
self.code_filth = other.code_filth;
|
||||||
self.code_cache = other.code_cache;
|
self.code_cache = other.code_cache;
|
||||||
self.code_size = other.code_size;
|
self.code_size = other.code_size;
|
||||||
self.address_hash = other.address_hash;
|
self.address_hash = other.address_hash;
|
||||||
@ -535,7 +538,7 @@ mod tests {
|
|||||||
let mut db = MemoryDB::new();
|
let mut db = MemoryDB::new();
|
||||||
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
||||||
a.init_code(vec![0x55, 0x44, 0xffu8]);
|
a.init_code(vec![0x55, 0x44, 0xffu8]);
|
||||||
assert_eq!(a.code_hash(), SHA3_EMPTY);
|
assert_eq!(a.code_filth, Filth::Dirty);
|
||||||
assert_eq!(a.code_size(), Some(3));
|
assert_eq!(a.code_size(), Some(3));
|
||||||
a.commit_code(&mut db);
|
a.commit_code(&mut db);
|
||||||
assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb");
|
assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb");
|
||||||
@ -547,11 +550,12 @@ mod tests {
|
|||||||
let mut db = MemoryDB::new();
|
let mut db = MemoryDB::new();
|
||||||
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
||||||
a.init_code(vec![0x55, 0x44, 0xffu8]);
|
a.init_code(vec![0x55, 0x44, 0xffu8]);
|
||||||
assert_eq!(a.code_hash(), SHA3_EMPTY);
|
assert_eq!(a.code_filth, Filth::Dirty);
|
||||||
a.commit_code(&mut db);
|
a.commit_code(&mut db);
|
||||||
|
assert_eq!(a.code_filth, Filth::Clean);
|
||||||
assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb");
|
assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb");
|
||||||
a.reset_code(vec![0x55]);
|
a.reset_code(vec![0x55]);
|
||||||
assert_eq!(a.code_hash(), SHA3_EMPTY);
|
assert_eq!(a.code_filth, Filth::Dirty);
|
||||||
a.commit_code(&mut db);
|
a.commit_code(&mut db);
|
||||||
assert_eq!(a.code_hash().hex(), "37bf2238b11b68cdc8382cece82651b59d3c3988873b6e0f33d79694aa45f1be");
|
assert_eq!(a.code_hash().hex(), "37bf2238b11b68cdc8382cece82651b59d3c3988873b6e0f33d79694aa45f1be");
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@ impl ActionValue {
|
|||||||
pub struct ActionParams {
|
pub struct ActionParams {
|
||||||
/// Address of currently executed code.
|
/// Address of currently executed code.
|
||||||
pub code_address: Address,
|
pub code_address: Address,
|
||||||
|
/// Hash of currently executed code.
|
||||||
|
pub code_hash: H256,
|
||||||
/// Receive address. Usually equal to code_address,
|
/// Receive address. Usually equal to code_address,
|
||||||
/// except when called using CALLCODE.
|
/// except when called using CALLCODE.
|
||||||
pub address: Address,
|
pub address: Address,
|
||||||
@ -57,7 +59,7 @@ pub struct ActionParams {
|
|||||||
/// Transaction value.
|
/// Transaction value.
|
||||||
pub value: ActionValue,
|
pub value: ActionValue,
|
||||||
/// Code being executed.
|
/// Code being executed.
|
||||||
pub code: Option<Bytes>,
|
pub code: Option<Arc<Bytes>>,
|
||||||
/// Input data.
|
/// Input data.
|
||||||
pub data: Option<Bytes>,
|
pub data: Option<Bytes>,
|
||||||
/// Type of call
|
/// Type of call
|
||||||
@ -70,6 +72,7 @@ impl Default for ActionParams {
|
|||||||
fn default() -> ActionParams {
|
fn default() -> ActionParams {
|
||||||
ActionParams {
|
ActionParams {
|
||||||
code_address: Address::new(),
|
code_address: Address::new(),
|
||||||
|
code_hash: SHA3_EMPTY,
|
||||||
address: Address::new(),
|
address: Address::new(),
|
||||||
sender: Address::new(),
|
sender: Address::new(),
|
||||||
origin: Address::new(),
|
origin: Address::new(),
|
||||||
@ -88,10 +91,11 @@ impl From<ethjson::vm::Transaction> for ActionParams {
|
|||||||
let address: Address = t.address.into();
|
let address: Address = t.address.into();
|
||||||
ActionParams {
|
ActionParams {
|
||||||
code_address: Address::new(),
|
code_address: Address::new(),
|
||||||
|
code_hash: (&*t.code).sha3(),
|
||||||
address: address,
|
address: address,
|
||||||
sender: t.sender.into(),
|
sender: t.sender.into(),
|
||||||
origin: t.origin.into(),
|
origin: t.origin.into(),
|
||||||
code: Some(t.code.into()),
|
code: Some(Arc::new(t.code.into())),
|
||||||
data: Some(t.data.into()),
|
data: Some(t.data.into()),
|
||||||
gas: t.gas.into(),
|
gas: t.gas.into(),
|
||||||
gas_price: t.gas_price.into(),
|
gas_price: t.gas_price.into(),
|
||||||
|
@ -808,7 +808,7 @@ impl BlockChainClient for Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn code(&self, address: &Address, id: BlockID) -> Option<Option<Bytes>> {
|
fn code(&self, address: &Address, id: BlockID) -> Option<Option<Bytes>> {
|
||||||
self.state_at(id).map(|s| s.code(address))
|
self.state_at(id).map(|s| s.code(address).map(|c| (*c).clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn balance(&self, address: &Address, id: BlockID) -> Option<U256> {
|
fn balance(&self, address: &Address, id: BlockID) -> Option<U256> {
|
||||||
|
@ -81,7 +81,7 @@ pub trait Ext {
|
|||||||
) -> MessageCallResult;
|
) -> MessageCallResult;
|
||||||
|
|
||||||
/// Returns code at given address
|
/// Returns code at given address
|
||||||
fn extcode(&self, address: &Address) -> Bytes;
|
fn extcode(&self, address: &Address) -> Arc<Bytes>;
|
||||||
|
|
||||||
/// Returns code length in bytes at given address
|
/// Returns code length in bytes at given address
|
||||||
fn extcode_len(&self, address: &Address) -> u64;
|
fn extcode_len(&self, address: &Address) -> u64;
|
||||||
|
@ -18,8 +18,10 @@
|
|||||||
//!
|
//!
|
||||||
//! TODO: consider spliting it into two separate files.
|
//! TODO: consider spliting it into two separate files.
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::sync::Arc;
|
||||||
use evm::Evm;
|
use evm::Evm;
|
||||||
use util::{U256, Uint};
|
use util::{U256, Uint};
|
||||||
|
use super::interpreter::SharedCache;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
/// Type of EVM to use.
|
/// Type of EVM to use.
|
||||||
@ -81,7 +83,8 @@ impl VMType {
|
|||||||
|
|
||||||
/// Evm factory. Creates appropriate Evm.
|
/// Evm factory. Creates appropriate Evm.
|
||||||
pub struct Factory {
|
pub struct Factory {
|
||||||
evm: VMType
|
evm: VMType,
|
||||||
|
evm_cache: Arc<SharedCache>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Factory {
|
impl Factory {
|
||||||
@ -94,9 +97,9 @@ impl Factory {
|
|||||||
Box::new(super::jit::JitEvm::default())
|
Box::new(super::jit::JitEvm::default())
|
||||||
},
|
},
|
||||||
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
||||||
Box::new(super::interpreter::Interpreter::<usize>::default())
|
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
|
||||||
} else {
|
} else {
|
||||||
Box::new(super::interpreter::Interpreter::<U256>::default())
|
Box::new(super::interpreter::Interpreter::<U256>::new(self.evm_cache.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,9 +110,9 @@ impl Factory {
|
|||||||
pub fn create(&self, gas: U256) -> Box<Evm> {
|
pub fn create(&self, gas: U256) -> Box<Evm> {
|
||||||
match self.evm {
|
match self.evm {
|
||||||
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
||||||
Box::new(super::interpreter::Interpreter::<usize>::default())
|
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
|
||||||
} else {
|
} else {
|
||||||
Box::new(super::interpreter::Interpreter::<U256>::default())
|
Box::new(super::interpreter::Interpreter::<U256>::new(self.evm_cache.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +120,8 @@ impl Factory {
|
|||||||
/// Create new instance of specific `VMType` factory
|
/// Create new instance of specific `VMType` factory
|
||||||
pub fn new(evm: VMType) -> Self {
|
pub fn new(evm: VMType) -> Self {
|
||||||
Factory {
|
Factory {
|
||||||
evm: evm
|
evm: evm,
|
||||||
|
evm_cache: Arc::new(SharedCache::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +135,8 @@ impl Default for Factory {
|
|||||||
#[cfg(feature = "jit")]
|
#[cfg(feature = "jit")]
|
||||||
fn default() -> Factory {
|
fn default() -> Factory {
|
||||||
Factory {
|
Factory {
|
||||||
evm: VMType::Jit
|
evm: VMType::Jit,
|
||||||
|
evm_cache: Arc::new(SharedCache::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +144,8 @@ impl Default for Factory {
|
|||||||
#[cfg(not(feature = "jit"))]
|
#[cfg(not(feature = "jit"))]
|
||||||
fn default() -> Factory {
|
fn default() -> Factory {
|
||||||
Factory {
|
Factory {
|
||||||
evm: VMType::Interpreter
|
evm: VMType::Interpreter,
|
||||||
|
evm_cache: Arc::new(SharedCache::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,12 @@ macro_rules! evm_debug {
|
|||||||
mod gasometer;
|
mod gasometer;
|
||||||
mod stack;
|
mod stack;
|
||||||
mod memory;
|
mod memory;
|
||||||
|
mod shared_cache;
|
||||||
|
|
||||||
use self::gasometer::Gasometer;
|
use self::gasometer::Gasometer;
|
||||||
use self::stack::{Stack, VecStack};
|
use self::stack::{Stack, VecStack};
|
||||||
use self::memory::Memory;
|
use self::memory::Memory;
|
||||||
|
pub use self::shared_cache::SharedCache;
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use common::*;
|
use common::*;
|
||||||
@ -98,9 +100,9 @@ enum InstructionResult<Gas> {
|
|||||||
|
|
||||||
|
|
||||||
/// Intepreter EVM implementation
|
/// Intepreter EVM implementation
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Interpreter<Cost: CostType> {
|
pub struct Interpreter<Cost: CostType> {
|
||||||
mem: Vec<u8>,
|
mem: Vec<u8>,
|
||||||
|
cache: Arc<SharedCache>,
|
||||||
_type: PhantomData<Cost>,
|
_type: PhantomData<Cost>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ impl<Cost: CostType> evm::Evm for Interpreter<Cost> {
|
|||||||
self.mem.clear();
|
self.mem.clear();
|
||||||
|
|
||||||
let code = ¶ms.code.as_ref().unwrap();
|
let code = ¶ms.code.as_ref().unwrap();
|
||||||
let valid_jump_destinations = self.find_jump_destinations(code);
|
let valid_jump_destinations = self.cache.jump_destinations(¶ms.code_hash, code);
|
||||||
|
|
||||||
let mut gasometer = Gasometer::<Cost>::new(try!(Cost::from_u256(params.gas)));
|
let mut gasometer = Gasometer::<Cost>::new(try!(Cost::from_u256(params.gas)));
|
||||||
let mut stack = VecStack::with_capacity(ext.schedule().stack_limit, U256::zero());
|
let mut stack = VecStack::with_capacity(ext.schedule().stack_limit, U256::zero());
|
||||||
@ -188,6 +190,14 @@ impl<Cost: CostType> evm::Evm for Interpreter<Cost> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Cost: CostType> Interpreter<Cost> {
|
impl<Cost: CostType> Interpreter<Cost> {
|
||||||
|
/// Create a new `Interpreter` instance with shared cache.
|
||||||
|
pub fn new(cache: Arc<SharedCache>) -> Interpreter<Cost> {
|
||||||
|
Interpreter {
|
||||||
|
mem: Vec::new(),
|
||||||
|
cache: cache,
|
||||||
|
_type: PhantomData::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn verify_instruction(&self, ext: &evm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> {
|
fn verify_instruction(&self, ext: &evm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> {
|
||||||
let schedule = ext.schedule();
|
let schedule = ext.schedule();
|
||||||
@ -486,10 +496,10 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
stack.push(U256::from(len));
|
stack.push(U256::from(len));
|
||||||
},
|
},
|
||||||
instructions::CALLDATACOPY => {
|
instructions::CALLDATACOPY => {
|
||||||
self.copy_data_to_memory(stack, ¶ms.data.clone().unwrap_or_else(|| vec![]));
|
self.copy_data_to_memory(stack, params.data.as_ref().map_or_else(|| &[] as &[u8], |d| &*d as &[u8]));
|
||||||
},
|
},
|
||||||
instructions::CODECOPY => {
|
instructions::CODECOPY => {
|
||||||
self.copy_data_to_memory(stack, ¶ms.code.clone().unwrap_or_else(|| vec![]));
|
self.copy_data_to_memory(stack, params.code.as_ref().map_or_else(|| &[] as &[u8], |c| &**c as &[u8]));
|
||||||
},
|
},
|
||||||
instructions::EXTCODECOPY => {
|
instructions::EXTCODECOPY => {
|
||||||
let address = u256_to_address(&stack.pop_back());
|
let address = u256_to_address(&stack.pop_back());
|
||||||
@ -790,23 +800,6 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_jump_destinations(&self, code: &[u8]) -> BitSet {
|
|
||||||
let mut jump_dests = BitSet::with_capacity(code.len());
|
|
||||||
let mut position = 0;
|
|
||||||
|
|
||||||
while position < code.len() {
|
|
||||||
let instruction = code[position];
|
|
||||||
|
|
||||||
if instruction == instructions::JUMPDEST {
|
|
||||||
jump_dests.insert(position);
|
|
||||||
} else if instructions::is_push(instruction) {
|
|
||||||
position += instructions::get_push_bytes(instruction);
|
|
||||||
}
|
|
||||||
position += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
jump_dests
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_and_reset_sign(value: U256) -> (U256, bool) {
|
fn get_and_reset_sign(value: U256) -> (U256, bool) {
|
||||||
@ -833,15 +826,3 @@ fn address_to_u256(value: Address) -> U256 {
|
|||||||
U256::from(H256::from(value).as_slice())
|
U256::from(H256::from(value).as_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_find_jump_destinations() {
|
|
||||||
// given
|
|
||||||
let interpreter = Interpreter::<U256>::default();
|
|
||||||
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b01600055".from_hex().unwrap();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let valid_jump_destinations = interpreter.find_jump_destinations(&code);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert!(valid_jump_destinations.contains(66));
|
|
||||||
}
|
|
||||||
|
84
ethcore/src/evm/interpreter/shared_cache.rs
Normal file
84
ethcore/src/evm/interpreter/shared_cache.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use lru_cache::LruCache;
|
||||||
|
use util::{H256, Mutex};
|
||||||
|
use util::sha3::*;
|
||||||
|
use bit_set::BitSet;
|
||||||
|
use super::super::instructions;
|
||||||
|
|
||||||
|
const CACHE_CODE_ITEMS: usize = 4096;
|
||||||
|
|
||||||
|
/// GLobal cache for EVM interpreter
|
||||||
|
pub struct SharedCache {
|
||||||
|
jump_destinations: Mutex<LruCache<H256, Arc<BitSet>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SharedCache {
|
||||||
|
/// Get jump destincations bitmap for a contract.
|
||||||
|
pub fn jump_destinations(&self, code_hash: &H256, code: &[u8]) -> Arc<BitSet> {
|
||||||
|
if code_hash == &SHA3_EMPTY {
|
||||||
|
return Self::find_jump_destinations(code);
|
||||||
|
}
|
||||||
|
if let Some(d) = self.jump_destinations.lock().get_mut(code_hash) {
|
||||||
|
return d.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
let d = Self::find_jump_destinations(code);
|
||||||
|
self.jump_destinations.lock().insert(code_hash.clone(), d.clone());
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_jump_destinations(code: &[u8]) -> Arc<BitSet> {
|
||||||
|
let mut jump_dests = BitSet::with_capacity(code.len());
|
||||||
|
let mut position = 0;
|
||||||
|
|
||||||
|
while position < code.len() {
|
||||||
|
let instruction = code[position];
|
||||||
|
|
||||||
|
if instruction == instructions::JUMPDEST {
|
||||||
|
jump_dests.insert(position);
|
||||||
|
} else if instructions::is_push(instruction) {
|
||||||
|
position += instructions::get_push_bytes(instruction);
|
||||||
|
}
|
||||||
|
position += 1;
|
||||||
|
}
|
||||||
|
Arc::new(jump_dests)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SharedCache {
|
||||||
|
fn default() -> SharedCache {
|
||||||
|
SharedCache {
|
||||||
|
jump_destinations: Mutex::new(LruCache::new(CACHE_CODE_ITEMS)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_find_jump_destinations() {
|
||||||
|
use util::FromHex;
|
||||||
|
// given
|
||||||
|
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b01600055".from_hex().unwrap();
|
||||||
|
|
||||||
|
// when
|
||||||
|
let valid_jump_destinations = SharedCache::find_jump_destinations(&code);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert!(valid_jump_destinations.contains(66));
|
||||||
|
}
|
@ -49,7 +49,7 @@ pub struct FakeExt {
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
store: HashMap<H256, H256>,
|
store: HashMap<H256, H256>,
|
||||||
blockhashes: HashMap<U256, H256>,
|
blockhashes: HashMap<U256, H256>,
|
||||||
codes: HashMap<Address, Bytes>,
|
codes: HashMap<Address, Arc<Bytes>>,
|
||||||
logs: Vec<FakeLogEntry>,
|
logs: Vec<FakeLogEntry>,
|
||||||
_suicides: HashSet<Address>,
|
_suicides: HashSet<Address>,
|
||||||
info: EnvInfo,
|
info: EnvInfo,
|
||||||
@ -136,8 +136,8 @@ impl Ext for FakeExt {
|
|||||||
MessageCallResult::Success(*gas)
|
MessageCallResult::Success(*gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcode(&self, address: &Address) -> Bytes {
|
fn extcode(&self, address: &Address) -> Arc<Bytes> {
|
||||||
self.codes.get(address).unwrap_or(&Bytes::new()).clone()
|
self.codes.get(address).unwrap_or(&Arc::new(Bytes::new())).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcode_len(&self, address: &Address) -> u64 {
|
fn extcode_len(&self, address: &Address) -> u64 {
|
||||||
@ -184,11 +184,11 @@ fn test_stack_underflow() {
|
|||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let err = {
|
let err = {
|
||||||
let mut vm : Box<evm::Evm> = Box::new(super::interpreter::Interpreter::<usize>::default());
|
let mut vm : Box<evm::Evm> = Box::new(super::interpreter::Interpreter::<usize>::new(Arc::new(super::interpreter::SharedCache::default())));
|
||||||
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
|
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ fn test_add(factory: super::Factory) {
|
|||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -231,7 +231,7 @@ fn test_sha3(factory: super::Factory) {
|
|||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -251,7 +251,7 @@ fn test_address(factory: super::Factory) {
|
|||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -273,7 +273,7 @@ fn test_origin(factory: super::Factory) {
|
|||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.origin = origin.clone();
|
params.origin = origin.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -295,7 +295,7 @@ fn test_sender(factory: super::Factory) {
|
|||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -329,9 +329,9 @@ fn test_extcodecopy(factory: super::Factory) {
|
|||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
ext.codes.insert(sender, sender_code);
|
ext.codes.insert(sender, Arc::new(sender_code));
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
let mut vm = factory.create(params.gas);
|
let mut vm = factory.create(params.gas);
|
||||||
@ -350,7 +350,7 @@ fn test_log_empty(factory: super::Factory) {
|
|||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -382,7 +382,7 @@ fn test_log_sender(factory: super::Factory) {
|
|||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -406,7 +406,7 @@ fn test_blockhash(factory: super::Factory) {
|
|||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
ext.blockhashes.insert(U256::zero(), blockhash.clone());
|
ext.blockhashes.insert(U256::zero(), blockhash.clone());
|
||||||
|
|
||||||
@ -428,7 +428,7 @@ fn test_calldataload(factory: super::Factory) {
|
|||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
params.data = Some(data);
|
params.data = Some(data);
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
@ -449,7 +449,7 @@ fn test_author(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
ext.info.author = author;
|
ext.info.author = author;
|
||||||
|
|
||||||
@ -469,7 +469,7 @@ fn test_timestamp(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
ext.info.timestamp = timestamp;
|
ext.info.timestamp = timestamp;
|
||||||
|
|
||||||
@ -489,7 +489,7 @@ fn test_number(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
ext.info.number = number;
|
ext.info.number = number;
|
||||||
|
|
||||||
@ -509,7 +509,7 @@ fn test_difficulty(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
ext.info.difficulty = difficulty;
|
ext.info.difficulty = difficulty;
|
||||||
|
|
||||||
@ -529,7 +529,7 @@ fn test_gas_limit(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
ext.info.gas_limit = gas_limit;
|
ext.info.gas_limit = gas_limit;
|
||||||
|
|
||||||
@ -548,7 +548,7 @@ fn test_mul(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -566,7 +566,7 @@ fn test_sub(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -584,7 +584,7 @@ fn test_div(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -602,7 +602,7 @@ fn test_div_zero(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -620,7 +620,7 @@ fn test_mod(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -639,7 +639,7 @@ fn test_smod(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -658,7 +658,7 @@ fn test_sdiv(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -677,7 +677,7 @@ fn test_exp(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -697,7 +697,7 @@ fn test_comparison(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -718,7 +718,7 @@ fn test_signed_comparison(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -739,7 +739,7 @@ fn test_bitops(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(150_000);
|
params.gas = U256::from(150_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -762,7 +762,7 @@ fn test_addmod_mulmod(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -783,7 +783,7 @@ fn test_byte(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -802,7 +802,7 @@ fn test_signextend(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -822,7 +822,7 @@ fn test_badinstruction_int() {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let err = {
|
let err = {
|
||||||
@ -842,7 +842,7 @@ fn test_pop(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -862,7 +862,7 @@ fn test_extops(factory: super::Factory) {
|
|||||||
params.gas = U256::from(150_000);
|
params.gas = U256::from(150_000);
|
||||||
params.gas_price = U256::from(0x32);
|
params.gas_price = U256::from(0x32);
|
||||||
params.value = ActionValue::Transfer(U256::from(0x99));
|
params.value = ActionValue::Transfer(U256::from(0x99));
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -885,7 +885,7 @@ fn test_jumps(factory: super::Factory) {
|
|||||||
|
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(150_000);
|
params.gas = U256::from(150_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
@ -908,7 +908,7 @@ fn test_calls(factory: super::Factory) {
|
|||||||
let code_address = Address::from(0x998);
|
let code_address = Address::from(0x998);
|
||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.gas = U256::from(150_000);
|
params.gas = U256::from(150_000);
|
||||||
params.code = Some(code);
|
params.code = Some(Arc::new(code));
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
let mut ext = FakeExt::new();
|
let mut ext = FakeExt::new();
|
||||||
ext.balances = {
|
ext.balances = {
|
||||||
|
@ -167,13 +167,14 @@ impl<'a> Executive<'a> {
|
|||||||
let new_address = contract_address(&sender, &nonce);
|
let new_address = contract_address(&sender, &nonce);
|
||||||
let params = ActionParams {
|
let params = ActionParams {
|
||||||
code_address: new_address.clone(),
|
code_address: new_address.clone(),
|
||||||
|
code_hash: t.data.sha3(),
|
||||||
address: new_address,
|
address: new_address,
|
||||||
sender: sender.clone(),
|
sender: sender.clone(),
|
||||||
origin: sender.clone(),
|
origin: sender.clone(),
|
||||||
gas: init_gas,
|
gas: init_gas,
|
||||||
gas_price: t.gas_price,
|
gas_price: t.gas_price,
|
||||||
value: ActionValue::Transfer(t.value),
|
value: ActionValue::Transfer(t.value),
|
||||||
code: Some(t.data.clone()),
|
code: Some(Arc::new(t.data.clone())),
|
||||||
data: None,
|
data: None,
|
||||||
call_type: CallType::None,
|
call_type: CallType::None,
|
||||||
};
|
};
|
||||||
@ -189,6 +190,7 @@ impl<'a> Executive<'a> {
|
|||||||
gas_price: t.gas_price,
|
gas_price: t.gas_price,
|
||||||
value: ActionValue::Transfer(t.value),
|
value: ActionValue::Transfer(t.value),
|
||||||
code: self.state.code(address),
|
code: self.state.code(address),
|
||||||
|
code_hash: self.state.code_hash(address),
|
||||||
data: Some(t.data.clone()),
|
data: Some(t.data.clone()),
|
||||||
call_type: CallType::Call,
|
call_type: CallType::Call,
|
||||||
};
|
};
|
||||||
@ -510,7 +512,7 @@ mod tests {
|
|||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some("3331600055".from_hex().unwrap());
|
params.code = Some(Arc::new("3331600055".from_hex().unwrap()));
|
||||||
params.value = ActionValue::Transfer(U256::from(0x7));
|
params.value = ActionValue::Transfer(U256::from(0x7));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
@ -569,7 +571,7 @@ mod tests {
|
|||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.origin = sender.clone();
|
params.origin = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code.clone());
|
params.code = Some(Arc::new(code));
|
||||||
params.value = ActionValue::Transfer(U256::from(100));
|
params.value = ActionValue::Transfer(U256::from(100));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
@ -624,7 +626,7 @@ mod tests {
|
|||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.origin = sender.clone();
|
params.origin = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code.clone());
|
params.code = Some(Arc::new(code));
|
||||||
params.value = ActionValue::Transfer(U256::from(100));
|
params.value = ActionValue::Transfer(U256::from(100));
|
||||||
params.call_type = CallType::Call;
|
params.call_type = CallType::Call;
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
@ -734,7 +736,7 @@ mod tests {
|
|||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.origin = sender.clone();
|
params.origin = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code.clone());
|
params.code = Some(Arc::new(code));
|
||||||
params.value = ActionValue::Transfer(100.into());
|
params.value = ActionValue::Transfer(100.into());
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
@ -822,7 +824,7 @@ mod tests {
|
|||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.origin = sender.clone();
|
params.origin = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code.clone());
|
params.code = Some(Arc::new(code));
|
||||||
params.value = ActionValue::Transfer(U256::from(100));
|
params.value = ActionValue::Transfer(U256::from(100));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
@ -874,7 +876,7 @@ mod tests {
|
|||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.origin = sender.clone();
|
params.origin = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code.clone());
|
params.code = Some(Arc::new(code));
|
||||||
params.value = ActionValue::Transfer(U256::from(100));
|
params.value = ActionValue::Transfer(U256::from(100));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
@ -931,7 +933,7 @@ mod tests {
|
|||||||
params.address = address_a.clone();
|
params.address = address_a.clone();
|
||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code_a.clone());
|
params.code = Some(Arc::new(code_a.clone()));
|
||||||
params.value = ActionValue::Transfer(U256::from(100_000));
|
params.value = ActionValue::Transfer(U256::from(100_000));
|
||||||
|
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
@ -981,10 +983,10 @@ mod tests {
|
|||||||
let mut params = ActionParams::default();
|
let mut params = ActionParams::default();
|
||||||
params.address = address.clone();
|
params.address = address.clone();
|
||||||
params.gas = U256::from(100_000);
|
params.gas = U256::from(100_000);
|
||||||
params.code = Some(code.clone());
|
params.code = Some(Arc::new(code.clone()));
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.init_code(&address, code.clone());
|
state.init_code(&address, code);
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0);
|
let engine = TestEngine::new(0);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
@ -1182,7 +1184,7 @@ mod tests {
|
|||||||
params.sender = sender.clone();
|
params.sender = sender.clone();
|
||||||
params.origin = sender.clone();
|
params.origin = sender.clone();
|
||||||
params.gas = U256::from(0x0186a0);
|
params.gas = U256::from(0x0186a0);
|
||||||
params.code = Some(code.clone());
|
params.code = Some(Arc::new(code));
|
||||||
params.value = ActionValue::Transfer(U256::from_str("0de0b6b3a7640000").unwrap());
|
params.value = ActionValue::Transfer(U256::from_str("0de0b6b3a7640000").unwrap());
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
|
@ -147,7 +147,8 @@ impl<'a, T, V> Ext for Externalities<'a, T, V> where T: 'a + Tracer, V: 'a + VMT
|
|||||||
gas: *gas,
|
gas: *gas,
|
||||||
gas_price: self.origin_info.gas_price,
|
gas_price: self.origin_info.gas_price,
|
||||||
value: ActionValue::Transfer(*value),
|
value: ActionValue::Transfer(*value),
|
||||||
code: Some(code.to_vec()),
|
code: Some(Arc::new(code.to_vec())),
|
||||||
|
code_hash: code.sha3(),
|
||||||
data: None,
|
data: None,
|
||||||
call_type: CallType::None,
|
call_type: CallType::None,
|
||||||
};
|
};
|
||||||
@ -186,6 +187,7 @@ impl<'a, T, V> Ext for Externalities<'a, T, V> where T: 'a + Tracer, V: 'a + VMT
|
|||||||
gas: *gas,
|
gas: *gas,
|
||||||
gas_price: self.origin_info.gas_price,
|
gas_price: self.origin_info.gas_price,
|
||||||
code: self.state.code(code_address),
|
code: self.state.code(code_address),
|
||||||
|
code_hash: self.state.code_hash(code_address),
|
||||||
data: Some(data.to_vec()),
|
data: Some(data.to_vec()),
|
||||||
call_type: call_type,
|
call_type: call_type,
|
||||||
};
|
};
|
||||||
@ -202,8 +204,8 @@ impl<'a, T, V> Ext for Externalities<'a, T, V> where T: 'a + Tracer, V: 'a + VMT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcode(&self, address: &Address) -> Bytes {
|
fn extcode(&self, address: &Address) -> Arc<Bytes> {
|
||||||
self.state.code(address).unwrap_or_else(|| vec![])
|
self.state.code(address).unwrap_or_else(|| Arc::new(vec![]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcode_len(&self, address: &Address) -> u64 {
|
fn extcode_len(&self, address: &Address) -> u64 {
|
||||||
|
@ -128,7 +128,7 @@ impl<'a, T, V> Ext for TestExt<'a, T, V> where T: Tracer, V: VMTracer {
|
|||||||
MessageCallResult::Success(*gas)
|
MessageCallResult::Success(*gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extcode(&self, address: &Address) -> Bytes {
|
fn extcode(&self, address: &Address) -> Arc<Bytes> {
|
||||||
self.ext.extcode(address)
|
self.ext.extcode(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec<String> {
|
|||||||
for (address, account) in vm.post_state.unwrap().into_iter() {
|
for (address, account) in vm.post_state.unwrap().into_iter() {
|
||||||
let address = address.into();
|
let address = address.into();
|
||||||
let code: Vec<u8> = account.code.into();
|
let code: Vec<u8> = account.code.into();
|
||||||
fail_unless(state.code(&address).unwrap_or_else(Vec::new) == code, "code is incorrect");
|
fail_unless(state.code(&address).as_ref().map_or_else(|| code.is_empty(), |c| &**c == &code), "code is incorrect");
|
||||||
fail_unless(state.balance(&address) == account.balance.into(), "balance is incorrect");
|
fail_unless(state.balance(&address) == account.balance.into(), "balance is incorrect");
|
||||||
fail_unless(state.nonce(&address) == account.nonce.into(), "nonce is incorrect");
|
fail_unless(state.nonce(&address) == account.nonce.into(), "nonce is incorrect");
|
||||||
account.storage.into_iter().foreach(|(k, v)| {
|
account.storage.into_iter().foreach(|(k, v)| {
|
||||||
|
@ -538,7 +538,7 @@ impl MinerService for Miner {
|
|||||||
|
|
||||||
fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<Bytes> {
|
fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<Bytes> {
|
||||||
let sealing_work = self.sealing_work.lock();
|
let sealing_work = self.sealing_work.lock();
|
||||||
sealing_work.queue.peek_last_ref().map_or_else(|| chain.latest_code(address), |b| b.block().fields().state.code(address))
|
sealing_work.queue.peek_last_ref().map_or_else(|| chain.latest_code(address), |b| b.block().fields().state.code(address).map(|c| (*c).clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_author(&self, author: Address) {
|
fn set_author(&self, author: Address) {
|
||||||
|
@ -311,9 +311,14 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get accounts' code.
|
/// Get accounts' code.
|
||||||
pub fn code(&self, a: &Address) -> Option<Bytes> {
|
pub fn code(&self, a: &Address) -> Option<Arc<Bytes>> {
|
||||||
self.ensure_cached(a, RequireCache::Code,
|
self.ensure_cached(a, RequireCache::Code,
|
||||||
|a| a.as_ref().map_or(None, |a| a.code().map(|x|x.to_vec())))
|
|a| a.as_ref().map_or(None, |a| a.code().clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn code_hash(&self, a: &Address) -> H256 {
|
||||||
|
self.ensure_cached(a, RequireCache::None,
|
||||||
|
|a| a.as_ref().map_or(SHA3_EMPTY, |a| a.code_hash()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get accounts' code size.
|
/// Get accounts' code size.
|
||||||
@ -1517,14 +1522,14 @@ fn code_from_database() {
|
|||||||
let mut state = get_temp_state_in(temp.as_path());
|
let mut state = get_temp_state_in(temp.as_path());
|
||||||
state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{});
|
state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{});
|
||||||
state.init_code(&a, vec![1, 2, 3]);
|
state.init_code(&a, vec![1, 2, 3]);
|
||||||
assert_eq!(state.code(&a), Some([1u8, 2, 3].to_vec()));
|
assert_eq!(state.code(&a), Some(Arc::new([1u8, 2, 3].to_vec())));
|
||||||
state.commit().unwrap();
|
state.commit().unwrap();
|
||||||
assert_eq!(state.code(&a), Some([1u8, 2, 3].to_vec()));
|
assert_eq!(state.code(&a), Some(Arc::new([1u8, 2, 3].to_vec())));
|
||||||
state.drop()
|
state.drop()
|
||||||
};
|
};
|
||||||
|
|
||||||
let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap();
|
let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap();
|
||||||
assert_eq!(state.code(&a), Some([1u8, 2, 3].to_vec()));
|
assert_eq!(state.code(&a), Some(Arc::new([1u8, 2, 3].to_vec())));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -181,7 +181,7 @@ impl From<ActionParams> for Create {
|
|||||||
from: p.sender,
|
from: p.sender,
|
||||||
value: p.value.value(),
|
value: p.value.value(),
|
||||||
gas: p.gas,
|
gas: p.gas,
|
||||||
init: p.code.unwrap_or_else(Vec::new),
|
init: p.code.map_or_else(Vec::new, |c| (*c).clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
|
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
|
||||||
!define VERSIONMAJOR 1
|
!define VERSIONMAJOR 1
|
||||||
!define VERSIONMINOR 3
|
!define VERSIONMINOR 3
|
||||||
!define VERSIONBUILD 2
|
!define VERSIONBUILD 3
|
||||||
|
|
||||||
!addplugindir .\
|
!addplugindir .\
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ impl MinerService for TestMinerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn code(&self, _chain: &MiningBlockChainClient, address: &Address) -> Option<Bytes> {
|
fn code(&self, _chain: &MiningBlockChainClient, address: &Address) -> Option<Bytes> {
|
||||||
self.latest_closed_block.lock().as_ref().map_or(None, |b| b.block().fields().state.code(address).clone())
|
self.latest_closed_block.lock().as_ref().map_or(None, |b| b.block().fields().state.code(address).map(|c| (*c).clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ description = "Ethcore utility library"
|
|||||||
homepage = "http://ethcore.io"
|
homepage = "http://ethcore.io"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
name = "ethcore-util"
|
name = "ethcore-util"
|
||||||
version = "1.3.2"
|
version = "1.3.3"
|
||||||
authors = ["Ethcore <admin@ethcore.io>"]
|
authors = ["Ethcore <admin@ethcore.io>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ use target_info::Target;
|
|||||||
include!(concat!(env!("OUT_DIR"), "/version.rs"));
|
include!(concat!(env!("OUT_DIR"), "/version.rs"));
|
||||||
include!(concat!(env!("OUT_DIR"), "/rustc_version.rs"));
|
include!(concat!(env!("OUT_DIR"), "/rustc_version.rs"));
|
||||||
|
|
||||||
#[derive(PartialEq,Eq,Clone,Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
/// Boolean type for clean/dirty status.
|
/// Boolean type for clean/dirty status.
|
||||||
pub enum Filth {
|
pub enum Filth {
|
||||||
/// Data has not been changed.
|
/// Data has not been changed.
|
||||||
|
Loading…
Reference in New Issue
Block a user