diff --git a/Cargo.lock b/Cargo.lock
index e2b4da1eb..7e1aa0d2b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -125,7 +125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bigint"
-version = "3.0.0"
+version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -301,6 +301,7 @@ dependencies = [
"ethcore-util 1.8.0",
"ethjson 0.1.0",
"rlp 0.2.0",
+ "rlp_derive 0.1.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -526,6 +527,7 @@ dependencies = [
"price-info 1.7.0",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0",
+ "rlp_derive 0.1.0",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -542,7 +544,7 @@ dependencies = [
name = "ethcore-bigint"
version = "0.1.3"
dependencies = [
- "bigint 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bigint 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -652,6 +654,7 @@ dependencies = [
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0",
+ "rlp_derive 0.1.0",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -773,7 +776,6 @@ dependencies = [
"ethcore-devtools 1.8.0",
"ethcore-logger 1.8.0",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1217,7 +1219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jsonrpc-core"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1229,7 +1231,7 @@ dependencies = [
[[package]]
name = "jsonrpc-http-server"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@@ -1242,7 +1244,7 @@ dependencies = [
[[package]]
name = "jsonrpc-ipc-server"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@@ -1255,7 +1257,7 @@ dependencies = [
[[package]]
name = "jsonrpc-macros"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@@ -1265,7 +1267,7 @@ dependencies = [
[[package]]
name = "jsonrpc-minihttp-server"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@@ -1280,7 +1282,7 @@ dependencies = [
[[package]]
name = "jsonrpc-pubsub"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1290,7 +1292,7 @@ dependencies = [
[[package]]
name = "jsonrpc-server-utils"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1303,7 +1305,7 @@ dependencies = [
[[package]]
name = "jsonrpc-tcp-server"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@@ -1317,7 +1319,7 @@ dependencies = [
[[package]]
name = "jsonrpc-ws-server"
version = "7.0.0"
-source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#4d3ec22c7aba426988a678b489b2791e95283699"
+source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@@ -1860,6 +1862,7 @@ dependencies = [
"fetch 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1971,6 +1974,7 @@ dependencies = [
"fetch 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@@ -2053,7 +2057,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.4.0"
-source = "git+https://github.com/paritytech/js-precompiled.git#dd9b92d9d8c244678e15163347f9adb2e2560959"
+source = "git+https://github.com/paritytech/js-precompiled.git#416ced84c23b1a776d53ee4a3023eb4eb4736cf8"
dependencies = [
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2305,7 +2309,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
-version = "0.3.10"
+version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -2396,6 +2400,15 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "rlp_derive"
+version = "0.1.0"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rlp 0.2.0",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "rocksdb"
version = "0.4.5"
@@ -2453,7 +2466,7 @@ dependencies = [
name = "rpc-cli"
version = "1.4.0"
dependencies = [
- "bigint 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bigint 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-util 1.8.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rpc 1.8.0",
@@ -2588,7 +2601,7 @@ name = "serde_derive"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2730,7 +2743,7 @@ name = "syn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -3231,7 +3244,7 @@ dependencies = [
"checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff"
"checksum base-x 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f59103b47307f76e03bef1633aec7fa9e29bfb5aa6daf5a334f94233c71f6c1"
"checksum base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b9605ba46d61df0410d8ac686b0007add8172eba90e8e909c347856fe794d8c"
-"checksum bigint 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0673c930652d3d4d6dcd5c45b5db4fa5f8f33994d7323618c43c083b223e8c"
+"checksum bigint 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b45beaa0727835a98df09295d4250afc52c3f7d375d560997ae942c95b98ceb"
"checksum bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e"
"checksum bit-set 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6e1e6fb1c9e3d6fcdec57216a74eaa03e41f52a22f13a16438251d8e88b89da"
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
@@ -3384,7 +3397,7 @@ dependencies = [
"checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd"
"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
"checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a"
-"checksum quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6732e32663c9c271bfc7c1823486b471f18c47a2dbf87c066897b7b51afc83be"
+"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
"checksum rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c83adcb08e5b922e804fe1918142b422602ef11f2fd670b0b52218cb5984a20"
"checksum rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "767d91bacddf07d442fe39257bf04fd95897d1c47c545d009f6beb03efd038f8"
diff --git a/README.md b/README.md
index 16758bc27..24178edbe 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ Parity's current release is 1.7. You can download it at https://github.com/parit
## Build dependencies
-**Parity requires Rust version 1.18.0 to build**
+**Parity requires Rust version 1.19.0 to build**
We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have rustup, you can install it like this:
diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml
index 75e15e396..143bbe30f 100644
--- a/dapps/Cargo.toml
+++ b/dapps/Cargo.toml
@@ -27,6 +27,7 @@ time = "0.1.35"
unicase = "1.3"
url = "1.0"
zip = { version = "0.1", default-features = false }
+itertools = "0.5"
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" }
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" }
diff --git a/dapps/src/apps/mod.rs b/dapps/src/apps/mod.rs
index 376b8a36f..c38c6784a 100644
--- a/dapps/src/apps/mod.rs
+++ b/dapps/src/apps/mod.rs
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-use std::collections::BTreeMap;
use std::path::PathBuf;
use std::sync::Arc;
@@ -30,8 +29,8 @@ use {WebProxyTokens, ParentFrameSettings};
mod app;
mod cache;
-mod fs;
mod ui;
+pub mod fs;
pub mod fetcher;
pub mod manifest;
@@ -64,9 +63,10 @@ pub fn all_endpoints(
web_proxy_tokens: Arc,
remote: Remote,
fetch: F,
-) -> Endpoints {
+) -> (Vec, Endpoints) {
// fetch fs dapps at first to avoid overwriting builtins
- let mut pages = fs::local_endpoints(dapps_path, embeddable.clone());
+ let mut pages = fs::local_endpoints(dapps_path.clone(), embeddable.clone());
+ let local_endpoints: Vec = pages.keys().cloned().collect();
for path in extra_dapps {
if let Some((id, endpoint)) = fs::local_endpoint(path.clone(), embeddable.clone()) {
pages.insert(id, endpoint);
@@ -80,10 +80,10 @@ pub fn all_endpoints(
pages.insert("proxy".into(), ProxyPac::boxed(embeddable.clone(), dapps_domain.to_owned()));
pages.insert(WEB_PATH.into(), Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), remote.clone(), fetch.clone()));
- Arc::new(pages)
+ (local_endpoints, pages)
}
-fn insert(pages: &mut BTreeMap>, id: &str, embed_at: Embeddable) {
+fn insert(pages: &mut Endpoints, id: &str, embed_at: Embeddable) {
pages.insert(id.to_owned(), Box::new(match embed_at {
Embeddable::Yes(address) => PageEndpoint::new_safe_to_embed(T::default(), address),
Embeddable::No => PageEndpoint::new(T::default()),
diff --git a/dapps/src/endpoint.rs b/dapps/src/endpoint.rs
index ea8fd0a38..ea5825b74 100644
--- a/dapps/src/endpoint.rs
+++ b/dapps/src/endpoint.rs
@@ -16,7 +16,6 @@
//! URL Endpoint traits
-use std::sync::Arc;
use std::collections::BTreeMap;
use hyper::{self, server, net};
@@ -39,7 +38,7 @@ pub struct EndpointInfo {
pub icon_url: String,
}
-pub type Endpoints = Arc>>;
+pub type Endpoints = BTreeMap>;
pub type Handler = server::Handler + Send;
pub trait Endpoint : Send + Sync {
diff --git a/dapps/src/handlers/mod.rs b/dapps/src/handlers/mod.rs
index 7937ce667..a8beabe84 100644
--- a/dapps/src/handlers/mod.rs
+++ b/dapps/src/handlers/mod.rs
@@ -31,8 +31,7 @@ pub use self::redirect::Redirection;
pub use self::streaming::StreamingHandler;
use std::iter;
-use util::Itertools;
-
+use itertools::Itertools;
use url::Url;
use hyper::{server, header, net, uri};
use {apps, address, Embeddable};
@@ -67,10 +66,20 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embedd
// Allow fonts from data: and HTTPS.
b"font-src 'self' data: https:;".to_vec(),
// Allow inline scripts and scripts eval (webpack/jsconsole)
- b"script-src 'self' 'unsafe-inline' 'unsafe-eval';".to_vec(),
- // Same restrictions as script-src (fallback) with additional
+ {
+ let script_src = embeddable_on.as_ref()
+ .map(|e| e.extra_script_src.iter()
+ .map(|&(ref host, port)| address(host, port))
+ .join(" ")
+ ).unwrap_or_default();
+ format!(
+ "script-src 'self' 'unsafe-inline' 'unsafe-eval' {};",
+ script_src
+ ).into_bytes()
+ },
+ // Same restrictions as script-src with additional
// blob: that is required for camera access (worker)
- b"worker-src 'self' 'unsafe-inline' 'unsafe-eval' blob: ;".to_vec(),
+ b"worker-src 'self' 'unsafe-inline' 'unsafe-eval' https: blob:;".to_vec(),
// Restrict everything else to the same origin.
b"default-src 'self';".to_vec(),
// Run in sandbox mode (although it's not fully safe since we allow same-origin and script)
@@ -90,7 +99,7 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embedd
.into_iter()
.chain(embed.extra_embed_on
.iter()
- .map(|&(ref host, port)| format!("{}:{}", host, port))
+ .map(|&(ref host, port)| address(host, port))
);
let ancestors = if embed.host == "127.0.0.1" {
diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs
index f34c24cae..135f0bb36 100644
--- a/dapps/src/lib.rs
+++ b/dapps/src/lib.rs
@@ -22,6 +22,7 @@
extern crate base32;
extern crate futures;
extern crate futures_cpupool;
+extern crate itertools;
extern crate linked_hash_map;
extern crate mime_guess;
extern crate ntp;
@@ -69,9 +70,11 @@ mod web;
#[cfg(test)]
mod tests;
+use std::collections::HashMap;
+use std::mem;
use std::path::PathBuf;
use std::sync::Arc;
-use std::collections::HashMap;
+use util::RwLock;
use jsonrpc_http_server::{self as http, hyper, Origin};
@@ -101,31 +104,54 @@ impl WebProxyTokens for F where F: Fn(String) -> Option + Send + Sync
}
/// Current supported endpoints.
+#[derive(Default, Clone)]
pub struct Endpoints {
- endpoints: endpoint::Endpoints,
+ local_endpoints: Arc>>,
+ endpoints: Arc>,
+ dapps_path: PathBuf,
+ embeddable: Option,
}
impl Endpoints {
/// Returns a current list of app endpoints.
pub fn list(&self) -> Vec {
- self.endpoints.iter().filter_map(|(ref k, ref e)| {
+ self.endpoints.read().iter().filter_map(|(ref k, ref e)| {
e.info().map(|ref info| apps::App::from_info(k, info))
}).collect()
}
+
+ /// Check for any changes in the local dapps folder and update.
+ pub fn refresh_local_dapps(&self) {
+ let new_local = apps::fs::local_endpoints(&self.dapps_path, self.embeddable.clone());
+ let old_local = mem::replace(&mut *self.local_endpoints.write(), new_local.keys().cloned().collect());
+ let (_, to_remove): (_, Vec<_>) = old_local
+ .into_iter()
+ .partition(|k| new_local.contains_key(&k.clone()));
+
+ let mut endpoints = self.endpoints.write();
+ // remove the dead dapps
+ for k in to_remove {
+ endpoints.remove(&k);
+ }
+ // new dapps to be added
+ for (k, v) in new_local {
+ if !endpoints.contains_key(&k) {
+ endpoints.insert(k, v);
+ }
+ }
+ }
}
/// Dapps server as `jsonrpc-http-server` request middleware.
pub struct Middleware {
+ endpoints: Endpoints,
router: router::Router,
- endpoints: endpoint::Endpoints,
}
impl Middleware {
/// Get local endpoints handle.
- pub fn endpoints(&self) -> Endpoints {
- Endpoints {
- endpoints: self.endpoints.clone(),
- }
+ pub fn endpoints(&self) -> &Endpoints {
+ &self.endpoints
}
/// Creates new middleware for UI server.
@@ -164,8 +190,8 @@ impl Middleware {
);
Middleware {
- router: router,
endpoints: Default::default(),
+ router: router,
}
}
@@ -176,6 +202,7 @@ impl Middleware {
remote: Remote,
ui_address: Option<(String, u16)>,
extra_embed_on: Vec<(String, u16)>,
+ extra_script_src: Vec<(String, u16)>,
dapps_path: PathBuf,
extra_dapps: Vec,
dapps_domain: &str,
@@ -184,15 +211,15 @@ impl Middleware {
web_proxy_tokens: Arc,
fetch: F,
) -> Self {
- let embeddable = as_embeddable(ui_address, extra_embed_on, dapps_domain);
+ let embeddable = as_embeddable(ui_address, extra_embed_on, extra_script_src, dapps_domain);
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
hash_fetch::urlhint::URLHintContract::new(registrar),
sync_status.clone(),
remote.clone(),
fetch.clone(),
).embeddable_on(embeddable.clone()).allow_dapps(true));
- let endpoints = apps::all_endpoints(
- dapps_path,
+ let (local_endpoints, endpoints) = apps::all_endpoints(
+ dapps_path.clone(),
extra_dapps,
dapps_domain,
embeddable.clone(),
@@ -200,6 +227,12 @@ impl Middleware {
remote.clone(),
fetch.clone(),
);
+ let endpoints = Endpoints {
+ endpoints: Arc::new(RwLock::new(endpoints)),
+ dapps_path,
+ local_endpoints: Arc::new(RwLock::new(local_endpoints)),
+ embeddable: embeddable.clone(),
+ };
let special = {
let mut special = special_endpoints(
@@ -225,8 +258,8 @@ impl Middleware {
);
Middleware {
- router: router,
- endpoints: endpoints,
+ endpoints,
+ router,
}
}
}
@@ -263,12 +296,14 @@ fn address(host: &str, port: u16) -> String {
fn as_embeddable(
ui_address: Option<(String, u16)>,
extra_embed_on: Vec<(String, u16)>,
+ extra_script_src: Vec<(String, u16)>,
dapps_domain: &str,
) -> Option {
ui_address.map(|(host, port)| ParentFrameSettings {
host,
port,
extra_embed_on,
+ extra_script_src,
dapps_domain: dapps_domain.to_owned(),
})
}
@@ -289,8 +324,10 @@ pub struct ParentFrameSettings {
pub host: String,
/// Port
pub port: u16,
- /// Additional pages the pages can be embedded on.
+ /// Additional URLs the dapps can be embedded on.
pub extra_embed_on: Vec<(String, u16)>,
+ /// Additional URLs the dapp scripts can be loaded from.
+ pub extra_script_src: Vec<(String, u16)>,
/// Dapps Domain (web3.site)
pub dapps_domain: String,
}
diff --git a/dapps/src/router.rs b/dapps/src/router.rs
index 5cf92ff7e..2b74d51df 100644
--- a/dapps/src/router.rs
+++ b/dapps/src/router.rs
@@ -28,7 +28,8 @@ use jsonrpc_http_server as http;
use apps;
use apps::fetcher::Fetcher;
-use endpoint::{Endpoint, Endpoints, EndpointPath, Handler};
+use endpoint::{Endpoint, EndpointPath, Handler};
+use Endpoints;
use handlers;
use Embeddable;
@@ -50,26 +51,27 @@ pub struct Router {
dapps_domain: String,
}
-impl http::RequestMiddleware for Router {
- fn on_request(&self, req: &server::Request, control: &Control) -> http::RequestMiddlewareAction {
+impl Router {
+ fn resolve_request(&self, req: &server::Request, control: Control, refresh_dapps: bool) -> (bool, Option>) {
// Choose proper handler depending on path / domain
let url = handlers::extract_url(req);
let endpoint = extract_endpoint(&url, &self.dapps_domain);
let referer = extract_referer_endpoint(req, &self.dapps_domain);
let is_utils = endpoint.1 == SpecialEndpoint::Utils;
- let is_origin_set = req.headers().get::().is_some();
let is_get_request = *req.method() == hyper::Method::Get;
let is_head_request = *req.method() == hyper::Method::Head;
+ let has_dapp = |dapp: &str| self.endpoints
+ .as_ref()
+ .map_or(false, |endpoints| endpoints.endpoints.read().contains_key(dapp));
trace!(target: "dapps", "Routing request to {:?}. Details: {:?}", url, req);
-
- let control = control.clone();
debug!(target: "dapps", "Handling endpoint request: {:?}", endpoint);
- let handler: Option> = match (endpoint.0, endpoint.1, referer) {
+
+ (is_utils, match (endpoint.0, endpoint.1, referer) {
// Handle invalid web requests that we can recover from
(ref path, SpecialEndpoint::None, Some((ref referer, ref referer_url)))
if referer.app_id == apps::WEB_PATH
- && self.endpoints.as_ref().map(|ep| ep.contains_key(apps::WEB_PATH)).unwrap_or(false)
+ && has_dapp(apps::WEB_PATH)
&& !is_web_endpoint(path)
=>
{
@@ -88,11 +90,13 @@ impl http::RequestMiddleware for Router {
.map(|special| special.to_async_handler(path.clone().unwrap_or_default(), control))
},
// Then delegate to dapp
- (Some(ref path), _, _) if self.endpoints.as_ref().map(|ep| ep.contains_key(&path.app_id)).unwrap_or(false) => {
+ (Some(ref path), _, _) if has_dapp(&path.app_id) => {
trace!(target: "dapps", "Resolving to local/builtin dapp.");
Some(self.endpoints
.as_ref()
.expect("endpoints known to be set; qed")
+ .endpoints
+ .read()
.get(&path.app_id)
.expect("endpoints known to contain key; qed")
.to_async_handler(path.clone(), control))
@@ -110,13 +114,19 @@ impl http::RequestMiddleware for Router {
=>
{
trace!(target: "dapps", "Resolving to 404.");
- Some(Box::new(handlers::ContentHandler::error(
- hyper::StatusCode::NotFound,
- "404 Not Found",
- "Requested content was not found.",
- None,
- self.embeddable_on.clone(),
- )))
+ if refresh_dapps {
+ debug!(target: "dapps", "Refreshing dapps and re-trying.");
+ self.endpoints.as_ref().map(|endpoints| endpoints.refresh_local_dapps());
+ return self.resolve_request(req, control, false)
+ } else {
+ Some(Box::new(handlers::ContentHandler::error(
+ hyper::StatusCode::NotFound,
+ "404 Not Found",
+ "Requested content was not found.",
+ None,
+ self.embeddable_on.clone(),
+ )))
+ }
},
// Any other GET|HEAD requests to home page.
_ if (is_get_request || is_head_request) && self.special.contains_key(&SpecialEndpoint::Home) => {
@@ -130,8 +140,15 @@ impl http::RequestMiddleware for Router {
trace!(target: "dapps", "Resolving to RPC call.");
None
}
- };
+ })
+ }
+}
+impl http::RequestMiddleware for Router {
+ fn on_request(&self, req: &server::Request, control: &Control) -> http::RequestMiddlewareAction {
+ let control = control.clone();
+ let is_origin_set = req.headers().get::().is_some();
+ let (is_utils, handler) = self.resolve_request(req, control, self.endpoints.is_some());
match handler {
Some(handler) => http::RequestMiddlewareAction::Respond {
should_validate_hosts: !is_utils,
diff --git a/dapps/src/tests/fetch.rs b/dapps/src/tests/fetch.rs
index 8abc86196..f12323155 100644
--- a/dapps/src/tests/fetch.rs
+++ b/dapps/src/tests/fetch.rs
@@ -39,7 +39,7 @@ fn should_resolve_dapp() {
// then
response.assert_status("HTTP/1.1 404 Not Found");
- assert_eq!(registrar.calls.lock().len(), 2);
+ assert_eq!(registrar.calls.lock().len(), 4);
assert_security_headers_for_embed(&response.headers);
}
diff --git a/dapps/src/tests/helpers/mod.rs b/dapps/src/tests/helpers/mod.rs
index 38dd82de6..30d3ba8f9 100644
--- a/dapps/src/tests/helpers/mod.rs
+++ b/dapps/src/tests/helpers/mod.rs
@@ -260,6 +260,7 @@ impl Server {
remote,
signer_address,
vec![],
+ vec![],
dapps_path,
extra_dapps,
DAPPS_DOMAIN.into(),
diff --git a/dapps/src/tests/redirection.rs b/dapps/src/tests/redirection.rs
index 1e9b039e2..81d3ec76c 100644
--- a/dapps/src/tests/redirection.rs
+++ b/dapps/src/tests/redirection.rs
@@ -204,4 +204,3 @@ fn should_serve_utils() {
assert_eq!(response.body.contains("function(){"), true);
assert_security_headers(&response.headers);
}
-
diff --git a/dapps/src/web.rs b/dapps/src/web.rs
index 637a5287e..5222f51b5 100644
--- a/dapps/src/web.rs
+++ b/dapps/src/web.rs
@@ -241,5 +241,3 @@ impl server::Handler for WebHandler {
}
}
}
-
-
diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml
index 0b4abc1bb..c49e31898 100644
--- a/ethcore/Cargo.toml
+++ b/ethcore/Cargo.toml
@@ -47,6 +47,7 @@ num_cpus = "1.2"
price-info = { path = "../price-info" }
rand = "0.3"
rlp = { path = "../util/rlp" }
+rlp_derive = { path = "../util/rlp_derive" }
rust-crypto = "0.2.34"
rustc-hex = "1.0"
semver = "0.6"
diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml
index b652050d2..9fda78f47 100644
--- a/ethcore/light/Cargo.toml
+++ b/ethcore/light/Cargo.toml
@@ -21,6 +21,7 @@ ethcore-devtools = { path = "../../devtools" }
evm = { path = "../evm" }
vm = { path = "../vm" }
rlp = { path = "../../util/rlp" }
+rlp_derive = { path = "../../util/rlp_derive" }
time = "0.1"
smallvec = "0.4"
futures = "0.1"
diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs
index 3f0e50584..d1cdfe9aa 100644
--- a/ethcore/light/src/client/mod.rs
+++ b/ethcore/light/src/client/mod.rs
@@ -100,8 +100,8 @@ pub trait LightChainClient: Send + Sync {
/// Get an iterator over a block and its ancestry.
fn ancestry_iter<'a>(&'a self, start: BlockId) -> Box + 'a>;
- /// Get the signing network ID.
- fn signing_network_id(&self) -> Option;
+ /// Get the signing chain ID.
+ fn signing_chain_id(&self) -> Option;
/// Get environment info for execution at a given block.
/// Fails if that block's header is not stored.
@@ -260,9 +260,9 @@ impl Client {
self.chain.ancestry_iter(start)
}
- /// Get the signing network id.
- pub fn signing_network_id(&self) -> Option {
- self.engine.signing_network_id(&self.latest_env_info())
+ /// Get the signing chain id.
+ pub fn signing_chain_id(&self) -> Option {
+ self.engine.signing_chain_id(&self.latest_env_info())
}
/// Flush the header queue.
@@ -448,8 +448,8 @@ impl LightChainClient for Client {
Box::new(Client::ancestry_iter(self, start))
}
- fn signing_network_id(&self) -> Option {
- Client::signing_network_id(self)
+ fn signing_chain_id(&self) -> Option {
+ Client::signing_chain_id(self)
}
fn env_info(&self, id: BlockId) -> Option {
diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs
index b172134cf..c2ab483d2 100644
--- a/ethcore/light/src/lib.rs
+++ b/ethcore/light/src/lib.rs
@@ -76,6 +76,8 @@ extern crate futures;
extern crate itertools;
extern crate rand;
extern crate rlp;
+#[macro_use]
+extern crate rlp_derive;
extern crate serde;
extern crate smallvec;
extern crate stats;
diff --git a/ethcore/light/src/types/request/mod.rs b/ethcore/light/src/types/request/mod.rs
index ff4a32535..51f916b15 100644
--- a/ethcore/light/src/types/request/mod.rs
+++ b/ethcore/light/src/types/request/mod.rs
@@ -650,7 +650,7 @@ pub mod header {
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
/// Potentially incomplete headers request.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Start block.
pub start: Field,
@@ -662,27 +662,6 @@ pub mod header {
pub reverse: bool,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- start: rlp.val_at(0)?,
- skip: rlp.val_at(1)?,
- max: rlp.val_at(2)?,
- reverse: rlp.val_at(3)?
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(4)
- .append(&self.start)
- .append(&self.skip)
- .append(&self.max)
- .append(&self.reverse);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@@ -784,26 +763,12 @@ pub mod header_proof {
use util::{Bytes, U256, H256};
/// Potentially incomplete header proof request.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block number.
pub num: Field,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- num: rlp.val_at(0)?,
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(1).append(&self.num);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@@ -889,30 +854,15 @@ pub mod header_proof {
/// Request and response for transaction index.
pub mod transaction_index {
use super::{Field, NoSuchOutput, OutputKind, Output};
- use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::H256;
/// Potentially incomplete transaction index request.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Transaction hash to get index for.
pub hash: Field,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- hash: rlp.val_at(0)?,
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(1).append(&self.hash);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@@ -959,7 +909,7 @@ pub mod transaction_index {
}
/// The output of a request for transaction index.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Response {
/// Block number.
pub num: u64,
@@ -976,55 +926,21 @@ pub mod transaction_index {
f(1, Output::Hash(self.hash));
}
}
-
- impl Decodable for Response {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Response {
- num: rlp.val_at(0)?,
- hash: rlp.val_at(1)?,
- index: rlp.val_at(2)?,
- })
- }
- }
-
- impl Encodable for Response {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(3)
- .append(&self.num)
- .append(&self.hash)
- .append(&self.index);
- }
- }
}
/// Request and response for block receipts
pub mod block_receipts {
use super::{Field, NoSuchOutput, OutputKind, Output};
use ethcore::receipt::Receipt;
- use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::H256;
/// Potentially incomplete block receipts request.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block hash to get receipts for.
pub hash: Field,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- hash: rlp.val_at(0)?,
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(1).append(&self.hash);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@@ -1068,7 +984,7 @@ pub mod block_receipts {
}
/// The output of a request for block receipts.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct Response {
/// The block receipts.
pub receipts: Vec
@@ -1078,20 +994,6 @@ pub mod block_receipts {
/// Fill reusable outputs by providing them to the function.
fn fill_outputs(&self, _: F) where F: FnMut(usize, Output) {}
}
-
- impl Decodable for Response {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Response {
- receipts: rlp.as_list()?,
- })
- }
- }
-
- impl Encodable for Response {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.append_list(&self.receipts);
- }
- }
}
/// Request and response for a block body
@@ -1102,26 +1004,12 @@ pub mod block_body {
use util::H256;
/// Potentially incomplete block body request.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block hash to get receipts for.
pub hash: Field,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- hash: rlp.val_at(0)?,
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(1).append(&self.hash);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@@ -1201,11 +1089,10 @@ pub mod block_body {
/// A request for an account proof.
pub mod account {
use super::{Field, NoSuchOutput, OutputKind, Output};
- use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::{Bytes, U256, H256};
/// Potentially incomplete request for an account proof.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block hash to request state proof for.
pub block_hash: Field,
@@ -1213,23 +1100,6 @@ pub mod account {
pub address_hash: Field,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- block_hash: rlp.val_at(0)?,
- address_hash: rlp.val_at(1)?,
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(2)
- .append(&self.block_hash)
- .append(&self.address_hash);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@@ -1292,7 +1162,7 @@ pub mod account {
}
/// The output of a request for an account state proof.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Response {
/// Inclusion/exclusion proof
pub proof: Vec,
@@ -1313,39 +1183,15 @@ pub mod account {
f(1, Output::Hash(self.storage_root));
}
}
-
- impl Decodable for Response {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Response {
- proof: rlp.list_at(0)?,
- nonce: rlp.val_at(1)?,
- balance: rlp.val_at(2)?,
- code_hash: rlp.val_at(3)?,
- storage_root: rlp.val_at(4)?
- })
- }
- }
-
- impl Encodable for Response {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(5)
- .append_list::,_>(&self.proof[..])
- .append(&self.nonce)
- .append(&self.balance)
- .append(&self.code_hash)
- .append(&self.storage_root);
- }
- }
}
/// A request for a storage proof.
pub mod storage {
use super::{Field, NoSuchOutput, OutputKind, Output};
- use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::{Bytes, H256};
/// Potentially incomplete request for an storage proof.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// Block hash to request state proof for.
pub block_hash: Field,
@@ -1355,25 +1201,6 @@ pub mod storage {
pub key_hash: Field,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- block_hash: rlp.val_at(0)?,
- address_hash: rlp.val_at(1)?,
- key_hash: rlp.val_at(2)?,
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(3)
- .append(&self.block_hash)
- .append(&self.address_hash)
- .append(&self.key_hash);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@@ -1450,7 +1277,7 @@ pub mod storage {
}
/// The output of a request for an account state proof.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Response {
/// Inclusion/exclusion proof
pub proof: Vec,
@@ -1464,33 +1291,15 @@ pub mod storage {
f(0, Output::Hash(self.value));
}
}
-
- impl Decodable for Response {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Response {
- proof: rlp.list_at(0)?,
- value: rlp.val_at(1)?,
- })
- }
- }
-
- impl Encodable for Response {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(2)
- .append_list::,_>(&self.proof[..])
- .append(&self.value);
- }
- }
}
/// A request for contract code.
pub mod contract_code {
use super::{Field, NoSuchOutput, OutputKind, Output};
- use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use util::{Bytes, H256};
/// Potentially incomplete contract code request.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// The block hash to request the state for.
pub block_hash: Field,
@@ -1498,23 +1307,6 @@ pub mod contract_code {
pub code_hash: Field,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- block_hash: rlp.val_at(0)?,
- code_hash: rlp.val_at(1)?,
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(2)
- .append(&self.block_hash)
- .append(&self.code_hash);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
@@ -1573,7 +1365,7 @@ pub mod contract_code {
}
/// The output of a request for
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct Response {
/// The requested code.
pub code: Bytes,
@@ -1583,21 +1375,6 @@ pub mod contract_code {
/// Fill reusable outputs by providing them to the function.
fn fill_outputs(&self, _: F) where F: FnMut(usize, Output) {}
}
-
- impl Decodable for Response {
- fn decode(rlp: &UntrustedRlp) -> Result {
-
- Ok(Response {
- code: rlp.as_val()?,
- })
- }
- }
-
- impl Encodable for Response {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.append(&self.code);
- }
- }
}
/// A request for proof of execution.
@@ -1608,7 +1385,7 @@ pub mod execution {
use util::{Bytes, Address, U256, H256, DBValue};
/// Potentially incomplete execution proof request.
- #[derive(Debug, Clone, PartialEq, Eq)]
+ #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct Incomplete {
/// The block hash to request the state for.
pub block_hash: Field,
@@ -1626,38 +1403,6 @@ pub mod execution {
pub data: Bytes,
}
- impl Decodable for Incomplete {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Incomplete {
- block_hash: rlp.val_at(0)?,
- from: rlp.val_at(1)?,
- action: rlp.val_at(2)?,
- gas: rlp.val_at(3)?,
- gas_price: rlp.val_at(4)?,
- value: rlp.val_at(5)?,
- data: rlp.val_at(6)?,
- })
- }
- }
-
- impl Encodable for Incomplete {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(7)
- .append(&self.block_hash)
- .append(&self.from);
-
- match self.action {
- Action::Create => s.append_empty_data(),
- Action::Call(ref addr) => s.append(addr),
- };
-
- s.append(&self.gas)
- .append(&self.gas_price)
- .append(&self.value)
- .append(&self.data);
- }
- }
-
impl super::IncompleteRequest for Incomplete {
type Complete = Complete;
type Response = Response;
diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs
index 249ca40af..752cec964 100755
--- a/ethcore/src/account_provider/mod.rs
+++ b/ethcore/src/account_provider/mod.rs
@@ -519,6 +519,11 @@ impl AccountProvider {
}
}
+ /// Returns account public key.
+ pub fn account_public(&self, address: Address, password: &str) -> Result {
+ self.sstore.public(&self.sstore.account_ref(&address)?, password)
+ }
+
/// Returns each account along with name and meta.
pub fn set_account_name(&self, address: Address, name: String) -> Result<(), Error> {
self.sstore.set_name(&self.sstore.account_ref(&address)?, name)?;
@@ -697,6 +702,13 @@ impl AccountProvider {
Ok(self.sstore.decrypt(&account, &password, shared_mac, message)?)
}
+ /// Agree on shared key.
+ pub fn agree(&self, address: Address, password: Option, other_public: &Public) -> Result {
+ let account = self.sstore.account_ref(&address)?;
+ let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?;
+ Ok(self.sstore.agree(&account, &password, other_public)?)
+ }
+
/// Returns the underlying `SecretStore` reference if one exists.
pub fn list_geth_accounts(&self, testnet: bool) -> Vec {
self.sstore.list_geth_accounts(testnet).into_iter().map(|a| Address::from(a).into()).collect()
diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs
index bd0defa47..001df861c 100644
--- a/ethcore/src/blockchain/blockchain.rs
+++ b/ethcore/src/blockchain/blockchain.rs
@@ -19,6 +19,7 @@
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use std::mem;
+use itertools::Itertools;
use bloomchain as bc;
use util::*;
use rlp::*;
diff --git a/ethcore/src/blockchain/extras.rs b/ethcore/src/blockchain/extras.rs
index ed3a5009b..0e2396f8c 100644
--- a/ethcore/src/blockchain/extras.rs
+++ b/ethcore/src/blockchain/extras.rs
@@ -25,11 +25,9 @@ use engines::epoch::{Transition as EpochTransition};
use header::BlockNumber;
use receipt::Receipt;
-use rlp::*;
-use util::*;
+use util::{HeapSizeOf, H256, H264, U256};
use util::kvdb::PREFIX_LEN as DB_PREFIX_LEN;
-
/// Represents index of extra data in database
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
pub enum ExtrasIndex {
@@ -184,7 +182,7 @@ impl Key for u64 {
}
/// Familial details concerning a block
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, RlpEncodable, RlpDecodable)]
pub struct BlockDetails {
/// Block number
pub number: BlockNumber,
@@ -202,30 +200,8 @@ impl HeapSizeOf for BlockDetails {
}
}
-impl Decodable for BlockDetails {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let details = BlockDetails {
- number: rlp.val_at(0)?,
- total_difficulty: rlp.val_at(1)?,
- parent: rlp.val_at(2)?,
- children: rlp.list_at(3)?,
- };
- Ok(details)
- }
-}
-
-impl Encodable for BlockDetails {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(4);
- s.append(&self.number);
- s.append(&self.total_difficulty);
- s.append(&self.parent);
- s.append_list(&self.children);
- }
-}
-
/// Represents address of certain transaction within block
-#[derive(Debug, PartialEq, Clone)]
+#[derive(Debug, PartialEq, Clone, RlpEncodable, RlpDecodable)]
pub struct TransactionAddress {
/// Block hash
pub block_hash: H256,
@@ -237,27 +213,8 @@ impl HeapSizeOf for TransactionAddress {
fn heap_size_of_children(&self) -> usize { 0 }
}
-impl Decodable for TransactionAddress {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let tx_address = TransactionAddress {
- block_hash: rlp.val_at(0)?,
- index: rlp.val_at(1)?,
- };
-
- Ok(tx_address)
- }
-}
-
-impl Encodable for TransactionAddress {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(2);
- s.append(&self.block_hash);
- s.append(&self.index);
- }
-}
-
/// Contains all block receipts.
-#[derive(Clone)]
+#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct BlockReceipts {
pub receipts: Vec,
}
@@ -270,20 +227,6 @@ impl BlockReceipts {
}
}
-impl Decodable for BlockReceipts {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(BlockReceipts {
- receipts: rlp.as_list()?,
- })
- }
-}
-
-impl Encodable for BlockReceipts {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.append_list(&self.receipts);
- }
-}
-
impl HeapSizeOf for BlockReceipts {
fn heap_size_of_children(&self) -> usize {
self.receipts.heap_size_of_children()
@@ -291,27 +234,12 @@ impl HeapSizeOf for BlockReceipts {
}
/// Candidate transitions to an epoch with specific number.
-#[derive(Clone)]
+#[derive(Clone, RlpEncodable, RlpDecodable)]
pub struct EpochTransitions {
pub number: u64,
pub candidates: Vec,
}
-impl Encodable for EpochTransitions {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(2).append(&self.number).append_list(&self.candidates);
- }
-}
-
-impl Decodable for EpochTransitions {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(EpochTransitions {
- number: rlp.val_at(0)?,
- candidates: rlp.list_at(1)?,
- })
- }
-}
-
#[cfg(test)]
mod tests {
use rlp::*;
diff --git a/ethcore/src/blooms/bloom.rs b/ethcore/src/blooms/bloom.rs
index cac9ff448..c79091cb4 100644
--- a/ethcore/src/blooms/bloom.rs
+++ b/ethcore/src/blooms/bloom.rs
@@ -15,12 +15,11 @@
// along with Parity. If not, see .
use bloomchain as bc;
-use rlp::*;
use util::HeapSizeOf;
use basic_types::LogBloom;
/// Helper structure representing bloom of the trace.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct Bloom(LogBloom);
impl From for Bloom {
@@ -43,18 +42,6 @@ impl Into for Bloom {
}
}
-impl Decodable for Bloom {
- fn decode(rlp: &UntrustedRlp) -> Result {
- LogBloom::decode(rlp).map(Bloom)
- }
-}
-
-impl Encodable for Bloom {
- fn rlp_append(&self, s: &mut RlpStream) {
- Encodable::rlp_append(&self.0, s)
- }
-}
-
impl HeapSizeOf for Bloom {
fn heap_size_of_children(&self) -> usize {
0
diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs
index 7141c7bdb..ff09a7b2b 100644
--- a/ethcore/src/client/client.rs
+++ b/ethcore/src/client/client.rs
@@ -20,9 +20,10 @@ use std::sync::{Arc, Weak};
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
use std::time::{Instant};
use time::precise_time_ns;
+use itertools::Itertools;
// util
-use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, MutexGuard, Hashable};
+use util::{Bytes, PerfTimer, Mutex, RwLock, MutexGuard, Hashable};
use util::{journaldb, DBValue, TrieFactory, Trie};
use util::{U256, H256, Address, H2048};
use util::trie::TrieSpec;
@@ -1112,20 +1113,9 @@ impl Client {
}.fake_sign(from)
}
- fn do_call(&self, env_info: &EnvInfo, state: &mut State, increase_balance: bool, t: &SignedTransaction, analytics: CallAnalytics) -> Result {
+ fn do_call(&self, env_info: &EnvInfo, state: &mut State, t: &SignedTransaction, analytics: CallAnalytics) -> Result {
let original_state = if analytics.state_diffing { Some(state.clone()) } else { None };
- // give the sender a sufficient balance (if calling in pending block)
- if increase_balance {
- let sender = t.sender();
- let balance = state.balance(&sender).map_err(ExecutionError::from)?;
- let needed_balance = t.value + t.gas * t.gas_price;
- if balance < needed_balance {
- state.add_balance(&sender, &(needed_balance - balance), state::CleanupMode::NoEmpty)
- .map_err(ExecutionError::from)?;
- }
- }
-
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
let mut ret = Executive::new(state, env_info, &*self.engine).transact_virtual(t, options)?;
@@ -1167,7 +1157,7 @@ impl BlockChainClient for Client {
// that's just a copy of the state.
let mut state = self.state_at(block).ok_or(CallError::StatePruned)?;
- self.do_call(&env_info, &mut state, block == BlockId::Pending, transaction, analytics)
+ self.do_call(&env_info, &mut state, transaction, analytics)
}
fn call_many(&self, transactions: &[(SignedTransaction, CallAnalytics)], block: BlockId) -> Result, CallError> {
@@ -1179,7 +1169,7 @@ impl BlockChainClient for Client {
let mut results = Vec::with_capacity(transactions.len());
for &(ref t, analytics) in transactions {
- let ret = self.do_call(&env_info, &mut state, block == BlockId::Pending, t, analytics)?;
+ let ret = self.do_call(&env_info, &mut state, t, analytics)?;
env_info.gas_used = ret.cumulative_gas_used;
results.push(ret);
}
@@ -1730,8 +1720,8 @@ impl BlockChainClient for Client {
}
}
- fn signing_network_id(&self) -> Option {
- self.engine.signing_network_id(&self.latest_env_info())
+ fn signing_chain_id(&self) -> Option {
+ self.engine.signing_chain_id(&self.latest_env_info())
}
fn block_extra_info(&self, id: BlockId) -> Option> {
@@ -1770,9 +1760,9 @@ impl BlockChainClient for Client {
value: U256::zero(),
data: data,
};
- let network_id = self.engine.signing_network_id(&self.latest_env_info());
- let signature = self.engine.sign(transaction.hash(network_id))?;
- let signed = SignedTransaction::new(transaction.with_signature(signature, network_id))?;
+ let chain_id = self.engine.signing_chain_id(&self.latest_env_info());
+ let signature = self.engine.sign(transaction.hash(chain_id))?;
+ let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?;
self.miner.import_own_transaction(self, signed.into())
}
diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs
index 2a205868d..0e7e53e43 100644
--- a/ethcore/src/client/test_client.rs
+++ b/ethcore/src/client/test_client.rs
@@ -20,6 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder};
use std::sync::Arc;
use std::collections::{HashMap, BTreeMap};
use std::mem;
+use itertools::Itertools;
use rustc_hex::FromHex;
use util::*;
use rlp::*;
@@ -733,7 +734,7 @@ impl BlockChainClient for TestBlockChainClient {
self.miner.ready_transactions(info.best_block_number, info.best_block_timestamp)
}
- fn signing_network_id(&self) -> Option { None }
+ fn signing_chain_id(&self) -> Option { None }
fn mode(&self) -> Mode { Mode::Active }
@@ -764,9 +765,9 @@ impl BlockChainClient for TestBlockChainClient {
value: U256::default(),
data: data,
};
- let network_id = Some(self.spec.params().network_id);
- let sig = self.spec.engine.sign(transaction.hash(network_id)).unwrap();
- let signed = SignedTransaction::new(transaction.with_signature(sig, network_id)).unwrap();
+ let chain_id = Some(self.spec.chain_id());
+ let sig = self.spec.engine.sign(transaction.hash(chain_id)).unwrap();
+ let signed = SignedTransaction::new(transaction.with_signature(sig, chain_id)).unwrap();
self.miner.import_own_transaction(self, signed.into())
}
diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs
index 8e1bd8b18..d7b7bba44 100644
--- a/ethcore/src/client/traits.rs
+++ b/ethcore/src/client/traits.rs
@@ -15,6 +15,7 @@
// along with Parity. If not, see .
use std::collections::BTreeMap;
+use itertools::Itertools;
use block::{OpenBlock, SealedBlock, ClosedBlock};
use blockchain::TreeRoute;
@@ -33,7 +34,7 @@ use trace::LocalizedTrace;
use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction};
use verification::queue::QueueInfo as BlockQueueInfo;
-use util::{U256, Address, H256, H2048, Bytes, Itertools};
+use util::{U256, Address, H256, H2048, Bytes};
use util::hashdb::DBValue;
use types::ids::*;
@@ -239,8 +240,8 @@ pub trait BlockChainClient : Sync + Send {
corpus.into()
}
- /// Get the preferred network ID to sign on
- fn signing_network_id(&self) -> Option;
+ /// Get the preferred chain ID to sign on
+ fn signing_chain_id(&self) -> Option;
/// Get the mode.
fn mode(&self) -> Mode;
diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs
index e7284bfbe..194fdd8fe 100644
--- a/ethcore/src/engines/authority_round/mod.rs
+++ b/ethcore/src/engines/authority_round/mod.rs
@@ -804,9 +804,9 @@ impl Engine for AuthorityRound {
fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> Result<(), Error> {
t.check_low_s()?;
- if let Some(n) = t.network_id() {
+ if let Some(n) = t.chain_id() {
if header.number() >= self.params().eip155_transition && n != self.params().chain_id {
- return Err(TransactionError::InvalidNetworkId.into());
+ return Err(TransactionError::InvalidChainId.into());
}
}
diff --git a/ethcore/src/engines/epoch.rs b/ethcore/src/engines/epoch.rs
index f738113cf..586059e83 100644
--- a/ethcore/src/engines/epoch.rs
+++ b/ethcore/src/engines/epoch.rs
@@ -16,14 +16,12 @@
//! Epoch verifiers and transitions.
+use util::H256;
use error::Error;
use header::Header;
-use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
-use util::H256;
-
/// A full epoch transition.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, RlpEncodable, RlpDecodable)]
pub struct Transition {
/// Block hash at which the transition occurred.
pub block_hash: H256,
@@ -33,46 +31,14 @@ pub struct Transition {
pub proof: Vec,
}
-impl Encodable for Transition {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(3)
- .append(&self.block_hash)
- .append(&self.block_number)
- .append(&self.proof);
- }
-}
-
-impl Decodable for Transition {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(Transition {
- block_hash: rlp.val_at(0)?,
- block_number: rlp.val_at(1)?,
- proof: rlp.val_at(2)?,
- })
- }
-}
-
/// An epoch transition pending a finality proof.
/// Not all transitions need one.
+#[derive(RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct PendingTransition {
/// "transition/epoch" proof from the engine.
pub proof: Vec,
}
-impl Encodable for PendingTransition {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.append(&self.proof);
- }
-}
-
-impl Decodable for PendingTransition {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(PendingTransition {
- proof: rlp.as_val()?,
- })
- }
-}
-
/// Verifier for all blocks within an epoch with self-contained state.
///
/// See docs on `Engine` relating to proving functions for more details.
diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs
index a293963d7..00f322318 100644
--- a/ethcore/src/engines/mod.rs
+++ b/ethcore/src/engines/mod.rs
@@ -263,7 +263,7 @@ pub trait Engine : Sync + Send {
// TODO: Add flags for which bits of the transaction to check.
// TODO: consider including State in the params.
fn verify_transaction_basic(&self, t: &UnverifiedTransaction, _header: &Header) -> Result<(), Error> {
- t.verify_basic(true, Some(self.params().network_id), true)?;
+ t.verify_basic(true, Some(self.params().chain_id), true)?;
Ok(())
}
@@ -273,7 +273,7 @@ pub trait Engine : Sync + Send {
}
/// The network ID that transactions should be signed with.
- fn signing_network_id(&self, _env_info: &EnvInfo) -> Option {
+ fn signing_chain_id(&self, _env_info: &EnvInfo) -> Option {
Some(self.params().chain_id)
}
diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs
index 3bdef480c..552154580 100644
--- a/ethcore/src/engines/null_engine.rs
+++ b/ethcore/src/engines/null_engine.rs
@@ -62,6 +62,6 @@ impl Engine for NullEngine {
}
fn snapshot_components(&self) -> Option> {
- Some(Box::new(::snapshot::PowSnapshot(10000)))
+ Some(Box::new(::snapshot::PowSnapshot::new(10000, 10000)))
}
}
diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs
index 96790dca7..1abcf2c8f 100644
--- a/ethcore/src/engines/validator_set/safe_contract.rs
+++ b/ethcore/src/engines/validator_set/safe_contract.rs
@@ -452,7 +452,7 @@ mod tests {
let s0: Secret = "1".sha3().into();
let v0 = tap.insert_account(s0.clone(), "").unwrap();
let v1 = tap.insert_account("0".sha3().into(), "").unwrap();
- let network_id = Spec::new_validator_safe_contract().network_id();
+ let chain_id = Spec::new_validator_safe_contract().chain_id();
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap));
client.engine().register_client(Arc::downgrade(&client));
let validator_contract = "0000000000000000000000000000000000000005".parse::().unwrap();
@@ -466,7 +466,7 @@ mod tests {
action: Action::Call(validator_contract),
value: 0.into(),
data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
- }.sign(&s0, Some(network_id));
+ }.sign(&s0, Some(chain_id));
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
client.update_sealing();
assert_eq!(client.chain_info().best_block_number, 1);
@@ -478,7 +478,7 @@ mod tests {
action: Action::Call(validator_contract),
value: 0.into(),
data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
- }.sign(&s0, Some(network_id));
+ }.sign(&s0, Some(chain_id));
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
client.update_sealing();
// The transaction is not yet included so still unable to seal.
@@ -497,7 +497,7 @@ mod tests {
action: Action::Call(Address::default()),
value: 0.into(),
data: Vec::new(),
- }.sign(&s0, Some(network_id));
+ }.sign(&s0, Some(chain_id));
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
client.update_sealing();
// Able to seal again.
diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs
index 194cbcb38..172323c0d 100644
--- a/ethcore/src/error.rs
+++ b/ethcore/src/error.rs
@@ -78,8 +78,8 @@ pub enum TransactionError {
RecipientBanned,
/// Contract creation code is banned.
CodeBanned,
- /// Invalid network ID given.
- InvalidNetworkId,
+ /// Invalid chain ID given.
+ InvalidChainId,
}
impl fmt::Display for TransactionError {
@@ -103,7 +103,7 @@ impl fmt::Display for TransactionError {
SenderBanned => "Sender is temporarily banned.".into(),
RecipientBanned => "Recipient is temporarily banned.".into(),
CodeBanned => "Contract code is temporarily banned.".into(),
- InvalidNetworkId => "Transaction of this network ID is not allowed on this chain.".into(),
+ InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(),
};
f.write_fmt(format_args!("Transaction error ({})", msg))
diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs
index 7e275cf98..6235255e4 100644
--- a/ethcore/src/ethereum/ethash.rs
+++ b/ethcore/src/ethereum/ethash.rs
@@ -39,7 +39,10 @@ pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]);
/// Number of blocks in an ethash snapshot.
// make dependent on difficulty incrment divisor?
-const SNAPSHOT_BLOCKS: u64 = 30000;
+const SNAPSHOT_BLOCKS: u64 = 5000;
+/// Maximum number of blocks allowed in an ethash snapshot.
+const MAX_SNAPSHOT_BLOCKS: u64 = 30000;
+
/// Ethash params.
#[derive(Debug, PartialEq)]
@@ -206,7 +209,7 @@ impl Engine for Arc {
}
}
- fn signing_network_id(&self, env_info: &EnvInfo) -> Option {
+ fn signing_chain_id(&self, env_info: &EnvInfo) -> Option {
if env_info.number >= self.params().eip155_transition {
Some(self.params().chain_id)
} else {
@@ -397,8 +400,8 @@ impl Engine for Arc {
}
let check_low_s = header.number() >= self.ethash_params.homestead_transition;
- let network_id = if header.number() >= self.params().eip155_transition { Some(self.params().chain_id) } else { None };
- t.verify_basic(check_low_s, network_id, false)?;
+ let chain_id = if header.number() >= self.params().eip155_transition { Some(self.params().chain_id) } else { None };
+ t.verify_basic(check_low_s, chain_id, false)?;
Ok(())
}
@@ -407,7 +410,7 @@ impl Engine for Arc {
}
fn snapshot_components(&self) -> Option> {
- Some(Box::new(::snapshot::PowSnapshot(SNAPSHOT_BLOCKS)))
+ Some(Box::new(::snapshot::PowSnapshot::new(SNAPSHOT_BLOCKS, MAX_SNAPSHOT_BLOCKS)))
}
}
diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs
index bd7cf28c1..8f2fb06f2 100644
--- a/ethcore/src/executive.rs
+++ b/ethcore/src/executive.rs
@@ -157,7 +157,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
pub fn transact_virtual(&'a mut self, t: &SignedTransaction, options: TransactOptions) -> Result {
let sender = t.sender();
let balance = self.state.balance(&sender)?;
- let needed_balance = t.value + t.gas * t.gas_price;
+ let needed_balance = t.value.saturating_add(t.gas.saturating_mul(t.gas_price));
if balance < needed_balance {
// give the sender a sufficient balance
self.state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty)?;
diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs
index a3c3c889d..3d71a5faf 100644
--- a/ethcore/src/json_tests/transaction.rs
+++ b/ethcore/src/json_tests/transaction.rs
@@ -36,25 +36,25 @@ fn do_json_test(json_data: &[u8]) -> Vec {
Some(x) if x < 3_000_000 => &homestead_schedule,
Some(_) => &metropolis_schedule
};
- let allow_network_id_of_one = number.map_or(false, |n| n >= 2_675_000);
+ let allow_chain_id_of_one = number.map_or(false, |n| n >= 2_675_000);
let allow_unsigned = number.map_or(false, |n| n >= 3_000_000);
let rlp: Vec = test.rlp.into();
let res = UntrustedRlp::new(&rlp)
.as_val()
.map_err(From::from)
- .and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_network_id_of_one, allow_unsigned));
+ .and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned));
fail_unless(test.transaction.is_none() == res.is_err(), "Validity different");
if let (Some(tx), Some(sender)) = (test.transaction, test.sender) {
let t = res.unwrap();
fail_unless(SignedTransaction::new(t.clone()).unwrap().sender() == sender.into(), "sender mismatch");
- let is_acceptable_network_id = match t.network_id() {
+ let is_acceptable_chain_id = match t.chain_id() {
None => true,
- Some(1) if allow_network_id_of_one => true,
+ Some(1) if allow_chain_id_of_one => true,
_ => false,
};
- fail_unless(is_acceptable_network_id, "Network ID unacceptable");
+ fail_unless(is_acceptable_chain_id, "Network ID unacceptable");
let data: Vec = tx.data.into();
fail_unless(t.data == data, "data mismatch");
fail_unless(t.gas_price == tx.gas_price.into(), "gas_price mismatch");
diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs
index 6c862ecda..15d44626b 100644
--- a/ethcore/src/lib.rs
+++ b/ethcore/src/lib.rs
@@ -101,6 +101,9 @@ extern crate num;
extern crate price_info;
extern crate rand;
extern crate rlp;
+
+#[macro_use]
+extern crate rlp_derive;
extern crate rustc_hex;
extern crate semver;
extern crate stats;
diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs
index 02463d929..0639c645f 100644
--- a/ethcore/src/miner/miner.rs
+++ b/ethcore/src/miner/miner.rs
@@ -1306,10 +1306,10 @@ mod tests {
}
fn transaction() -> SignedTransaction {
- transaction_with_network_id(2)
+ transaction_with_chain_id(2)
}
- fn transaction_with_network_id(id: u64) -> SignedTransaction {
+ fn transaction_with_chain_id(chain_id: u64) -> SignedTransaction {
let keypair = Random.generate().unwrap();
Transaction {
action: Action::Create,
@@ -1318,7 +1318,7 @@ mod tests {
gas: U256::from(100_000),
gas_price: U256::zero(),
nonce: U256::zero(),
- }.sign(keypair.secret(), Some(id))
+ }.sign(keypair.secret(), Some(chain_id))
}
#[test]
@@ -1399,14 +1399,14 @@ mod tests {
let client = generate_dummy_client(2);
- assert_eq!(miner.import_external_transactions(&*client, vec![transaction_with_network_id(spec.network_id()).into()]).pop().unwrap().unwrap(), TransactionImportResult::Current);
+ assert_eq!(miner.import_external_transactions(&*client, vec![transaction_with_chain_id(spec.chain_id()).into()]).pop().unwrap().unwrap(), TransactionImportResult::Current);
miner.update_sealing(&*client);
client.flush_queue();
assert!(miner.pending_block(0).is_none());
assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber);
- assert_eq!(miner.import_own_transaction(&*client, PendingTransaction::new(transaction_with_network_id(spec.network_id()).into(), None)).unwrap(), TransactionImportResult::Current);
+ assert_eq!(miner.import_own_transaction(&*client, PendingTransaction::new(transaction_with_chain_id(spec.chain_id()).into(), None)).unwrap(), TransactionImportResult::Current);
miner.update_sealing(&*client);
client.flush_queue();
diff --git a/ethcore/src/miner/stratum.rs b/ethcore/src/miner/stratum.rs
index e419247f0..0031bb715 100644
--- a/ethcore/src/miner/stratum.rs
+++ b/ethcore/src/miner/stratum.rs
@@ -32,7 +32,6 @@ use util::Mutex;
use miner::{self, Miner, MinerService};
use client::Client;
use block::IsBlock;
-use std::str::FromStr;
use rlp::encode;
/// Configures stratum server options.
@@ -60,7 +59,7 @@ impl SubmitPayload {
return Err(PayloadError::ArgumentsAmountUnexpected(payload.len()));
}
- let nonce = match H64::from_str(clean_0x(&payload[0])) {
+ let nonce = match clean_0x(&payload[0]).parse::() {
Ok(nonce) => nonce,
Err(e) => {
warn!(target: "stratum", "submit_work ({}): invalid nonce ({:?})", &payload[0], e);
@@ -68,7 +67,7 @@ impl SubmitPayload {
}
};
- let pow_hash = match H256::from_str(clean_0x(&payload[1])) {
+ let pow_hash = match clean_0x(&payload[1]).parse::() {
Ok(pow_hash) => pow_hash,
Err(e) => {
warn!(target: "stratum", "submit_work ({}): invalid hash ({:?})", &payload[1], e);
@@ -76,7 +75,7 @@ impl SubmitPayload {
}
};
- let mix_hash = match H256::from_str(clean_0x(&payload[2])) {
+ let mix_hash = match clean_0x(&payload[2]).parse::() {
Ok(mix_hash) => mix_hash,
Err(e) => {
warn!(target: "stratum", "submit_work ({}): invalid mix-hash ({:?})", &payload[2], e);
@@ -133,7 +132,7 @@ impl JobDispatcher for StratumJobDispatcher {
fn submit(&self, payload: Vec) -> Result<(), StratumServiceError> {
let payload = SubmitPayload::from_args(payload).map_err(|e|
- StratumServiceError::Dispatch(format!("{}", e))
+ StratumServiceError::Dispatch(e.to_string())
)?;
trace!(
@@ -144,14 +143,16 @@ impl JobDispatcher for StratumJobDispatcher {
payload.mix_hash,
);
- self.with_core_void(|client, miner| {
+ self.with_core_result(|client, miner| {
let seal = vec![encode(&payload.mix_hash).into_vec(), encode(&payload.nonce).into_vec()];
- if let Err(e) = miner.submit_seal(&*client, payload.pow_hash, seal) {
- warn!(target: "stratum", "submit_seal error: {:?}", e);
- };
- });
-
- Ok(())
+ match miner.submit_seal(&*client, payload.pow_hash, seal) {
+ Ok(_) => Ok(()),
+ Err(e) => {
+ warn!(target: "stratum", "submit_seal error: {:?}", e);
+ Err(StratumServiceError::Dispatch(e.to_string()))
+ }
+ }
+ })
}
}
@@ -181,8 +182,11 @@ impl StratumJobDispatcher {
self.client.upgrade().and_then(|client| self.miner.upgrade().and_then(|miner| (f)(client, miner)))
}
- fn with_core_void(&self, f: F) where F: Fn(Arc, Arc) {
- self.client.upgrade().map(|client| self.miner.upgrade().map(|miner| (f)(client, miner)));
+ fn with_core_result(&self, f: F) -> Result<(), StratumServiceError> where F: Fn(Arc, Arc) -> Result<(), StratumServiceError> {
+ match (self.client.upgrade(), self.miner.upgrade()) {
+ (Some(client), Some(miner)) => f(client, miner),
+ _ => Ok(()),
+ }
}
}
@@ -230,7 +234,7 @@ impl Stratum {
let dispatcher = Arc::new(StratumJobDispatcher::new(miner, client));
let stratum_svc = StratumService::start(
- &SocketAddr::new(IpAddr::from_str(&options.listen_addr)?, options.port),
+ &SocketAddr::new(options.listen_addr.parse::()?, options.port),
dispatcher.clone(),
options.secret.clone(),
)?;
diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs
index bbd2fffa5..4204b591d 100644
--- a/ethcore/src/pod_account.rs
+++ b/ethcore/src/pod_account.rs
@@ -16,6 +16,7 @@
use std::fmt;
use std::collections::BTreeMap;
+use itertools::Itertools;
use util::*;
use state::Account;
use ethjson;
diff --git a/ethcore/src/pod_state.rs b/ethcore/src/pod_state.rs
index 3e8d0bbfe..5a0265dc1 100644
--- a/ethcore/src/pod_state.rs
+++ b/ethcore/src/pod_state.rs
@@ -18,6 +18,7 @@
use std::fmt;
use std::collections::BTreeMap;
+use itertools::Itertools;
use util::*;
use pod_account::{self, PodAccount};
use types::state_diff::StateDiff;
diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs
index 4975203b7..2bf154fc4 100644
--- a/ethcore/src/snapshot/consensus/work.rs
+++ b/ethcore/src/snapshot/consensus/work.rs
@@ -37,11 +37,24 @@ use rand::OsRng;
/// Snapshot creation and restoration for PoW chains.
/// This includes blocks from the head of the chain as a
/// loose assurance that the chain is valid.
-///
-/// The field is the number of blocks from the head of the chain
-/// to include in the snapshot.
#[derive(Clone, Copy, PartialEq)]
-pub struct PowSnapshot(pub u64);
+pub struct PowSnapshot {
+ /// Number of blocks from the head of the chain
+ /// to include in the snapshot.
+ pub blocks: u64,
+ /// Number of to allow in the snapshot when restoring.
+ pub max_restore_blocks: u64,
+}
+
+impl PowSnapshot {
+ /// Create a new instance.
+ pub fn new(blocks: u64, max_restore_blocks: u64) -> PowSnapshot {
+ PowSnapshot {
+ blocks: blocks,
+ max_restore_blocks: max_restore_blocks,
+ }
+ }
+}
impl SnapshotComponents for PowSnapshot {
fn chunk_all(
@@ -57,7 +70,7 @@ impl SnapshotComponents for PowSnapshot {
current_hash: block_at,
writer: chunk_sink,
preferred_size: preferred_size,
- }.chunk_all(self.0)
+ }.chunk_all(self.blocks)
}
fn rebuilder(
@@ -66,7 +79,7 @@ impl SnapshotComponents for PowSnapshot {
db: Arc,
manifest: &ManifestData,
) -> Result, ::error::Error> {
- PowRebuilder::new(chain, db, manifest, self.0).map(|r| Box::new(r) as Box<_>)
+ PowRebuilder::new(chain, db, manifest, self.max_restore_blocks).map(|r| Box::new(r) as Box<_>)
}
fn min_supported_version(&self) -> u64 { ::snapshot::MIN_SUPPORTED_STATE_CHUNK_VERSION }
@@ -218,7 +231,7 @@ impl Rebuilder for PowRebuilder {
trace!(target: "snapshot", "restoring block chunk with {} blocks.", item_count - 3);
if self.fed_blocks + num_blocks > self.snapshot_blocks {
- return Err(Error::TooManyBlocks(self.snapshot_blocks, self.fed_blocks).into())
+ return Err(Error::TooManyBlocks(self.snapshot_blocks, self.fed_blocks + num_blocks).into())
}
// todo: assert here that these values are consistent with chunks being in order.
diff --git a/ethcore/src/snapshot/io.rs b/ethcore/src/snapshot/io.rs
index 8cb778117..f28adcf7f 100644
--- a/ethcore/src/snapshot/io.rs
+++ b/ethcore/src/snapshot/io.rs
@@ -27,7 +27,7 @@ use std::path::{Path, PathBuf};
use util::Bytes;
use util::hash::H256;
-use rlp::{self, Encodable, RlpStream, UntrustedRlp};
+use rlp::{RlpStream, UntrustedRlp};
use super::ManifestData;
@@ -49,24 +49,9 @@ pub trait SnapshotWriter {
}
// (hash, len, offset)
+#[derive(RlpEncodable, RlpDecodable)]
struct ChunkInfo(H256, u64, u64);
-impl Encodable for ChunkInfo {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(3);
- s.append(&self.0).append(&self.1).append(&self.2);
- }
-}
-
-impl rlp::Decodable for ChunkInfo {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let hash = rlp.val_at(0)?;
- let len = rlp.val_at(1)?;
- let off = rlp.val_at(2)?;
- Ok(ChunkInfo(hash, len, off))
- }
-}
-
/// A packed snapshot writer. This writes snapshots to a single concatenated file.
///
/// The file format is very simple and consists of three parts:
diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs
index a62dbaf10..7c44ec20a 100644
--- a/ethcore/src/snapshot/tests/proof_of_authority.rs
+++ b/ethcore/src/snapshot/tests/proof_of_authority.rs
@@ -130,7 +130,7 @@ fn make_chain(accounts: Arc, blocks_beyond: usize, transitions:
action: Action::Call(Address::new()),
value: 1.into(),
data: Vec::new(),
- }.sign(&*RICH_SECRET, client.signing_network_id());
+ }.sign(&*RICH_SECRET, client.signing_chain_id());
*nonce = *nonce + 1.into();
vec![transaction]
@@ -176,7 +176,7 @@ fn make_chain(accounts: Arc, blocks_beyond: usize, transitions:
action: Action::Call(addr),
value: 0.into(),
data: data,
- }.sign(&*RICH_SECRET, client.signing_network_id());
+ }.sign(&*RICH_SECRET, client.signing_chain_id());
pending.push(transaction);
diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/ethcore/src/snapshot/tests/proof_of_work.rs
index e7d0a0964..a6c0166f5 100644
--- a/ethcore/src/snapshot/tests/proof_of_work.rs
+++ b/ethcore/src/snapshot/tests/proof_of_work.rs
@@ -30,7 +30,7 @@ use util::kvdb::{self, KeyValueDB, DBTransaction};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
-const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot(30000);
+const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot { blocks: 30000, max_restore_blocks: 30000 };
fn chunk_and_restore(amount: u64) {
let mut canon_chain = ChainGenerator::default();
diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs
index 395f8ef9c..ba57a7f27 100644
--- a/ethcore/src/spec/spec.rs
+++ b/ethcore/src/spec/spec.rs
@@ -380,6 +380,9 @@ impl Spec {
/// Get the configured Network ID.
pub fn network_id(&self) -> u64 { self.params().network_id }
+ /// Get the chain ID used for signing.
+ pub fn chain_id(&self) -> u64 { self.params().chain_id }
+
/// Get the configured subprotocol name.
pub fn subprotocol_name(&self) -> String { self.params().subprotocol_name.clone() }
diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs
index 5d05e66f5..d8ba8313e 100644
--- a/ethcore/src/tests/helpers.rs
+++ b/ethcore/src/tests/helpers.rs
@@ -211,7 +211,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, ac
action: Action::Create,
data: vec![],
value: U256::zero(),
- }.sign(kp.secret(), Some(test_spec.network_id())), None).unwrap();
+ }.sign(kp.secret(), Some(test_spec.chain_id())), None).unwrap();
n += 1;
}
diff --git a/ethcore/src/trace/bloom.rs b/ethcore/src/trace/bloom.rs
index 561a83719..ed34d6505 100644
--- a/ethcore/src/trace/bloom.rs
+++ b/ethcore/src/trace/bloom.rs
@@ -1,10 +1,9 @@
use bloomchain::Bloom;
use bloomchain::group::{BloomGroup, GroupPosition};
-use rlp::*;
use basic_types::LogBloom;
/// Helper structure representing bloom of the trace.
-#[derive(Clone)]
+#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct BlockTracesBloom(LogBloom);
impl From for BlockTracesBloom {
@@ -28,7 +27,7 @@ impl Into for BlockTracesBloom {
}
/// Represents group of X consecutive blooms.
-#[derive(Clone)]
+#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct BlockTracesBloomGroup {
blooms: Vec,
}
@@ -59,34 +58,6 @@ impl Into for BlockTracesBloomGroup {
}
}
-impl Decodable for BlockTracesBloom {
- fn decode(rlp: &UntrustedRlp) -> Result {
- LogBloom::decode(rlp).map(BlockTracesBloom)
- }
-}
-
-impl Encodable for BlockTracesBloom {
- fn rlp_append(&self, s: &mut RlpStream) {
- Encodable::rlp_append(&self.0, s)
- }
-}
-
-impl Decodable for BlockTracesBloomGroup {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let blooms = rlp.as_list()?;
- let group = BlockTracesBloomGroup {
- blooms: blooms
- };
- Ok(group)
- }
-}
-
-impl Encodable for BlockTracesBloomGroup {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.append_list(&self.blooms);
- }
-}
-
/// Represents `BloomGroup` position in database.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct TraceGroupPosition {
diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs
index da304694d..8b65f1f4c 100644
--- a/ethcore/src/trace/types/flat.rs
+++ b/ethcore/src/trace/types/flat.rs
@@ -77,7 +77,7 @@ impl Decodable for FlatTrace {
}
/// Represents all traces produced by a single transaction.
-#[derive(Debug, PartialEq, Clone)]
+#[derive(Debug, PartialEq, Clone, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct FlatTransactionTraces(Vec);
impl From> for FlatTransactionTraces {
@@ -99,18 +99,6 @@ impl FlatTransactionTraces {
}
}
-impl Encodable for FlatTransactionTraces {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.append_list(&self.0);
- }
-}
-
-impl Decodable for FlatTransactionTraces {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(FlatTransactionTraces(rlp.as_list()?))
- }
-}
-
impl Into> for FlatTransactionTraces {
fn into(self) -> Vec {
self.0
@@ -118,7 +106,7 @@ impl Into> for FlatTransactionTraces {
}
/// Represents all traces produced by transactions in a single block.
-#[derive(Debug, PartialEq, Clone, Default)]
+#[derive(Debug, PartialEq, Clone, Default, RlpEncodableWrapper, RlpDecodableWrapper)]
pub struct FlatBlockTraces(Vec);
impl HeapSizeOf for FlatBlockTraces {
@@ -140,18 +128,6 @@ impl FlatBlockTraces {
}
}
-impl Encodable for FlatBlockTraces {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.append_list(&self.0);
- }
-}
-
-impl Decodable for FlatBlockTraces {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(FlatBlockTraces(rlp.as_list()?))
- }
-}
-
impl Into> for FlatBlockTraces {
fn into(self) -> Vec {
self.0
diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs
index 3863a935e..5fa0260c6 100644
--- a/ethcore/src/trace/types/trace.rs
+++ b/ethcore/src/trace/types/trace.rs
@@ -27,7 +27,7 @@ use evm::CallType;
use super::error::Error;
/// `Call` result.
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct CallResult {
/// Gas used by call.
@@ -36,27 +36,8 @@ pub struct CallResult {
pub output: Bytes,
}
-impl Encodable for CallResult {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(2);
- s.append(&self.gas_used);
- s.append(&self.output);
- }
-}
-
-impl Decodable for CallResult {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let res = CallResult {
- gas_used: rlp.val_at(0)?,
- output: rlp.val_at(1)?,
- };
-
- Ok(res)
- }
-}
-
/// `Create` result.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct CreateResult {
/// Gas used by create.
@@ -67,27 +48,6 @@ pub struct CreateResult {
pub address: Address,
}
-impl Encodable for CreateResult {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(3);
- s.append(&self.gas_used);
- s.append(&self.code);
- s.append(&self.address);
- }
-}
-
-impl Decodable for CreateResult {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let res = CreateResult {
- gas_used: rlp.val_at(0)?,
- code: rlp.val_at(1)?,
- address: rlp.val_at(2)?,
- };
-
- Ok(res)
- }
-}
-
impl CreateResult {
/// Returns bloom.
pub fn bloom(&self) -> LogBloom {
@@ -96,7 +56,7 @@ impl CreateResult {
}
/// Description of a _call_ action, either a `CALL` operation or a message transction.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Call {
/// The sending account.
@@ -126,33 +86,6 @@ impl From for Call {
}
}
-impl Encodable for Call {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(6);
- s.append(&self.from);
- s.append(&self.to);
- s.append(&self.value);
- s.append(&self.gas);
- s.append(&self.input);
- s.append(&self.call_type);
- }
-}
-
-impl Decodable for Call {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let res = Call {
- from: rlp.val_at(0)?,
- to: rlp.val_at(1)?,
- value: rlp.val_at(2)?,
- gas: rlp.val_at(3)?,
- input: rlp.val_at(4)?,
- call_type: rlp.val_at(5)?,
- };
-
- Ok(res)
- }
-}
-
impl Call {
/// Returns call action bloom.
/// The bloom contains from and to addresses.
@@ -163,7 +96,7 @@ impl Call {
}
/// Description of a _create_ action, either a `CREATE` operation or a create transction.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Create {
/// The address of the creator.
@@ -187,29 +120,6 @@ impl From for Create {
}
}
-impl Encodable for Create {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(4);
- s.append(&self.from);
- s.append(&self.value);
- s.append(&self.gas);
- s.append(&self.init);
- }
-}
-
-impl Decodable for Create {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let res = Create {
- from: rlp.val_at(0)?,
- value: rlp.val_at(1)?,
- gas: rlp.val_at(2)?,
- init: rlp.val_at(3)?,
- };
-
- Ok(res)
- }
-}
-
impl Create {
/// Returns bloom create action bloom.
/// The bloom contains only from address.
@@ -219,7 +129,7 @@ impl Create {
}
/// Suicide action.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Suicide {
/// Suicided address.
@@ -238,28 +148,6 @@ impl Suicide {
}
}
-impl Encodable for Suicide {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(3);
- s.append(&self.address);
- s.append(&self.refund_address);
- s.append(&self.balance);
- }
-}
-
-impl Decodable for Suicide {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let res = Suicide {
- address: rlp.val_at(0)?,
- refund_address: rlp.val_at(1)?,
- balance: rlp.val_at(2)?,
- };
-
- Ok(res)
- }
-}
-
-
/// Description of an action that we trace; will be either a call or a create.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
@@ -394,7 +282,7 @@ impl Res {
}
}
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A diff of some chunk of memory.
pub struct MemoryDiff {
@@ -404,24 +292,7 @@ pub struct MemoryDiff {
pub data: Bytes,
}
-impl Encodable for MemoryDiff {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(2);
- s.append(&self.offset);
- s.append(&self.data);
- }
-}
-
-impl Decodable for MemoryDiff {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(MemoryDiff {
- offset: rlp.val_at(0)?,
- data: rlp.val_at(1)?,
- })
- }
-}
-
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A diff of some storage value.
pub struct StorageDiff {
@@ -431,24 +302,7 @@ pub struct StorageDiff {
pub value: U256,
}
-impl Encodable for StorageDiff {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(2);
- s.append(&self.location);
- s.append(&self.value);
- }
-}
-
-impl Decodable for StorageDiff {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(StorageDiff {
- location: rlp.val_at(0)?,
- value: rlp.val_at(1)?,
- })
- }
-}
-
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of an executed VM operation.
pub struct VMExecutedOperation {
@@ -462,28 +316,7 @@ pub struct VMExecutedOperation {
pub store_diff: Option,
}
-impl Encodable for VMExecutedOperation {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(4);
- s.append(&self.gas_used);
- s.append_list(&self.stack_push);
- s.append(&self.mem_diff);
- s.append(&self.store_diff);
- }
-}
-
-impl Decodable for VMExecutedOperation {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(VMExecutedOperation {
- gas_used: rlp.val_at(0)?,
- stack_push: rlp.list_at(1)?,
- mem_diff: rlp.val_at(2)?,
- store_diff: rlp.val_at(3)?,
- })
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of the execution of a single VM operation.
pub struct VMOperation {
@@ -497,30 +330,7 @@ pub struct VMOperation {
pub executed: Option,
}
-impl Encodable for VMOperation {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(4);
- s.append(&self.pc);
- s.append(&self.instruction);
- s.append(&self.gas_cost);
- s.append(&self.executed);
- }
-}
-
-impl Decodable for VMOperation {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let res = VMOperation {
- pc: rlp.val_at(0)?,
- instruction: rlp.val_at(1)?,
- gas_cost: rlp.val_at(2)?,
- executed: rlp.val_at(3)?,
- };
-
- Ok(res)
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
#[cfg_attr(feature = "ipc", binary)]
/// A record of a full VM trace for a CALL/CREATE.
pub struct VMTrace {
@@ -534,26 +344,3 @@ pub struct VMTrace {
/// Thre is a 1:1 correspondance between these and a CALL/CREATE/CALLCODE/DELEGATECALL instruction.
pub subs: Vec,
}
-
-impl Encodable for VMTrace {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(4);
- s.append(&self.parent_step);
- s.append(&self.code);
- s.append_list(&self.operations);
- s.append_list(&self.subs);
- }
-}
-
-impl Decodable for VMTrace {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let res = VMTrace {
- parent_step: rlp.val_at(0)?,
- code: rlp.val_at(1)?,
- operations: rlp.list_at(2)?,
- subs: rlp.list_at(3)?,
- };
-
- Ok(res)
- }
-}
diff --git a/ethcore/src/transaction.rs b/ethcore/src/transaction.rs
index 6f5470028..0bd61dceb 100644
--- a/ethcore/src/transaction.rs
+++ b/ethcore/src/transaction.rs
@@ -56,6 +56,15 @@ impl Decodable for Action {
}
}
+impl Encodable for Action {
+ fn rlp_append(&self, s: &mut RlpStream) {
+ match *self {
+ Action::Create => s.append_internal(&""),
+ Action::Call(ref addr) => s.append_internal(addr),
+ };
+ }
+}
+
/// Transaction activation condition.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Condition {
@@ -85,18 +94,15 @@ pub struct Transaction {
impl Transaction {
/// Append object with a without signature into RLP stream
- pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option) {
- s.begin_list(if network_id.is_none() { 6 } else { 9 });
+ pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, chain_id: Option) {
+ s.begin_list(if chain_id.is_none() { 6 } else { 9 });
s.append(&self.nonce);
s.append(&self.gas_price);
s.append(&self.gas);
- match self.action {
- Action::Create => s.append_empty_data(),
- Action::Call(ref to) => s.append(to)
- };
+ s.append(&self.action);
s.append(&self.value);
s.append(&self.data);
- if let Some(n) = network_id {
+ if let Some(n) = chain_id {
s.append(&n);
s.append(&0u8);
s.append(&0u8);
@@ -157,27 +163,27 @@ impl From for UnverifiedTransaction {
impl Transaction {
/// The message hash of the transaction.
- pub fn hash(&self, network_id: Option) -> H256 {
+ pub fn hash(&self, chain_id: Option) -> H256 {
let mut stream = RlpStream::new();
- self.rlp_append_unsigned_transaction(&mut stream, network_id);
+ self.rlp_append_unsigned_transaction(&mut stream, chain_id);
stream.as_raw().sha3()
}
/// Signs the transaction as coming from `sender`.
- pub fn sign(self, secret: &Secret, network_id: Option) -> SignedTransaction {
- let sig = ::ethkey::sign(secret, &self.hash(network_id))
+ pub fn sign(self, secret: &Secret, chain_id: Option) -> SignedTransaction {
+ let sig = ::ethkey::sign(secret, &self.hash(chain_id))
.expect("data is valid and context has signing capabilities; qed");
- SignedTransaction::new(self.with_signature(sig, network_id))
+ SignedTransaction::new(self.with_signature(sig, chain_id))
.expect("secret is valid so it's recoverable")
}
/// Signs the transaction with signature.
- pub fn with_signature(self, sig: Signature, network_id: Option) -> UnverifiedTransaction {
+ pub fn with_signature(self, sig: Signature, chain_id: Option) -> UnverifiedTransaction {
UnverifiedTransaction {
unsigned: self,
r: sig.r().into(),
s: sig.s().into(),
- v: sig.v() as u64 + if let Some(n) = network_id { 35 + n * 2 } else { 27 },
+ v: sig.v() as u64 + if let Some(n) = chain_id { 35 + n * 2 } else { 27 },
hash: 0.into(),
}.compute_hash()
}
@@ -210,13 +216,13 @@ impl Transaction {
}
/// Add EIP-86 compatible empty signature.
- pub fn null_sign(self, network_id: u64) -> SignedTransaction {
+ pub fn null_sign(self, chain_id: u64) -> SignedTransaction {
SignedTransaction {
transaction: UnverifiedTransaction {
unsigned: self,
r: U256::zero(),
s: U256::zero(),
- v: network_id,
+ v: chain_id,
hash: 0.into(),
}.compute_hash(),
sender: UNSIGNED_SENDER,
@@ -244,7 +250,7 @@ pub struct UnverifiedTransaction {
/// Plain Transaction.
unsigned: Transaction,
/// The V field of the signature; the LS bit described which half of the curve our point falls
- /// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
+ /// in. The MS bits describe which chain this transaction is for. If 27/28, its for all chains.
v: u64,
/// The R field of the signature; helps describe the point on the curve.
r: U256,
@@ -308,10 +314,7 @@ impl UnverifiedTransaction {
s.append(&self.nonce);
s.append(&self.gas_price);
s.append(&self.gas);
- match self.action {
- Action::Create => s.append_empty_data(),
- Action::Call(ref to) => s.append(to)
- };
+ s.append(&self.action);
s.append(&self.value);
s.append(&self.data);
s.append(&self.v);
@@ -330,8 +333,8 @@ impl UnverifiedTransaction {
/// The `v` value that appears in the RLP.
pub fn original_v(&self) -> u64 { self.v }
- /// The network ID, or `None` if this is a global transaction.
- pub fn network_id(&self) -> Option {
+ /// The chain ID, or `None` if this is a global transaction.
+ pub fn chain_id(&self) -> Option {
match self.v {
v if self.is_unsigned() => Some(v),
v if v > 36 => Some((v - 35) / 2),
@@ -360,15 +363,15 @@ impl UnverifiedTransaction {
/// Recovers the public key of the sender.
pub fn recover_public(&self) -> Result {
- Ok(recover(&self.signature(), &self.unsigned.hash(self.network_id()))?)
+ Ok(recover(&self.signature(), &self.unsigned.hash(self.chain_id()))?)
}
/// Do basic validation, checking for valid signature and minimum gas,
// TODO: consider use in block validation.
#[cfg(test)]
#[cfg(feature = "json-tests")]
- pub fn validate(self, schedule: &Schedule, require_low: bool, allow_network_id_of_one: bool, allow_empty_signature: bool) -> Result {
- let chain_id = if allow_network_id_of_one { Some(1) } else { None };
+ pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool) -> Result {
+ let chain_id = if allow_chain_id_of_one { Some(1) } else { None };
self.verify_basic(require_low, chain_id, allow_empty_signature)?;
if !allow_empty_signature || !self.is_unsigned() {
self.recover_public()?;
@@ -388,10 +391,10 @@ impl UnverifiedTransaction {
if allow_empty_signature && self.is_unsigned() && !(self.gas_price.is_zero() && self.value.is_zero() && self.nonce.is_zero()) {
return Err(EthkeyError::InvalidSignature.into())
}
- match (self.network_id(), chain_id) {
+ match (self.chain_id(), chain_id) {
(None, _) => {},
(Some(n), Some(m)) if n == m => {},
- _ => return Err(TransactionError::InvalidNetworkId.into()),
+ _ => return Err(TransactionError::InvalidChainId.into()),
};
Ok(())
}
@@ -555,7 +558,7 @@ mod tests {
} else { panic!(); }
assert_eq!(t.value, U256::from(0x0au64));
assert_eq!(public_to_address(&t.recover_public().unwrap()), "0f65fe9276bc9a24ae7083ae28e2660ef72df99e".into());
- assert_eq!(t.network_id(), None);
+ assert_eq!(t.chain_id(), None);
}
#[test]
@@ -572,7 +575,7 @@ mod tests {
data: b"Hello!".to_vec()
}.sign(&key.secret(), None);
assert_eq!(Address::from(key.public().sha3()), t.sender());
- assert_eq!(t.network_id(), None);
+ assert_eq!(t.chain_id(), None);
}
#[test]
@@ -586,15 +589,15 @@ mod tests {
data: b"Hello!".to_vec()
}.fake_sign(Address::from(0x69));
assert_eq!(Address::from(0x69), t.sender());
- assert_eq!(t.network_id(), None);
+ assert_eq!(t.chain_id(), None);
let t = t.clone();
assert_eq!(Address::from(0x69), t.sender());
- assert_eq!(t.network_id(), None);
+ assert_eq!(t.chain_id(), None);
}
#[test]
- fn should_recover_from_network_specific_signing() {
+ fn should_recover_from_chain_specific_signing() {
use ethkey::{Random, Generator};
let key = Random.generate().unwrap();
let t = Transaction {
@@ -606,7 +609,7 @@ mod tests {
data: b"Hello!".to_vec()
}.sign(&key.secret(), Some(69));
assert_eq!(Address::from(key.public().sha3()), t.sender());
- assert_eq!(t.network_id(), Some(69));
+ assert_eq!(t.chain_id(), Some(69));
}
#[test]
@@ -617,7 +620,7 @@ mod tests {
let signed = decode(&FromHex::from_hex(tx_data).unwrap());
let signed = SignedTransaction::new(signed).unwrap();
assert_eq!(signed.sender(), address.into());
- flushln!("networkid: {:?}", signed.network_id());
+ flushln!("chainid: {:?}", signed.chain_id());
};
test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce");
diff --git a/ethcore/types/Cargo.toml b/ethcore/types/Cargo.toml
index 77f392bf6..82963f960 100644
--- a/ethcore/types/Cargo.toml
+++ b/ethcore/types/Cargo.toml
@@ -6,6 +6,7 @@ authors = ["Parity Technologies "]
[dependencies]
rlp = { path = "../../util/rlp" }
+rlp_derive = { path = "../../util/rlp_derive" }
ethcore-util = { path = "../../util" }
ethjson = { path = "../../json" }
bloomable = { path = "../../util/bloomable" }
diff --git a/ethcore/types/src/basic_account.rs b/ethcore/types/src/basic_account.rs
index c071040cf..f30872f6b 100644
--- a/ethcore/types/src/basic_account.rs
+++ b/ethcore/types/src/basic_account.rs
@@ -16,11 +16,10 @@
//! Basic account type -- the decoded RLP from the state trie.
-use rlp::*;
use util::{U256, H256};
/// Basic account type.
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct BasicAccount {
/// Nonce of the account.
pub nonce: U256,
@@ -31,24 +30,3 @@ pub struct BasicAccount {
/// Code hash of the account.
pub code_hash: H256,
}
-
-impl Encodable for BasicAccount {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(4)
- .append(&self.nonce)
- .append(&self.balance)
- .append(&self.storage_root)
- .append(&self.code_hash);
- }
-}
-
-impl Decodable for BasicAccount {
- fn decode(rlp: &UntrustedRlp) -> Result {
- Ok(BasicAccount {
- nonce: rlp.val_at(0)?,
- balance: rlp.val_at(1)?,
- storage_root: rlp.val_at(2)?,
- code_hash: rlp.val_at(3)?,
- })
- }
-}
diff --git a/ethcore/types/src/lib.rs b/ethcore/types/src/lib.rs
index 7650cf651..10a4ac71e 100644
--- a/ethcore/types/src/lib.rs
+++ b/ethcore/types/src/lib.rs
@@ -19,6 +19,8 @@
extern crate ethcore_util as util;
extern crate ethjson;
extern crate rlp;
+#[macro_use]
+extern crate rlp_derive;
extern crate bloomable;
#[cfg(test)]
diff --git a/ethcore/types/src/log_entry.rs b/ethcore/types/src/log_entry.rs
index f917a4dab..152b48a0e 100644
--- a/ethcore/types/src/log_entry.rs
+++ b/ethcore/types/src/log_entry.rs
@@ -19,7 +19,6 @@
use std::ops::Deref;
use util::{H256, Address, Bytes, HeapSizeOf, Hashable};
use bloomable::Bloomable;
-use rlp::*;
use {BlockNumber};
use ethjson;
@@ -27,7 +26,7 @@ use ethjson;
pub type LogBloom = ::util::H2048;
/// A record of execution for a `LOG` operation.
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
+#[derive(Default, Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct LogEntry {
/// The address of the contract executing at the point of the `LOG` operation.
pub address: Address,
@@ -37,26 +36,6 @@ pub struct LogEntry {
pub data: Bytes,
}
-impl Encodable for LogEntry {
- fn rlp_append(&self, s: &mut RlpStream) {
- s.begin_list(3);
- s.append(&self.address);
- s.append_list(&self.topics);
- s.append(&self.data);
- }
-}
-
-impl Decodable for LogEntry {
- fn decode(rlp: &UntrustedRlp) -> Result {
- let entry = LogEntry {
- address: rlp.val_at(0)?,
- topics: rlp.list_at(1)?,
- data: rlp.val_at(2)?,
- };
- Ok(entry)
- }
-}
-
impl HeapSizeOf for LogEntry {
fn heap_size_of_children(&self) -> usize {
self.topics.heap_size_of_children() + self.data.heap_size_of_children()
diff --git a/ethcore/wasm/src/env.rs b/ethcore/wasm/src/env.rs
index cb7462046..777016a1b 100644
--- a/ethcore/wasm/src/env.rs
+++ b/ethcore/wasm/src/env.rs
@@ -17,8 +17,9 @@
//! Wasm env module bindings
use parity_wasm::elements::ValueType::*;
-use parity_wasm::interpreter::UserFunctionDescriptor;
+use parity_wasm::interpreter::{self, UserFunctionDescriptor};
use parity_wasm::interpreter::UserFunctionDescriptor::*;
+use super::runtime::Runtime;
pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
Static(
@@ -81,63 +82,29 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
&[I32],
None,
),
- Static(
- "_abort",
- &[],
- None,
- ),
- Static(
- "abortOnCannotGrowMemory",
- &[I32; 0],
- Some(I32)
- ),
-
- /*
- THIS IS EXPERIMENTAL RUST-ONLY RUNTIME EXTERNS, THEY ARE SUBJECT TO CHANGE
-
- AVOID YOUR WASM CONTAINS ANY OF THESE OTHERWISE
- EITHER FACE THE NEED OF HARDFORK
- OR YOU CAN STUCK ON SPECIFIC RUST VERSION FOR WASM COMPILATION
- */
-
- Static(
- "_rust_begin_unwind",
- &[I32; 4],
- None,
- ),
Static(
"_emscripten_memcpy_big",
&[I32; 3],
Some(I32),
),
- Static(
- "___syscall6",
- &[I32; 2],
- Some(I32),
- ),
- Static(
- "___syscall140",
- &[I32; 2],
- Some(I32)
- ),
- Static(
- "___syscall146",
- &[I32; 2],
- Some(I32)
- ),
- Static(
- "___syscall54",
- &[I32; 2],
- Some(I32)
- ),
+
+ // TODO: Get rid of it also somehow?
Static(
"_llvm_trap",
&[I32; 0],
None
),
+
Static(
- "___setErrNo",
- &[I32; 1],
- None
+ "_llvm_bswap_i64",
+ &[I32; 2],
+ Some(I32)
),
];
+
+pub fn native_bindings<'a>(runtime: &'a mut Runtime) -> interpreter::UserFunctions<'a> {
+ interpreter::UserFunctions {
+ executor: runtime,
+ functions: ::std::borrow::Cow::from(SIGNATURES),
+ }
+}
\ No newline at end of file
diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs
index ec6e67405..3fec0f781 100644
--- a/ethcore/wasm/src/lib.rs
+++ b/ethcore/wasm/src/lib.rs
@@ -32,8 +32,6 @@ mod result;
mod tests;
mod env;
-use std::sync::Arc;
-
const DEFAULT_STACK_SPACE: u32 = 5 * 1024 * 1024;
use parity_wasm::{interpreter, elements};
@@ -89,6 +87,7 @@ impl vm::Vm for WasmInterpreter {
DEFAULT_STACK_SPACE,
params.gas.low_u64(),
RuntimeContext::new(params.address, params.sender),
+ &self.program,
);
let mut cursor = ::std::io::Cursor::new(&*code);
@@ -112,16 +111,8 @@ impl vm::Vm for WasmInterpreter {
)?;
{
- let execution_params = interpreter::ExecutionParams::with_external(
- "env".into(),
- Arc::new(
- interpreter::env_native_module(env_instance, native_bindings(&mut runtime))
- .map_err(|err| {
- // todo: prefer explicit panic here also?
- vm::Error::Wasm(format!("Error instantiating native bindings: {:?}", err))
- })?
- )
- ).add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32));
+ let execution_params = runtime.execution_params()
+ .add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32));
let module_instance = self.program.add_module("contract", contract_module, Some(&execution_params.externals))
.map_err(|err| {
@@ -158,13 +149,6 @@ impl vm::Vm for WasmInterpreter {
}
}
-fn native_bindings<'a>(runtime: &'a mut Runtime) -> interpreter::UserFunctions<'a> {
- interpreter::UserFunctions {
- executor: runtime,
- functions: ::std::borrow::Cow::from(env::SIGNATURES),
- }
-}
-
impl From for vm::Error {
fn from(err: runtime::Error) -> vm::Error {
vm::Error::Wasm(format!("WASM runtime-error: {:?}", err))
diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs
index a983c954f..e1def857e 100644
--- a/ethcore/wasm/src/runtime.rs
+++ b/ethcore/wasm/src/runtime.rs
@@ -72,24 +72,26 @@ impl RuntimeContext {
}
/// Runtime enviroment data for wasm contract execution
-pub struct Runtime<'a> {
+pub struct Runtime<'a, 'b> {
gas_counter: u64,
gas_limit: u64,
dynamic_top: u32,
ext: &'a mut vm::Ext,
memory: Arc,
context: RuntimeContext,
+ instance: &'b interpreter::ProgramInstance,
}
-impl<'a> Runtime<'a> {
+impl<'a, 'b> Runtime<'a, 'b> {
/// New runtime for wasm contract with specified params
- pub fn with_params<'b>(
- ext: &'b mut vm::Ext,
+ pub fn with_params<'c, 'd>(
+ ext: &'c mut vm::Ext,
memory: Arc,
stack_space: u32,
gas_limit: u64,
context: RuntimeContext,
- ) -> Runtime<'b> {
+ program_instance: &'d interpreter::ProgramInstance,
+ ) -> Runtime<'c, 'd> {
Runtime {
gas_counter: 0,
gas_limit: gas_limit,
@@ -97,6 +99,7 @@ impl<'a> Runtime<'a> {
memory: memory,
ext: ext,
context: context,
+ instance: program_instance,
}
}
@@ -449,9 +452,58 @@ impl<'a> Runtime<'a> {
Ok(Some(0i32.into()))
}
+
+ fn bswap_32(x: u32) -> u32 {
+ x >> 24 | x >> 8 & 0xff00 | x << 8 & 0xff0000 | x << 24
+ }
+
+ fn bitswap_i64(&mut self, context: interpreter::CallerContext)
+ -> Result