diff --git a/Cargo.lock b/Cargo.lock index 720b32f62..07423bfc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,6 @@ dependencies = [ "fdlimit 0.1.0", "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -175,6 +174,15 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cookie" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam" version = "0.2.9" @@ -296,7 +304,7 @@ dependencies = [ "ethstore 0.1.0", "evmjit 1.4.0", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -340,9 +348,9 @@ dependencies = [ "ethcore-rpc 1.5.0", "ethcore-util 1.5.0", "fetch 0.1.0", - "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc-http-server.git)", + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -503,9 +511,9 @@ dependencies = [ "ethstore 0.1.0", "ethsync 1.5.0", "fetch 0.1.0", - "json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc-http-server.git)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -526,7 +534,7 @@ dependencies = [ "ethcore-io 1.5.0", "ethcore-rpc 1.5.0", "ethcore-util 1.5.0", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-ui 1.4.0", @@ -545,8 +553,8 @@ dependencies = [ "ethcore-ipc-codegen 1.4.0", "ethcore-ipc-nano 1.4.0", "ethcore-util 1.5.0", - "json-tcp-server 0.1.0 (git+https://github.com/ethcore/json-tcp-server)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", @@ -686,7 +694,7 @@ name = "fetch" version = "0.1.0" dependencies = [ "https-fetch 0.1.0", - "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -748,27 +756,6 @@ dependencies = [ "rustls 0.1.2 (git+https://github.com/ctz/rustls)", ] -[[package]] -name = "hyper" -version = "0.9.4" -source = "git+https://github.com/ethcore/hyper#9e346c1d4bc30cd4142dea9d8a0b117d30858ca4" -dependencies = [ - "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rotor 0.6.3 (git+https://github.com/ethcore/rotor)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hyper" version = "0.9.10" @@ -789,6 +776,25 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper" +version = "0.10.0-a.0" +source = "git+https://github.com/ethcore/hyper#7d4f7fa0baddcb2b0c523f7c05855d67de94fe88" +dependencies = [ + "cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rotor 0.6.3 (git+https://github.com/ethcore/rotor)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "idna" version = "0.1.0" @@ -831,39 +837,10 @@ name = "itoa" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "json-ipc-server" -version = "0.2.4" -source = "git+https://github.com/ethcore/json-ipc-server.git#4642cd03ec1d23db89df80d22d5a88e7364ab885" -dependencies = [ - "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "json-tcp-server" -version = "0.1.0" -source = "git+https://github.com/ethcore/json-tcp-server#c2858522274ae56042472bb5d22845a1b85e5338" -dependencies = [ - "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "jsonrpc-core" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "4.0.0" +source = "git+https://github.com/ethcore/jsonrpc.git#20c7e55b84d7fd62732f062dc3058e1b71133e4a" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -875,14 +852,44 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "6.1.1" -source = "git+https://github.com/ethcore/jsonrpc-http-server.git#cd6d4cb37d672cc3057aecd0692876f9e85f3ba5" +source = "git+https://github.com/ethcore/jsonrpc.git#20c7e55b84d7fd62732f062dc3058e1b71133e4a" dependencies = [ - "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-ipc-server" +version = "0.2.4" +source = "git+https://github.com/ethcore/jsonrpc.git#20c7e55b84d7fd62732f062dc3058e1b71133e4a" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jsonrpc-tcp-server" +version = "0.1.0" +source = "git+https://github.com/ethcore/jsonrpc.git#20c7e55b84d7fd62732f062dc3058e1b71133e4a" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -1503,11 +1510,12 @@ dependencies = [ [[package]] name = "rotor" version = "0.6.3" -source = "git+https://github.com/ethcore/rotor#e63d45137b2eb66d1e085a7c6321a5db8b187576" +source = "git+https://github.com/ethcore/rotor#c1a2dd0046c5ea2517a5b637fca8ee2e77021e82" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", + "mio 0.6.1 (git+https://github.com/ethcore/mio)", "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2008,6 +2016,7 @@ dependencies = [ "checksum clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4fabf979ddf6419a313c1c0ada4a5b95cfd2049c56e8418d622d27b4b6ff32" "checksum clippy_lints 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "ce96ec05bfe018a0d5d43da115e54850ea2217981ff0f2e462780ab9d594651a" "checksum cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90266f45846f14a1e986c77d1e9c2626b8c342ed806fe60241ec38cc8697b245" +"checksum cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d53b80dde876f47f03cda35303e368a79b91c70b0d65ecba5fd5280944a08591" "checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc" "checksum ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)" = "" "checksum daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "271ec51b7e0bee92f0d04601422c73eb76ececf197026711c97ad25038a010cf" @@ -2025,17 +2034,17 @@ dependencies = [ "checksum heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "abb306abb8d398e053cfb1b3e7b72c2f580be048b85745c52652954f8ad1439c" "checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58" "checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae" +"checksum hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)" = "" "checksum hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "eb27e8a3e8f17ac43ffa41bbda9cf5ad3f9f13ef66fa4873409d4902310275f7" -"checksum hyper 0.9.4 (git+https://github.com/ethcore/hyper)" = "" "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" "checksum igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8c12b1795b8b168f577c45fa10379b3814dcb11b7ab702406001f0d63f40484" "checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c" "checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" -"checksum json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)" = "" -"checksum json-tcp-server 0.1.0 (git+https://github.com/ethcore/json-tcp-server)" = "" -"checksum jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5094610b07f28f3edaf3947b732dadb31dbba4941d4d0c1c7a8350208f4414" -"checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc-http-server.git)" = "" +"checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" diff --git a/Cargo.toml b/Cargo.toml index 3808cce95..e0e4df2e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ serde = "0.8.0" serde_json = "0.8.0" hyper = { version = "0.9", default-features = false } ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" } -json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } fdlimit = { path = "util/fdlimit" } ethcore = { path = "ethcore" } ethcore-util = { path = "util" } diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index 6be30884a..bbab8420e 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -12,8 +12,8 @@ build = "build.rs" rand = "0.3.14" log = "0.3" env_logger = "0.3" -jsonrpc-core = "3.0" -jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" } +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" } hyper = { default-features = false, git = "https://github.com/ethcore/hyper" } unicase = "1.3" url = "1.0" diff --git a/dapps/src/handlers/content.rs b/dapps/src/handlers/content.rs index 738a9a890..fde5fbcf0 100644 --- a/dapps/src/handlers/content.rs +++ b/dapps/src/handlers/content.rs @@ -16,7 +16,6 @@ //! Simple Content Handler -use std::io::Write; use hyper::{header, server, Decoder, Encoder, Next}; use hyper::net::HttpStream; use hyper::mime::Mime; diff --git a/dapps/src/handlers/mod.rs b/dapps/src/handlers/mod.rs index b575509a5..1299a9c12 100644 --- a/dapps/src/handlers/mod.rs +++ b/dapps/src/handlers/mod.rs @@ -58,7 +58,7 @@ pub fn extract_url(req: &server::Request) -> Option { _ => None, } }, - uri::RequestUri::AbsolutePath(ref path) => { + uri::RequestUri::AbsolutePath { ref path, .. } => { // Attempt to prepend the Host header (mandatory in HTTP/1.1) let url_string = match req.headers().get::() { Some(ref host) => { diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index 7c7ea0a86..9bb3be4a7 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -266,7 +266,11 @@ impl Server { #[cfg(test)] /// Returns address that this server is bound to. pub fn addr(&self) -> &SocketAddr { - self.server.as_ref().expect("server is always Some at the start; it's consumed only when object is dropped; qed").addr() + self.server.as_ref() + .expect("server is always Some at the start; it's consumed only when object is dropped; qed") + .addrs() + .first() + .expect("You cannot start the server without binding to at least one address; qed") } } diff --git a/dapps/src/page/handler.rs b/dapps/src/page/handler.rs index 74eabf917..1494a04c7 100644 --- a/dapps/src/page/handler.rs +++ b/dapps/src/page/handler.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::io::Write; use time::{self, Duration}; use hyper::header; @@ -126,7 +125,7 @@ impl PageHandler { impl server::Handler for PageHandler { fn on_request(&mut self, req: server::Request) -> Next { self.file = match *req.uri() { - RequestUri::AbsolutePath(ref path) => { + RequestUri::AbsolutePath { ref path, .. } => { self.app.file(&self.extract_path(path)) }, RequestUri::AbsoluteUri(ref url) => { diff --git a/dapps/src/rpc.rs b/dapps/src/rpc.rs index 625bfc269..c47777bee 100644 --- a/dapps/src/rpc.rs +++ b/dapps/src/rpc.rs @@ -16,13 +16,14 @@ use std::sync::{Arc, Mutex}; use hyper; -use jsonrpc_core::IoHandler; -use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin}; + +use jsonrpc_core::{IoHandler, ResponseHandler, Request, Response}; +use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin, RpcHandler}; use endpoint::{Endpoint, EndpointPath, Handler}; pub fn rpc(handler: Arc, panic_handler: Arc () + Send>>>>) -> Box { Box::new(RpcEndpoint { - handler: handler, + handler: Arc::new(RpcMiddleware::new(handler)), panic_handler: panic_handler, cors_domain: None, // NOTE [ToDr] We don't need to do any hosts validation here. It's already done in router. @@ -31,7 +32,7 @@ pub fn rpc(handler: Arc, panic_handler: Arc } struct RpcEndpoint { - handler: Arc, + handler: Arc, panic_handler: Arc () + Send>>>>, cors_domain: Option>, allowed_hosts: Option>, @@ -49,3 +50,86 @@ impl Endpoint for RpcEndpoint { )) } } + +const MIDDLEWARE_METHOD: &'static str = "eth_accounts"; + +struct RpcMiddleware { + handler: Arc, +} + +impl RpcMiddleware { + fn new(handler: Arc) -> Self { + RpcMiddleware { + handler: handler, + } + } + + /// Appends additional parameter for specific calls. + fn augment_request(&self, request: &mut Request, meta: Option) { + use jsonrpc_core::{Call, Params, to_value}; + + fn augment_call(call: &mut Call, meta: Option<&Meta>) { + match (call, meta) { + (&mut Call::MethodCall(ref mut method_call), Some(meta)) if &method_call.method == MIDDLEWARE_METHOD => { + let session = to_value(&meta.app_id); + + let params = match method_call.params { + Some(Params::Array(ref vec)) if vec.len() == 0 => Some(Params::Array(vec![session])), + // invalid params otherwise + _ => None, + }; + + method_call.params = params; + }, + _ => {} + } + } + + match *request { + Request::Single(ref mut call) => augment_call(call, meta.as_ref()), + Request::Batch(ref mut vec) => { + for mut call in vec { + augment_call(call, meta.as_ref()) + } + }, + } + } +} + +#[derive(Debug)] +struct Meta { + app_id: String, +} + +impl RpcHandler for RpcMiddleware { + type Metadata = Meta; + + fn read_metadata(&self, request: &hyper::server::Request) -> Option { + request.headers().get::() + .and_then(|referer| hyper::Url::parse(referer).ok()) + .and_then(|url| { + url.path_segments() + .and_then(|mut split| split.next()) + .map(|app_id| Meta { + app_id: app_id.to_owned(), + }) + }) + } + + fn handle_request(&self, request_str: &str, response_handler: H, meta: Option) where + H: ResponseHandler, Option> + 'static + { + let handler = IoHandler::convert_handler(response_handler); + let request = IoHandler::read_request(request_str); + trace!(target: "rpc", "Request metadata: {:?}", meta); + + match request { + Ok(mut request) => { + self.augment_request(&mut request, meta); + self.handler.request_handler().handle_request(request, handler, None) + }, + Err(error) => handler.send(Some(Response::from(error))), + } + } +} + diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index d509c7593..e8f4624b7 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit d509c75936ec6cbba683ee1916aa0bca436bc376 +Subproject commit e8f4624b7f1a15c63674eecf577c7ab76c3b16be diff --git a/ethcore/src/account_provider.rs b/ethcore/src/account_provider/mod.rs similarity index 80% rename from ethcore/src/account_provider.rs rename to ethcore/src/account_provider/mod.rs index 917ae8b8b..24548dda3 100644 --- a/ethcore/src/account_provider.rs +++ b/ethcore/src/account_provider/mod.rs @@ -16,9 +16,12 @@ //! Account management. -use std::{fs, fmt}; +mod stores; + +use self::stores::{AddressBook, DappsSettingsStore}; + +use std::fmt; use std::collections::HashMap; -use std::path::PathBuf; use std::time::{Instant, Duration}; use util::{Mutex, RwLock}; use ethstore::{SecretStore, Error as SSError, SafeAccount, EthStore}; @@ -91,84 +94,16 @@ impl KeyDirectory for NullDir { } } -/// Disk-backed map from Address to String. Uses JSON. -struct AddressBook { - path: PathBuf, - cache: HashMap, - transient: bool, -} - -impl AddressBook { - pub fn new(path: String) -> Self { - trace!(target: "addressbook", "new({})", path); - let mut path: PathBuf = path.into(); - path.push("address_book.json"); - trace!(target: "addressbook", "path={:?}", path); - let mut r = AddressBook { - path: path, - cache: HashMap::new(), - transient: false, - }; - r.revert(); - r - } - - pub fn transient() -> Self { - let mut book = AddressBook::new(Default::default()); - book.transient = true; - book - } - - pub fn get(&self) -> HashMap { - self.cache.clone() - } - - pub fn set_name(&mut self, a: Address, name: String) { - let mut x = self.cache.get(&a) - .cloned() - .unwrap_or_else(|| AccountMeta {name: Default::default(), meta: "{}".to_owned(), uuid: None}); - x.name = name; - self.cache.insert(a, x); - self.save(); - } - - pub fn set_meta(&mut self, a: Address, meta: String) { - let mut x = self.cache.get(&a) - .cloned() - .unwrap_or_else(|| AccountMeta {name: "Anonymous".to_owned(), meta: Default::default(), uuid: None}); - x.meta = meta; - self.cache.insert(a, x); - self.save(); - } - - fn revert(&mut self) { - if self.transient { return; } - trace!(target: "addressbook", "revert"); - let _ = fs::File::open(self.path.clone()) - .map_err(|e| trace!(target: "addressbook", "Couldn't open address book: {}", e)) - .and_then(|f| AccountMeta::read_address_map(&f) - .map_err(|e| warn!(target: "addressbook", "Couldn't read address book: {}", e)) - .and_then(|m| { self.cache = m; Ok(()) }) - ); - } - - fn save(&mut self) { - if self.transient { return; } - trace!(target: "addressbook", "save"); - let _ = fs::File::create(self.path.clone()) - .map_err(|e| warn!(target: "addressbook", "Couldn't open address book for writing: {}", e)) - .and_then(|mut f| AccountMeta::write_address_map(&self.cache, &mut f) - .map_err(|e| warn!(target: "addressbook", "Couldn't write to address book: {}", e)) - ); - } -} +/// Dapp identifier +pub type DappId = String; /// Account management. /// Responsible for unlocking accounts. pub struct AccountProvider { unlocked: Mutex>, sstore: Box, - address_book: Mutex, + address_book: RwLock, + dapps_settings: RwLock, } impl AccountProvider { @@ -176,7 +111,8 @@ impl AccountProvider { pub fn new(sstore: Box) -> Self { AccountProvider { unlocked: Mutex::new(HashMap::new()), - address_book: Mutex::new(AddressBook::new(sstore.local_path().into())), + address_book: RwLock::new(AddressBook::new(sstore.local_path().into())), + dapps_settings: RwLock::new(DappsSettingsStore::new(sstore.local_path().into())), sstore: sstore, } } @@ -185,7 +121,8 @@ impl AccountProvider { pub fn transient_provider() -> Self { AccountProvider { unlocked: Mutex::new(HashMap::new()), - address_book: Mutex::new(AddressBook::transient()), + address_book: RwLock::new(AddressBook::transient()), + dapps_settings: RwLock::new(DappsSettingsStore::transient()), sstore: Box::new(EthStore::open(Box::new(NullDir::default())) .expect("NullDir load always succeeds; qed")) } @@ -230,19 +167,31 @@ impl AccountProvider { Ok(accounts) } + /// Gets addresses visile for dapp. + pub fn dapps_addresses(&self, dapp: DappId) -> Result, Error> { + let accounts = self.dapps_settings.read().get(); + Ok(accounts.get(&dapp).map(|settings| settings.accounts.clone()).unwrap_or_else(Vec::new)) + } + + /// Sets addresses visile for dapp. + pub fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec
) -> Result<(), Error> { + self.dapps_settings.write().set_accounts(dapp, addresses); + Ok(()) + } + /// Returns each address along with metadata. pub fn addresses_info(&self) -> Result, Error> { - Ok(self.address_book.lock().get()) + Ok(self.address_book.read().get()) } /// Returns each address along with metadata. pub fn set_address_name(&self, account: Address, name: String) -> Result<(), Error> { - Ok(self.address_book.lock().set_name(account, name)) + Ok(self.address_book.write().set_name(account, name)) } /// Returns each address along with metadata. pub fn set_address_meta(&self, account: Address, meta: String) -> Result<(), Error> { - Ok(self.address_book.lock().set_meta(account, meta)) + Ok(self.address_book.write().set_meta(account, meta)) } /// Returns each account along with name and meta. @@ -379,23 +328,9 @@ impl AccountProvider { #[cfg(test)] mod tests { - use super::{AccountProvider, AddressBook, Unlock}; - use std::collections::HashMap; + use super::{AccountProvider, Unlock}; use std::time::Instant; - use ethjson::misc::AccountMeta; use ethstore::ethkey::{Generator, Random}; - use devtools::RandomTempPath; - - #[test] - fn should_save_and_reload_address_book() { - let temp = RandomTempPath::create_dir(); - let path = temp.as_str().to_owned(); - let mut b = AddressBook::new(path.clone()); - b.set_name(1.into(), "One".to_owned()); - b.set_meta(1.into(), "{1:1}".to_owned()); - let b = AddressBook::new(path); - assert_eq!(b.get(), hash_map![1.into() => AccountMeta{name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None}]); - } #[test] fn unlock_account_temp() { @@ -433,4 +368,17 @@ mod tests { ap.unlocked.lock().get_mut(&kp.address()).unwrap().unlock = Unlock::Timed(Instant::now()); assert!(ap.sign(kp.address(), None, Default::default()).is_err()); } + + #[test] + fn should_set_dapps_addresses() { + // given + let ap = AccountProvider::transient_provider(); + let app = "app1".to_owned(); + + // when + ap.set_dapps_addresses(app.clone(), vec![1.into(), 2.into()]).unwrap(); + + // then + assert_eq!(ap.dapps_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]); + } } diff --git a/ethcore/src/account_provider/stores.rs b/ethcore/src/account_provider/stores.rs new file mode 100644 index 000000000..cfc81f495 --- /dev/null +++ b/ethcore/src/account_provider/stores.rs @@ -0,0 +1,247 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Address Book and Dapps Settings Store + +use std::{fs, fmt, hash, ops}; +use std::collections::HashMap; +use std::path::PathBuf; + +use ethstore::ethkey::Address; +use ethjson::misc::{AccountMeta, DappsSettings as JsonSettings}; +use account_provider::DappId; + +/// Disk-backed map from Address to String. Uses JSON. +pub struct AddressBook { + cache: DiskMap, +} + +impl AddressBook { + /// Creates new address book at given directory. + pub fn new(path: String) -> Self { + let mut r = AddressBook { + cache: DiskMap::new(path, "address_book.json".into()) + }; + r.cache.revert(AccountMeta::read_address_map); + r + } + + /// Creates transient address book (no changes are saved to disk). + pub fn transient() -> Self { + AddressBook { + cache: DiskMap::transient() + } + } + + /// Get the address book. + pub fn get(&self) -> HashMap { + self.cache.clone() + } + + fn save(&self) { + self.cache.save(AccountMeta::write_address_map) + } + + /// Sets new name for given address. + pub fn set_name(&mut self, a: Address, name: String) { + { + let mut x = self.cache.entry(a) + .or_insert_with(|| AccountMeta {name: Default::default(), meta: "{}".to_owned(), uuid: None}); + x.name = name; + } + self.save(); + } + + /// Sets new meta for given address. + pub fn set_meta(&mut self, a: Address, meta: String) { + { + let mut x = self.cache.entry(a) + .or_insert_with(|| AccountMeta {name: "Anonymous".to_owned(), meta: Default::default(), uuid: None}); + x.meta = meta; + } + self.save(); + } +} + +/// Dapps user settings +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub struct DappsSettings { + /// A list of visible accounts + pub accounts: Vec
, +} + +impl From for DappsSettings { + fn from(s: JsonSettings) -> Self { + DappsSettings { + accounts: s.accounts.into_iter().map(Into::into).collect(), + } + } +} + +impl From for JsonSettings { + fn from(s: DappsSettings) -> Self { + JsonSettings { + accounts: s.accounts.into_iter().map(Into::into).collect(), + } + } +} + +/// Disk-backed map from DappId to Settings. Uses JSON. +pub struct DappsSettingsStore { + cache: DiskMap, +} + +impl DappsSettingsStore { + /// Creates new store at given directory path. + pub fn new(path: String) -> Self { + let mut r = DappsSettingsStore { + cache: DiskMap::new(path, "dapps_accounts.json".into()) + }; + r.cache.revert(JsonSettings::read_dapps_settings); + r + } + + /// Creates transient store (no changes are saved to disk). + pub fn transient() -> Self { + DappsSettingsStore { + cache: DiskMap::transient() + } + } + + /// Get copy of the dapps settings + pub fn get(&self) -> HashMap { + self.cache.clone() + } + + fn save(&self) { + self.cache.save(JsonSettings::write_dapps_settings) + } + + pub fn set_accounts(&mut self, id: DappId, accounts: Vec
) { + { + let mut settings = self.cache.entry(id).or_insert_with(DappsSettings::default); + settings.accounts = accounts; + } + self.save(); + } +} + +/// Disk-serializable HashMap +#[derive(Debug)] +struct DiskMap { + path: PathBuf, + cache: HashMap, + transient: bool, +} + +impl ops::Deref for DiskMap { + type Target = HashMap; + fn deref(&self) -> &Self::Target { + &self.cache + } +} + +impl ops::DerefMut for DiskMap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.cache + } +} + +impl DiskMap { + pub fn new(path: String, file_name: String) -> Self { + trace!(target: "diskmap", "new({})", path); + let mut path: PathBuf = path.into(); + path.push(file_name); + trace!(target: "diskmap", "path={:?}", path); + DiskMap { + path: path, + cache: HashMap::new(), + transient: false, + } + } + + pub fn transient() -> Self { + let mut map = DiskMap::new(Default::default(), "diskmap.json".into()); + map.transient = true; + map + } + + fn revert(&mut self, read: F) where + F: Fn(fs::File) -> Result, E>, + E: fmt::Display, + { + if self.transient { return; } + trace!(target: "diskmap", "revert {:?}", self.path); + let _ = fs::File::open(self.path.clone()) + .map_err(|e| trace!(target: "diskmap", "Couldn't open disk map: {}", e)) + .and_then(|f| read(f).map_err(|e| warn!(target: "diskmap", "Couldn't read disk map: {}", e))) + .and_then(|m| { + self.cache = m; + Ok(()) + }); + } + + fn save(&self, write: F) where + F: Fn(&HashMap, &mut fs::File) -> Result<(), E>, + E: fmt::Display, + { + if self.transient { return; } + trace!(target: "diskmap", "save {:?}", self.path); + let _ = fs::File::create(self.path.clone()) + .map_err(|e| warn!(target: "diskmap", "Couldn't open disk map for writing: {}", e)) + .and_then(|mut f| { + write(&self.cache, &mut f).map_err(|e| warn!(target: "diskmap", "Couldn't write to disk map: {}", e)) + }); + } +} + +#[cfg(test)] +mod tests { + use super::{AddressBook, DappsSettingsStore, DappsSettings}; + use std::collections::HashMap; + use ethjson::misc::AccountMeta; + use devtools::RandomTempPath; + + #[test] + fn should_save_and_reload_address_book() { + let temp = RandomTempPath::create_dir(); + let path = temp.as_str().to_owned(); + let mut b = AddressBook::new(path.clone()); + b.set_name(1.into(), "One".to_owned()); + b.set_meta(1.into(), "{1:1}".to_owned()); + let b = AddressBook::new(path); + assert_eq!(b.get(), hash_map![1.into() => AccountMeta{name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None}]); + } + + #[test] + fn should_save_and_reload_dapps_settings() { + // given + let temp = RandomTempPath::create_dir(); + let path = temp.as_str().to_owned(); + let mut b = DappsSettingsStore::new(path.clone()); + + // when + b.set_accounts("dappOne".into(), vec![1.into(), 2.into()]); + + // then + let b = DappsSettingsStore::new(path); + assert_eq!(b.get(), hash_map![ + "dappOne".into() => DappsSettings { + accounts: vec![1.into(), 2.into()], + } + ]); + } +} diff --git a/json/src/misc/account_meta.rs b/json/src/misc/account_meta.rs index 242b58a01..400f9b8df 100644 --- a/json/src/misc/account_meta.rs +++ b/json/src/misc/account_meta.rs @@ -51,7 +51,7 @@ impl AccountMeta { ) } - /// Write a hash map of Address -> AccountMeta. + /// Write a hash map of Address -> AccountMeta. pub fn write_address_map(m: &HashMap, writer: &mut W) -> Result<(), serde_json::Error> where W: Write { serde_json::to_writer(writer, &m.iter().map(|(a, m)| (a.clone().into(), m)).collect::>()) } diff --git a/json/src/misc/dapps_settings.rs b/json/src/misc/dapps_settings.rs new file mode 100644 index 000000000..893e7e93e --- /dev/null +++ b/json/src/misc/dapps_settings.rs @@ -0,0 +1,51 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Dapps settings de/serialization. + +use std::io; +use std::collections::HashMap; +use serde_json; +use hash; + +type DappId = String; + +/// Settings for specific dapp. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct DappsSettings { + /// A list of accounts this Dapp can see. + pub accounts: Vec, +} + +impl DappsSettings { + /// Read a hash map of DappId -> DappsSettings + pub fn read_dapps_settings(reader: R) -> Result, serde_json::Error> where + R: io::Read, + S: From + Clone, + { + serde_json::from_reader(reader).map(|ok: HashMap| + ok.into_iter().map(|(a, m)| (a.into(), m.into())).collect() + ) + } + + /// Write a hash map of DappId -> DappsSettings + pub fn write_dapps_settings(m: &HashMap, writer: &mut W) -> Result<(), serde_json::Error> where + W: io::Write, + S: Into + Clone, + { + serde_json::to_writer(writer, &m.iter().map(|(a, m)| (a.clone().into(), m.clone().into())).collect::>()) + } +} diff --git a/json/src/misc/mod.rs b/json/src/misc/mod.rs index 5db868d03..baab83d08 100644 --- a/json/src/misc/mod.rs +++ b/json/src/misc/mod.rs @@ -17,5 +17,7 @@ //! Misc deserialization. mod account_meta; +mod dapps_settings; +pub use self::dapps_settings::DappsSettings; pub use self::account_meta::AccountMeta; diff --git a/parity/main.rs b/parity/main.rs index 274d29de2..c125e87f6 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -44,8 +44,6 @@ extern crate serde_json; extern crate rlp; extern crate ethcore_hash_fetch as hash_fetch; -extern crate json_ipc_server as jsonipc; - extern crate ethcore_ipc_hypervisor as hypervisor; extern crate ethcore_rpc; diff --git a/parity/rpc.rs b/parity/rpc.rs index 59279eaea..52a5bcc0f 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -19,14 +19,12 @@ use std::sync::Arc; use std::net::SocketAddr; use std::io; use io::PanicHandler; -use ethcore_rpc::{RpcServerError, RpcServer as Server}; -use jsonipc; +use ethcore_rpc::{RpcServerError, RpcServer as Server, IpcServerError}; use rpc_apis; use rpc_apis::ApiSet; use helpers::parity_ipc_path; -pub use jsonipc::Server as IpcServer; -pub use ethcore_rpc::Server as HttpServer; +pub use ethcore_rpc::{IpcServer, Server as HttpServer}; #[derive(Debug, PartialEq)] pub struct HttpConfiguration { @@ -126,7 +124,7 @@ pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result Result { let server = try!(setup_rpc_server(apis, dependencies)); match server.start_ipc(addr) { - Err(jsonipc::Error::Io(io_error)) => Err(format!("RPC io error: {}", io_error)), + Err(IpcServerError::Io(io_error)) => Err(format!("RPC io error: {}", io_error)), Err(any_error) => Err(format!("Rpc error: {:?}", any_error)), Ok(server) => Ok(server) } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 8598372f8..dcdf68325 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -12,8 +12,9 @@ build = "build.rs" log = "0.3" serde = "0.8" serde_json = "0.8" -jsonrpc-core = "3.0" -jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" } +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" } ethcore-io = { path = "../util/io" } ethcore-util = { path = "../util" } ethcore = { path = "../ethcore" } @@ -30,7 +31,6 @@ rustc-serialize = "0.3" transient-hashmap = "0.1" serde_macros = { version = "0.8.0", optional = true } clippy = { version = "0.0.103", optional = true} -json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } ethcore-ipc = { path = "../ipc/rpc" } time = "0.1" diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 3b67ae7f0..e02a18509 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -32,7 +32,7 @@ extern crate ethcrypto as crypto; extern crate ethstore; extern crate ethsync; extern crate transient_hashmap; -extern crate json_ipc_server as ipc; +extern crate jsonrpc_ipc_server as ipc; extern crate ethcore_ipc; extern crate time; extern crate rlp; @@ -51,8 +51,9 @@ extern crate ethcore_devtools as devtools; use std::sync::Arc; use std::net::SocketAddr; use io::PanicHandler; -use self::jsonrpc_core::{IoHandler, IoDelegate}; +use jsonrpc_core::{IoHandler, IoDelegate}; +pub use ipc::{Server as IpcServer, Error as IpcServerError}; pub use jsonrpc_http_server::{ServerBuilder, Server, RpcServerError}; pub mod v1; pub use v1::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings}; @@ -66,7 +67,7 @@ pub trait Extendable { /// Http server. pub struct RpcServer { - handler: Arc, + handler: Arc, } impl Extendable for RpcServer { diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 5f1449e07..6b9f47de3 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -20,7 +20,6 @@ extern crate ethash; use std::io::{Write}; use std::process::{Command, Stdio}; -use std::collections::BTreeSet; use std::thread; use std::time::{Instant, Duration}; use std::sync::{Arc, Weak}; @@ -46,7 +45,7 @@ use self::ethash::SeedHashCompute; use v1::traits::Eth; use v1::types::{ RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, - Transaction, CallRequest, Index, Filter, Log, Receipt, Work, + Transaction, CallRequest, Index, Filter, Log, Receipt, Work, DappId, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256, }; use v1::helpers::{CallRequest as CRequest, errors, limit_logs}; @@ -335,15 +334,15 @@ impl Eth for EthClient where Ok(RpcU256::from(default_gas_price(&*client, &*miner))) } - fn accounts(&self) -> Result, Error> { + fn accounts(&self, id: Trailing) -> Result, Error> { try!(self.active()); - let store = take_weak!(self.accounts); - let accounts = try!(store.accounts().map_err(|e| errors::internal("Could not fetch accounts.", e))); - let addresses = try!(store.addresses_info().map_err(|e| errors::internal("Could not fetch accounts.", e))); + let dapp = id.0; - let set: BTreeSet
= accounts.into_iter().chain(addresses.keys().cloned()).collect(); - Ok(set.into_iter().map(Into::into).collect()) + let store = take_weak!(self.accounts); + let accounts = try!(store.dapps_addresses(dapp.into()).map_err(|e| errors::internal("Could not fetch accounts.", e))); + + Ok(accounts.into_iter().map(Into::into).collect()) } fn block_number(&self) -> Result { diff --git a/rpc/src/v1/impls/parity_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs index 3d91bf08a..ea927de4e 100644 --- a/rpc/src/v1/impls/parity_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -25,7 +25,7 @@ use ethcore::client::MiningBlockChainClient; use jsonrpc_core::{Value, Error, to_value}; use v1::traits::ParityAccounts; -use v1::types::{H160 as RpcH160, H256 as RpcH256}; +use v1::types::{H160 as RpcH160, H256 as RpcH256, DappId}; use v1::helpers::errors; /// Account management (personal) rpc implementation. @@ -152,6 +152,15 @@ impl ParityAccounts for ParityAccountsClient where C: MiningBlock Ok(false) } + fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec) -> Result { + let store = take_weak!(self.accounts); + let addresses = addresses.into_iter().map(Into::into).collect(); + + store.set_dapps_addresses(dapp.into(), addresses) + .map_err(|e| errors::account("Couldn't set dapps addresses.", e)) + .map(|_| true) + } + fn import_geth_accounts(&self, addresses: Vec) -> Result, Error> { let store = take_weak!(self.accounts); diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 2f5131f32..7894fa111 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -30,7 +30,7 @@ use devtools::RandomTempPath; use util::Hashable; use io::IoChannel; use util::{U256, H256, Uint, Address}; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use ethjson::blockchain::BlockChain; use v1::impls::{EthClient, SigningUnsafeClient}; diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 861bb5234..2b5942af6 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -31,7 +31,7 @@ use ethcore::transaction::{Transaction, Action}; use ethcore::miner::{ExternalMiner, MinerService}; use ethsync::SyncState; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService}; @@ -354,18 +354,17 @@ fn rpc_eth_gas_price() { #[test] fn rpc_eth_accounts() { let tester = EthTester::default(); - let address = tester.accounts_provider.new_account("").unwrap(); - let address2 = Address::default(); - - tester.accounts_provider.set_address_name(address2, "Test Account".into()).unwrap(); + let _address = tester.accounts_provider.new_account("").unwrap(); + // even with some account it should return empty list (no dapp detected) let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() - + &format!("0x{:?}", address2) - + r#"",""# - + &format!("0x{:?}", address) - + r#""],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#; + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); + // when we add visible address it should return that. + tester.accounts_provider.set_dapps_addresses("app1".into(), vec![10.into()]).unwrap(); + let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": ["app1"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#; assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/net.rs b/rpc/src/v1/tests/mocked/net.rs index 0a5eb43e7..37ef84fca 100644 --- a/rpc/src/v1/tests/mocked/net.rs +++ b/rpc/src/v1/tests/mocked/net.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::sync::Arc; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{Net, NetClient}; use v1::tests::helpers::{Config, TestSyncProvider}; diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 5226e2f96..9b4daaccd 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -23,7 +23,7 @@ use ethcore::client::{TestBlockChainClient}; use ethcore::miner::LocalTransactionStatus; use ethstore::ethkey::{Generator, Random}; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{Parity, ParityClient}; use v1::helpers::{SignerService, NetworkSettings}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; diff --git a/rpc/src/v1/tests/mocked/parity_accounts.rs b/rpc/src/v1/tests/mocked/parity_accounts.rs index d2dfe3544..3b1899f38 100644 --- a/rpc/src/v1/tests/mocked/parity_accounts.rs +++ b/rpc/src/v1/tests/mocked/parity_accounts.rs @@ -19,7 +19,7 @@ use std::sync::Arc; use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{ParityAccounts, ParityAccountsClient}; struct ParityAccountsTester { @@ -116,6 +116,21 @@ fn should_be_able_to_set_meta() { assert_eq!(res, Some(response)); } +#[test] +fn rpc_parity_set_dapps_accounts() { + // given + let tester = setup(); + assert_eq!(tester.accounts.dapps_addresses("app1".into()).unwrap(), vec![]); + + // when + let request = r#"{"jsonrpc": "2.0", "method": "parity_setDappsAddresses","params":["app1",["0x000000000000000000000000000000000000000a"]], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); + + // then + assert_eq!(tester.accounts.dapps_addresses("app1".into()).unwrap(), vec![10.into()]); +} + #[test] fn should_be_able_to_kill_account() { let tester = setup(); @@ -137,4 +152,3 @@ fn should_be_able_to_kill_account() { let accounts = tester.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 0); } - diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index 3202374a7..01f33e251 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -23,7 +23,7 @@ use ethcore::miner::MinerService; use ethcore::client::TestBlockChainClient; use ethsync::ManageNetwork; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{ParitySet, ParitySetClient}; use v1::tests::helpers::{TestMinerService, TestFetch}; use super::manage_network::TestManageNetwork; diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 301abf1f9..ea4973ee4 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -16,7 +16,7 @@ use std::sync::Arc; use std::str::FromStr; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use util::{U256, Uint, Address}; use ethcore::account_provider::AccountProvider; use v1::{PersonalClient, Personal}; diff --git a/rpc/src/v1/tests/mocked/rpc.rs b/rpc/src/v1/tests/mocked/rpc.rs index b2c340d94..44406f4e3 100644 --- a/rpc/src/v1/tests/mocked/rpc.rs +++ b/rpc/src/v1/tests/mocked/rpc.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::collections::BTreeMap; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{Rpc, RpcClient}; diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index 447c809cd..ea89e5876 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -23,7 +23,7 @@ use ethcore::client::TestBlockChainClient; use ethcore::transaction::{Transaction, Action}; use rlp::encode; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{SignerClient, Signer}; use v1::tests::helpers::TestMinerService; use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload}; diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index 7431bc45e..629fbe707 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -15,10 +15,10 @@ // along with Parity. If not, see . use std::str::FromStr; -use std::sync::Arc; +use std::sync::{mpsc, Arc}; use rlp; -use jsonrpc_core::{IoHandler, Success}; +use jsonrpc_core::{IoHandler, Success, GenericIoHandler}; use v1::impls::SigningQueueClient; use v1::traits::{EthSigning, ParitySigning, Parity}; use v1::helpers::{SignerService, SigningQueue}; @@ -87,13 +87,16 @@ fn should_add_sign_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","id":1}"#; // then - let async_result = tester.io.handle_request(&request).unwrap(); + let (tx, rx) = mpsc::channel(); + tester.io.handle_request(&request, move |response| { + tx.send(response).unwrap(); + }); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Signature(0.into()))); - assert!(async_result.on_result(move |res| { - assert_eq!(res, response.to_owned()); - })); + + let res = rx.try_recv().unwrap(); + assert_eq!(res, Some(response.to_owned())); } #[test] @@ -227,13 +230,16 @@ fn should_add_transaction_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#; // then - let async_result = tester.io.handle_request(&request).unwrap(); + let (tx, rx) = mpsc::channel(); + tester.io.handle_request(&request, move |response| { + tx.send(response).unwrap(); + }); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SendTransaction(0.into()))); - assert!(async_result.on_result(move |res| { - assert_eq!(res, response.to_owned()); - })); + + let res = rx.try_recv().unwrap(); + assert_eq!(res, Some(response.to_owned())); } #[test] @@ -289,14 +295,17 @@ fn should_add_sign_transaction_to_the_queue() { r#"}},"id":1}"#; // then + let (tx, rx) = mpsc::channel(); tester.miner.last_nonces.write().insert(address.clone(), U256::zero()); - let async_result = tester.io.handle_request(&request).unwrap(); + tester.io.handle_request(&request, move |response| { + tx.send(response).unwrap(); + }); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into()))); - assert!(async_result.on_result(move |res| { - assert_eq!(res, response.to_owned()); - })); + + let res = rx.try_recv().unwrap(); + assert_eq!(res, Some(response.to_owned())); } #[test] @@ -387,11 +396,14 @@ fn should_add_decryption_to_the_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0102","id":1}"#; // then - let async_result = tester.io.handle_request(&request).unwrap(); + let (tx, rx) = mpsc::channel(); + tester.io.handle_request(&request, move |response| { + tx.send(response).unwrap(); + }); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Decrypt(vec![0x1, 0x2].into()))); - assert!(async_result.on_result(move |res| { - assert_eq!(res, response.to_owned()); - })); + + let res = rx.try_recv().unwrap(); + assert_eq!(res, Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/web3.rs b/rpc/src/v1/tests/mocked/web3.rs index b9f80b0a8..c3bd79110 100644 --- a/rpc/src/v1/tests/mocked/web3.rs +++ b/rpc/src/v1/tests/mocked/web3.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use util::version; use v1::{Web3, Web3Client}; diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 6308be324..64a87c175 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -17,7 +17,7 @@ //! Eth rpc interface. use jsonrpc_core::Error; -use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index}; +use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index, DappId}; use v1::types::{Log, Receipt, SyncStatus, Transaction, Work}; use v1::types::{H64, H160, H256, U256}; @@ -52,7 +52,7 @@ build_rpc_trait! { /// Returns accounts list. #[rpc(name = "eth_accounts")] - fn accounts(&self) -> Result, Error>; + fn accounts(&self, Trailing) -> Result, Error>; /// Returns highest block number. #[rpc(name = "eth_blockNumber")] diff --git a/rpc/src/v1/traits/parity_accounts.rs b/rpc/src/v1/traits/parity_accounts.rs index 29706d0b2..f72802959 100644 --- a/rpc/src/v1/traits/parity_accounts.rs +++ b/rpc/src/v1/traits/parity_accounts.rs @@ -19,7 +19,7 @@ use std::collections::BTreeMap; use jsonrpc_core::{Value, Error}; use v1::helpers::auto_args::Wrap; -use v1::types::{H160, H256}; +use v1::types::{H160, H256, DappId}; build_rpc_trait! { /// Personal Parity rpc interface. @@ -66,10 +66,14 @@ build_rpc_trait! { #[rpc(name = "parity_setAccountMeta")] fn set_account_meta(&self, H160, String) -> Result; - /// Returns accounts information. + /// Sets account visibility #[rpc(name = "parity_setAccountVisiblity")] fn set_account_visibility(&self, H160, H256, bool) -> Result; + /// Sets accounts exposed for particular dapp. + #[rpc(name = "parity_setDappsAddresses")] + fn set_dapps_addresses(&self, DappId, Vec) -> Result; + /// Imports a number of Geth accounts, with the list provided as the argument. #[rpc(name = "parity_importGethAccounts")] fn import_geth_accounts(&self, Vec) -> Result, Error>; diff --git a/rpc/src/v1/types/dapp_id.rs b/rpc/src/v1/types/dapp_id.rs new file mode 100644 index 000000000..04aa80e3a --- /dev/null +++ b/rpc/src/v1/types/dapp_id.rs @@ -0,0 +1,60 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Dapp Id type + +/// Dapplication Internal Id +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct DappId(pub String); + +impl Into for DappId { + fn into(self) -> String { + self.0 + } +} + +#[cfg(test)] +mod tests { + + use serde_json; + use super::DappId; + + #[test] + fn should_serialize_dapp_id() { + // given + let id = DappId("testapp".into()); + + // when + let res = serde_json::to_string(&id).unwrap(); + + // then + assert_eq!(res, r#""testapp""#); + } + + #[test] + fn should_deserialize_dapp_id() { + // given + let id = r#""testapp""#; + + // when + let res: DappId = serde_json::from_str(id).unwrap(); + + // then + assert_eq!(res, DappId("testapp".into())); + } + + +} diff --git a/rpc/src/v1/types/mod.rs.in b/rpc/src/v1/types/mod.rs.in index 55e8fd27b..364fa53d3 100644 --- a/rpc/src/v1/types/mod.rs.in +++ b/rpc/src/v1/types/mod.rs.in @@ -19,6 +19,7 @@ mod block; mod block_number; mod call_request; mod confirmations; +mod dapp_id; mod filter; mod hash; mod index; @@ -39,6 +40,7 @@ pub use self::block::{RichBlock, Block, BlockTransactions}; pub use self::block_number::BlockNumber; pub use self::call_request::CallRequest; pub use self::confirmations::{ConfirmationPayload, ConfirmationRequest, ConfirmationResponse, TransactionModification, SignRequest, DecryptRequest, Either}; +pub use self::dapp_id::DappId; pub use self::filter::{Filter, FilterChanges}; pub use self::hash::{H64, H160, H256, H512, H520, H2048}; pub use self::index::Index; diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 4b56ec474..78fda12be 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -12,7 +12,7 @@ rustc_version = "0.1" [dependencies] rand = "0.3.14" -jsonrpc-core = "3.0" +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } log = "0.3" env_logger = "0.3" parity-dapps-glue = { version = "1.4", optional = true } diff --git a/signer/src/ws_server/session.rs b/signer/src/ws_server/session.rs index 13d253587..deb791b54 100644 --- a/signer/src/ws_server/session.rs +++ b/signer/src/ws_server/session.rs @@ -21,8 +21,8 @@ use authcode_store::AuthCodes; use std::path::{PathBuf, Path}; use std::sync::Arc; use std::str::FromStr; -use jsonrpc_core::IoHandler; -use util::{H256, Mutex, version}; +use jsonrpc_core::{IoHandler, GenericIoHandler}; +use util::{H256, version}; #[cfg(feature = "parity-ui")] mod ui { @@ -130,7 +130,7 @@ fn add_headers(mut response: ws::Response, mime: &str) -> ws::Response { } pub struct Session { - out: Arc>, + out: ws::Sender, skip_origin_validation: bool, self_origin: String, authcodes_path: PathBuf, @@ -208,15 +208,15 @@ impl ws::Handler for Session { fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> { let req = try!(msg.as_text()); - if let Some(async) = self.handler.handle_request(req) { - let out = self.out.clone(); - async.on_result(move |result| { - let res = out.lock().send(result); + let out = self.out.clone(); + self.handler.handle_request(req, move |response| { + if let Some(result) = response { + let res = out.send(result); if let Err(e) = res { warn!(target: "signer", "Error while sending response: {:?}", e); } - }); - } + } + }); Ok(()) } } @@ -246,7 +246,7 @@ impl ws::Factory for Factory { fn connection_made(&mut self, sender: ws::Sender) -> Self::Handler { Session { - out: Arc::new(Mutex::new(sender)), + out: sender, handler: self.handler.clone(), skip_origin_validation: self.skip_origin_validation, self_origin: self.self_origin.clone(), diff --git a/stratum/Cargo.toml b/stratum/Cargo.toml index d300106aa..28f5208dd 100644 --- a/stratum/Cargo.toml +++ b/stratum/Cargo.toml @@ -11,8 +11,8 @@ ethcore-ipc-codegen = { path = "../ipc/codegen" } [dependencies] log = "0.3" -json-tcp-server = { git = "https://github.com/ethcore/json-tcp-server" } -jsonrpc-core = "3.0" +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-tcp-server = { git = "https://github.com/ethcore/jsonrpc.git" } mio = { git = "https://github.com/ethcore/mio", branch = "v0.5.x" } ethcore-util = { path = "../util" } ethcore-devtools = { path = "../devtools" } diff --git a/stratum/src/lib.rs b/stratum/src/lib.rs index ecec535c2..45d8a3639 100644 --- a/stratum/src/lib.rs +++ b/stratum/src/lib.rs @@ -16,7 +16,7 @@ //! Stratum protocol implementation for parity ethereum/bitcoin clients -extern crate json_tcp_server; +extern crate jsonrpc_tcp_server; extern crate jsonrpc_core; #[macro_use] extern crate log; extern crate ethcore_util as util; @@ -44,7 +44,7 @@ pub use traits::{ RemoteWorkHandler, RemoteJobDispatcher, }; -use json_tcp_server::Server as JsonRpcServer; +use jsonrpc_tcp_server::Server as JsonRpcServer; use jsonrpc_core::{IoHandler, Params, IoDelegate, to_value, from_params}; use std::sync::Arc; @@ -72,7 +72,7 @@ impl Stratum { addr: &SocketAddr, dispatcher: Arc, secret: Option, - ) -> Result, json_tcp_server::Error> { + ) -> Result, jsonrpc_tcp_server::Error> { let handler = Arc::new(IoHandler::new()); let server = try!(JsonRpcServer::new(addr, &handler)); let stratum = Arc::new(Stratum {