From 41da1a0a79b552687e48c0ee65d3ed5e984d01e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 11 Jan 2017 20:02:27 +0100 Subject: [PATCH] New jsonrpc-core with futures and metadata support (#3859) * Bumping serde & serde_json * Super-initial usage of new jsonrpc * Single event loop for jsonrpc * Metadata * Supporting metadata extraction for eth_accounts * Fixing Cargo.lock * Removing uneccessary clones * Fixing unused import * Unused import * Fixing test --- Cargo.lock | 202 ++++++++++----------- Cargo.toml | 15 +- dapps/src/lib.rs | 98 ++++------ dapps/src/rpc.rs | 99 ++-------- dapps/src/tests/helpers/mod.rs | 76 +++++--- parity/dapps.rs | 20 +- parity/main.rs | 1 + parity/rpc.rs | 29 +-- parity/rpc_apis.rs | 54 +++--- parity/run.rs | 6 +- parity/signer.rs | 9 +- rpc/Cargo.toml | 11 +- rpc/rpctest/Cargo.toml | 2 +- rpc/src/lib.rs | 95 ++++------ rpc/src/v1/impls/eth.rs | 57 +++--- rpc/src/v1/impls/parity_set.rs | 41 ++--- rpc/src/v1/impls/signing.rs | 50 +++-- rpc/src/v1/impls/signing_unsafe.rs | 22 ++- rpc/src/v1/impls/traces.rs | 2 - rpc/src/v1/metadata.rs | 50 +++++ rpc/src/v1/mod.rs | 2 + rpc/src/v1/tests/eth.rs | 22 +-- rpc/src/v1/tests/mocked/eth.rs | 19 +- rpc/src/v1/tests/mocked/net.rs | 14 +- rpc/src/v1/tests/mocked/parity.rs | 10 +- rpc/src/v1/tests/mocked/parity_accounts.rs | 6 +- rpc/src/v1/tests/mocked/parity_set.rs | 44 ++--- rpc/src/v1/tests/mocked/personal.rs | 6 +- rpc/src/v1/tests/mocked/rpc.rs | 10 +- rpc/src/v1/tests/mocked/signer.rs | 6 +- rpc/src/v1/tests/mocked/signing.rs | 43 ++--- rpc/src/v1/tests/mocked/traces.rs | 6 +- rpc/src/v1/tests/mocked/web3.rs | 14 +- rpc/src/v1/traits/eth.rs | 13 +- rpc/src/v1/traits/eth_signing.rs | 9 +- rpc/src/v1/traits/parity_set.rs | 4 +- rpc/src/v1/traits/parity_signing.rs | 4 +- signer/src/lib.rs | 10 +- signer/src/tests/mod.rs | 34 +++- signer/src/ws_server/mod.rs | 23 +-- signer/src/ws_server/session.rs | 26 +-- stratum/Cargo.toml | 1 + stratum/src/lib.rs | 49 +++-- util/fetch/src/client.rs | 12 +- util/reactor/src/lib.rs | 20 ++ 45 files changed, 705 insertions(+), 641 deletions(-) create mode 100644 rpc/src/v1/metadata.rs diff --git a/Cargo.lock b/Cargo.lock index 664a2b85554..27a5e0a51f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,7 @@ dependencies = [ "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 5.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)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -44,7 +45,7 @@ dependencies = [ "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -100,14 +101,6 @@ dependencies = [ "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "aster" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bigint" version = "1.0.0" @@ -329,8 +322,8 @@ dependencies = [ "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -413,8 +406,8 @@ dependencies = [ "fetch 0.1.0", "futures 0.1.6 (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)", - "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-http-server 7.0.0 (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)", @@ -426,8 +419,8 @@ dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (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)", @@ -582,20 +575,19 @@ dependencies = [ "ethsync 1.6.0", "fetch 0.1.0", "futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", - "jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-ipc-server 1.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-macros 0.2.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", "parity-updater 1.6.0", - "rand 0.3.14 (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)", "semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -610,7 +602,7 @@ dependencies = [ "ethcore-io 1.6.0", "ethcore-rpc 1.6.0", "ethcore-util 1.6.0", - "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-core 5.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.6.0", @@ -629,8 +621,9 @@ dependencies = [ "ethcore-ipc-codegen 1.6.0", "ethcore-ipc-nano 1.6.0", "ethcore-util 1.6.0", - "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)", + "jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-macros 0.2.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-tcp-server 1.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 (git+https://github.com/ethcore/mio?branch=v0.5.x)", @@ -691,8 +684,8 @@ dependencies = [ "ethcore-util 1.6.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -724,8 +717,8 @@ dependencies = [ "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -950,63 +943,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" -version = "4.0.0" -source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" +version = "5.0.0" +source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3" dependencies = [ + "futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-http-server" -version = "6.1.1" -source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" +version = "7.0.0" +source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3" dependencies = [ + "futures 0.1.6 (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)", + "jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 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)", ] [[package]] name = "jsonrpc-ipc-server" -version = "0.2.4" -source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" +version = "1.0.0" +source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3" 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)", + "jsonrpc-core 5.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)", + "rand 0.3.14 (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-macros" -version = "0.1.0" -source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" +version = "0.2.0" +source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3" dependencies = [ - "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "serde 0.8.19 (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#33262d626a294a00c20435dec331058ba65e224a" +version = "1.0.0" +source = "git+https://github.com/ethcore/jsonrpc.git#2187ebc32f67620b000afb03a43a3c2b1020abb3" 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)", + "jsonrpc-core 5.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)", + "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1470,13 +1469,13 @@ dependencies = [ "ethcore-signer 1.6.0", "ethcore-util 1.6.0", "futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-core 5.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)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.5.3 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)", @@ -1637,15 +1636,6 @@ dependencies = [ "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "quasi" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quasi_codegen" version = "0.11.0" @@ -1656,17 +1646,6 @@ dependencies = [ "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "quasi_codegen" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quick-error" version = "1.1.0" @@ -1677,6 +1656,11 @@ name = "quine-mc_cluskey" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "quote" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rand" version = "0.3.14" @@ -1721,7 +1705,7 @@ dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1910,29 +1894,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_codegen" -version = "0.8.4" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen_internals 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_codegen_internals" -version = "0.7.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "0.8.1" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2030,6 +2012,15 @@ name = "strsim" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "syn" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syntex" version = "0.33.0" @@ -2040,29 +2031,29 @@ dependencies = [ [[package]] name = "syntex" -version = "0.42.2" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_errors" -version = "0.42.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_pos" -version = "0.42.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2083,15 +2074,15 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.42.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2366,7 +2357,6 @@ dependencies = [ "checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4" "checksum arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "16e3bdb2f54b3ace0285975d59a97cf8ed3855294b2b6bc651fcf22a9c352975" "checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a" -"checksum aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df293303e8a52e1df7984ac1415e195f5fcbf51e4bb7bda54557861a3954a08" "checksum bigint 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2311bcd71b281e142a095311c22509f0d6bcd87b3000d7dbaa810929b9d6f6ae" "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" @@ -2414,11 +2404,11 @@ dependencies = [ "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 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-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" -"checksum jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-ipc-server 1.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-macros 0.2.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-tcp-server 1.0.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" @@ -2480,11 +2470,10 @@ dependencies = [ "checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5" "checksum primal-sieve 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7aa73fd87e5984a00bdb4c1b14d3d5d6d0bad01b2caaaf924c16ab7260ac946c" "checksum quasi 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b26543b563704e7d87f3ec7cfafb713010a905c5f1b155a8ab66863af43ca578" -"checksum quasi 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb7eaef226a434a570fa336bc99502c4f5878208c1ebdd83b2d0bc37b1b1c34c" "checksum quasi_codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0881d9a45d5f9ebe4a7e77742f8c604f3658c212baf8dd711a692dd000bc648c" -"checksum quasi_codegen 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62e90381b315dfd00bfe6efbfeeec9f03a6d66159c3a5c8411b6c550d24b08fd" "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 rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5" "checksum rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "655df67c314c30fa3055a365eae276eb88aa4f3413a352a1ab32c1320eda41ea" "checksum regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)" = "b4329b8928a284580a1c63ec9d846b12f6d3472317243ff7077aff11f23f2b29" @@ -2508,9 +2497,9 @@ dependencies = [ "checksum semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5" "checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9" "checksum serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)" = "58a19c0871c298847e6b68318484685cd51fa5478c0c905095647540031356e5" -"checksum serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e422ae53d7933f59c6ff57e7b5870b5c9094b1f473f78ec33d89f8a692c3ec02" -"checksum serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f877e2781ed0a323295d1c9f0e26556117b5a11489fc47b1848dfb98b3173d21" -"checksum serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e10f8a9d94b06cf5d3bef66475f04c8ff90950f1be7004c357ff9472ccbaebc" +"checksum serde_codegen 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ce29a6ae259579707650ec292199b5fed2c0b8e2a4bdc994452d24d1bcf2242a" +"checksum serde_codegen_internals 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "59933a62554548c690d2673c5164f0c4a46be7c5731edfd94b0ecb1048940732" +"checksum serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7d3c184d35801fb8b32b46a7d58d57dbcc150b0eb2b46a1eb79645e8ecfd5b" "checksum serde_urlencoded 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53d4ebaa8d1d4f90d1b63dfca81ccd98ac20e1e479dbae393cbaf60f6fecd8d8" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d" @@ -2525,12 +2514,13 @@ dependencies = [ "checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf" "checksum stable-heap 0.1.0 (git+https://github.com/carllerche/stable-heap?rev=3c5cd1ca47)" = "" "checksum strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4d73a2c36a4d095ed1a6df5cbeac159863173447f7a82b3f4757426844ab825" +"checksum syn 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94e7d81ecd16d39f16193af05b8d5a0111b9d8d2f3f78f31760f327a247da777" "checksum syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393b6dd0889df2b064beeea954cfda6bc2571604ac460deeae0fed55a53988af" -"checksum syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a30b08a6b383a22e5f6edc127d169670d48f905bb00ca79a00ea3e442ebe317" -"checksum syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04c48f32867b6114449155b2a82114b86d4b09e1bddb21c47ff104ab9172b646" -"checksum syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd49988e52451813c61fecbe9abb5cfd4e1b7bb6cdbb980a6fbcbab859171a6" +"checksum syntex 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd253b0d7d787723a33384d426f0ebec7f8edccfaeb2022d0177162bb134da0" +"checksum syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84822a1178204a191239ad844599f8c85c128cf9f4173397def4eb46b55b0aa1" +"checksum syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a43abded5057c75bac8555e46ec913ce502efb418267b1ab8e9783897470c7db" "checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e" -"checksum syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7628a0506e8f9666fdabb5f265d0059b059edac9a3f810bda077abb5d826bd8d" +"checksum syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef781e4b60f03431f1b5b59843546ce60ae029a787770cf8e0969ac1fd063a5" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" diff --git a/Cargo.toml b/Cargo.toml index 8026662d13b..359ec77b5da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,14 +26,13 @@ lazy_static = "0.2" regex = "0.1" isatty = "0.1" toml = "0.2" -serde = "0.8.0" -serde_json = "0.8.0" +serde = "0.8" +serde_json = "0.8" app_dirs = "1.1.1" +fdlimit = "0.1" hyper = { version = "0.9", default-features = false } ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" } -fdlimit = "0.1" -clippy = { version = "0.0.103", optional = true} -rlp = { path = "util/rlp" } +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } ethsync = { path = "sync" } ethcore = { path = "ethcore" } ethcore-util = { path = "util" } @@ -44,15 +43,17 @@ ethcore-signer = { path = "signer" } ethcore-ipc = { path = "ipc/rpc" } ethcore-ipc-nano = { path = "ipc/nano" } ethcore-ipc-hypervisor = { path = "ipc/hypervisor" } +ethcore-light = { path = "ethcore/light" } ethcore-logger = { path = "logger" } ethcore-stratum = { path = "stratum" } -ethcore-dapps = { path = "dapps", optional = true } +rlp = { path = "util/rlp" } rpc-cli = { path = "rpc_cli" } parity-rpc-client = { path = "rpc_client" } -ethcore-light = { path = "ethcore/light" } parity-hash-fetch = { path = "hash-fetch" } parity-updater = { path = "updater" } parity-reactor = { path = "util/reactor" } +ethcore-dapps = { path = "dapps", optional = true } +clippy = { version = "0.0.103", optional = true} [target.'cfg(windows)'.dependencies] winapi = "0.2" diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index 64ee0c3410a..55bc67ff3ec 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -15,30 +15,6 @@ // along with Parity. If not, see . //! Ethcore Webapplications for Parity -//! ``` -//! extern crate jsonrpc_core; -//! extern crate ethcore_dapps; -//! -//! use std::sync::Arc; -//! use jsonrpc_core::IoHandler; -//! use ethcore_dapps::*; -//! -//! struct SayHello; -//! impl MethodCommand for SayHello { -//! fn execute(&self, _params: Params) -> Result { -//! Ok(Value::String("hello".to_string())) -//! } -//! } -//! -//! fn main() { -//! let io = IoHandler::new(); -//! io.add_method("say_hello", SayHello); -//! let _server = Server::start_unsecure_http( -//! &"127.0.0.1:3030".parse().unwrap(), -//! Arc::new(io) -//! ); -//! } -//! ``` //! #![warn(missing_docs)] #![cfg_attr(feature="nightly", plugin(clippy))] @@ -93,11 +69,11 @@ use std::sync::{Arc, Mutex}; use std::net::SocketAddr; use std::collections::HashMap; -use hash_fetch::urlhint::ContractClient; +use ethcore_rpc::Metadata; use fetch::{Fetch, Client as FetchClient}; -use jsonrpc_core::{IoHandler, IoDelegate}; +use hash_fetch::urlhint::ContractClient; +use jsonrpc_core::reactor::RpcHandler; use router::auth::{Authorization, NoAuth, HttpBasicAuth}; -use ethcore_rpc::Extendable; use parity_reactor::Remote; use self::apps::{HOME_PAGE, DAPPS_DOMAIN}; @@ -126,32 +102,26 @@ impl WebProxyTokens for F where F: Fn(String) -> bool + Send + Sync { pub struct ServerBuilder { dapps_path: PathBuf, extra_dapps: Vec, - handler: Arc, registrar: Arc, sync_status: Arc, web_proxy_tokens: Arc, signer_address: Option<(String, u16)>, + allowed_hosts: Option>, remote: Remote, fetch: Option, } -impl Extendable for ServerBuilder { - fn add_delegate(&self, delegate: IoDelegate) { - self.handler.add_delegate(delegate); - } -} - impl ServerBuilder { /// Construct new dapps server pub fn new>(dapps_path: P, registrar: Arc, remote: Remote) -> Self { ServerBuilder { dapps_path: dapps_path.as_ref().to_owned(), extra_dapps: vec![], - handler: Arc::new(IoHandler::new()), registrar: registrar, sync_status: Arc::new(|| false), web_proxy_tokens: Arc::new(|_| false), signer_address: None, + allowed_hosts: Some(vec![]), remote: remote, fetch: None, } @@ -164,11 +134,11 @@ impl ServerBuilder { ServerBuilder { dapps_path: self.dapps_path, extra_dapps: vec![], - handler: self.handler, registrar: self.registrar, sync_status: self.sync_status, web_proxy_tokens: self.web_proxy_tokens, signer_address: self.signer_address, + allowed_hosts: self.allowed_hosts, remote: self.remote, fetch: Some(fetch), } @@ -192,6 +162,14 @@ impl ServerBuilder { self } + /// Change allowed hosts. + /// `None` - All hosts are allowed + /// `Some(whitelist)` - Allow only whitelisted hosts (+ listen address) + pub fn allowed_hosts(mut self, allowed_hosts: Option>) -> Self { + self.allowed_hosts = allowed_hosts; + self + } + /// Change extra dapps paths (apart from `dapps_path`) pub fn extra_dapps>(mut self, extra_dapps: &[P]) -> Self { self.extra_dapps = extra_dapps.iter().map(|p| p.as_ref().to_owned()).collect(); @@ -200,39 +178,41 @@ impl ServerBuilder { /// Asynchronously start server with no authentication, /// returns result with `Server` handle on success or an error. - pub fn start_unsecured_http(self, addr: &SocketAddr, hosts: Option>) -> Result { + pub fn start_unsecured_http(self, addr: &SocketAddr, handler: RpcHandler) -> Result { + let fetch = self.fetch_client()?; Server::start_http( addr, - hosts, + self.allowed_hosts, NoAuth, - self.handler.clone(), - self.dapps_path.clone(), - self.extra_dapps.clone(), - self.signer_address.clone(), - self.registrar.clone(), - self.sync_status.clone(), - self.web_proxy_tokens.clone(), - self.remote.clone(), - self.fetch_client()?, + handler, + self.dapps_path, + self.extra_dapps, + self.signer_address, + self.registrar, + self.sync_status, + self.web_proxy_tokens, + self.remote, + fetch, ) } /// Asynchronously start server with `HTTP Basic Authentication`, /// return result with `Server` handle on success or an error. - pub fn start_basic_auth_http(self, addr: &SocketAddr, hosts: Option>, username: &str, password: &str) -> Result { + pub fn start_basic_auth_http(self, addr: &SocketAddr, username: &str, password: &str, handler: RpcHandler) -> Result { + let fetch = self.fetch_client()?; Server::start_http( addr, - hosts, + self.allowed_hosts, HttpBasicAuth::single_user(username, password), - self.handler.clone(), - self.dapps_path.clone(), - self.extra_dapps.clone(), - self.signer_address.clone(), - self.registrar.clone(), - self.sync_status.clone(), - self.web_proxy_tokens.clone(), - self.remote.clone(), - self.fetch_client()?, + handler, + self.dapps_path, + self.extra_dapps, + self.signer_address, + self.registrar, + self.sync_status, + self.web_proxy_tokens, + self.remote, + fetch, ) } @@ -281,7 +261,7 @@ impl Server { addr: &SocketAddr, hosts: Option>, authorization: A, - handler: Arc, + handler: RpcHandler, dapps_path: PathBuf, extra_dapps: Vec, signer_address: Option<(String, u16)>, diff --git a/dapps/src/rpc.rs b/dapps/src/rpc.rs index 1abae3b490a..03bd3b34ea3 100644 --- a/dapps/src/rpc.rs +++ b/dapps/src/rpc.rs @@ -17,13 +17,15 @@ use std::sync::{Arc, Mutex}; use hyper; -use jsonrpc_core::{IoHandler, ResponseHandler, Request, Response}; -use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin, RpcHandler}; +use ethcore_rpc::{Metadata, Origin}; +use jsonrpc_core::reactor::RpcHandler; +use jsonrpc_http_server::{Rpc, ServerHandler, PanicHandler, AccessControlAllowOrigin, HttpMetaExtractor}; use endpoint::{Endpoint, EndpointPath, Handler}; -pub fn rpc(handler: Arc, panic_handler: Arc () + Send>>>>) -> Box { +pub fn rpc(handler: RpcHandler, panic_handler: Arc () + Send>>>>) -> Box { Box::new(RpcEndpoint { - handler: Arc::new(RpcMiddleware::new(handler)), + handler: handler, + meta_extractor: Arc::new(MetadataExtractor), 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. @@ -32,7 +34,8 @@ pub fn rpc(handler: Arc, panic_handler: Arc } struct RpcEndpoint { - handler: Arc, + handler: RpcHandler, + meta_extractor: Arc>, panic_handler: Arc () + Send>>>>, cors_domain: Option>, allowed_hosts: Option>, @@ -42,7 +45,7 @@ impl Endpoint for RpcEndpoint { fn to_async_handler(&self, _path: EndpointPath, control: hyper::Control) -> Box { let panic_handler = PanicHandler { handler: self.panic_handler.clone() }; Box::new(ServerHandler::new( - self.handler.clone(), + Rpc::new(self.handler.clone(), self.meta_extractor.clone()), self.cors_domain.clone(), self.allowed_hosts.clone(), panic_handler, @@ -51,85 +54,19 @@ impl Endpoint for RpcEndpoint { } } -struct RpcMiddleware { - handler: Arc, - methods: Vec, -} - -impl RpcMiddleware { - fn new(handler: Arc) -> Self { - RpcMiddleware { - handler: handler, - methods: vec!["eth_accounts".into(), "parity_accountsInfo".into()], - } - } - - /// 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>, methods: &Vec) { - match (call, meta) { - (&mut Call::MethodCall(ref mut method_call), Some(meta)) if methods.contains(&method_call.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(), &self.methods), - Request::Batch(ref mut vec) => { - for mut call in vec { - augment_call(call, meta.as_ref(), &self.methods) - } - }, - } - } -} - -#[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::() +struct MetadataExtractor; +impl HttpMetaExtractor for MetadataExtractor { + fn read_metadata(&self, request: &hyper::server::Request) -> Metadata { + let dapp_id = 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))), + .map(|app_id| app_id.to_owned()) + }); + Metadata { + dapp_id: dapp_id, + origin: Origin::Dapps, } } } - diff --git a/dapps/src/tests/helpers/mod.rs b/dapps/src/tests/helpers/mod.rs index 5cc367fccf5..02a4598303e 100644 --- a/dapps/src/tests/helpers/mod.rs +++ b/dapps/src/tests/helpers/mod.rs @@ -16,8 +16,11 @@ use std::env; use std::str; +use std::ops::Deref; use std::sync::Arc; use env_logger::LogBuilder; +use jsonrpc_core::MetaIoHandler; +use jsonrpc_core::reactor::RpcEventLoop; use ServerBuilder; use Server; @@ -42,7 +45,20 @@ fn init_logger() { } } -pub fn init_server(hosts: Option>, process: F, remote: Remote) -> (Server, Arc) where +pub struct ServerLoop { + pub server: Server, + pub event_loop: RpcEventLoop, +} + +impl Deref for ServerLoop { + type Target = Server; + + fn deref(&self) -> &Self::Target { + &self.server + } +} + +pub fn init_server(process: F, remote: Remote) -> (ServerLoop, Arc) where F: FnOnce(ServerBuilder) -> ServerBuilder, B: Fetch, { @@ -50,60 +66,76 @@ pub fn init_server(hosts: Option>, process: F, remote: Remote) let registrar = Arc::new(FakeRegistrar::new()); let mut dapps_path = env::temp_dir(); dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading"); + + // TODO [ToDr] When https://github.com/ethcore/jsonrpc/issues/26 is resolved + // this additional EventLoop wouldn't be needed, we should be able to re-use remote. + let event_loop = RpcEventLoop::spawn(); + let handler = event_loop.handler(Arc::new(MetaIoHandler::default())); let server = process(ServerBuilder::new( &dapps_path, registrar.clone(), remote, )) .signer_address(Some(("127.0.0.1".into(), SIGNER_PORT))) - .start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), hosts).unwrap(); + .start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), handler).unwrap(); ( - server, + ServerLoop { server: server, event_loop: event_loop }, registrar, ) } -pub fn serve_with_auth(user: &str, pass: &str) -> Server { +pub fn serve_with_auth(user: &str, pass: &str) -> ServerLoop { init_logger(); let registrar = Arc::new(FakeRegistrar::new()); let mut dapps_path = env::temp_dir(); dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading"); - ServerBuilder::new(&dapps_path, registrar.clone(), Remote::new_sync()) + + let event_loop = RpcEventLoop::spawn(); + let handler = event_loop.handler(Arc::new(MetaIoHandler::default())); + let server = ServerBuilder::new(&dapps_path, registrar, Remote::new(event_loop.remote())) .signer_address(Some(("127.0.0.1".into(), SIGNER_PORT))) - .start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), None, user, pass).unwrap() + .allowed_hosts(None) + .start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), user, pass, handler).unwrap(); + ServerLoop { + server: server, + event_loop: event_loop, + } } -pub fn serve_hosts(hosts: Option>) -> Server { - init_server(hosts, |builder| builder, Remote::new_sync()).0 +pub fn serve_hosts(hosts: Option>) -> ServerLoop { + init_server(|builder| builder.allowed_hosts(hosts), Remote::new_sync()).0 } -pub fn serve_with_registrar() -> (Server, Arc) { - init_server(None, |builder| builder, Remote::new_sync()) +pub fn serve_with_registrar() -> (ServerLoop, Arc) { + init_server(|builder| builder.allowed_hosts(None), Remote::new_sync()) } -pub fn serve_with_registrar_and_sync() -> (Server, Arc) { - init_server(None, |builder| { - builder.sync_status(Arc::new(|| true)) +pub fn serve_with_registrar_and_sync() -> (ServerLoop, Arc) { + init_server(|builder| { + builder + .sync_status(Arc::new(|| true)) + .allowed_hosts(None) }, Remote::new_sync()) } -pub fn serve_with_registrar_and_fetch() -> (Server, FakeFetch, Arc) { +pub fn serve_with_registrar_and_fetch() -> (ServerLoop, FakeFetch, Arc) { serve_with_registrar_and_fetch_and_threads(false) } -pub fn serve_with_registrar_and_fetch_and_threads(multi_threaded: bool) -> (Server, FakeFetch, Arc) { +pub fn serve_with_registrar_and_fetch_and_threads(multi_threaded: bool) -> (ServerLoop, FakeFetch, Arc) { let fetch = FakeFetch::default(); let f = fetch.clone(); - let (server, reg) = init_server(None, move |builder| { - builder.fetch(f.clone()) + let (server, reg) = init_server(move |builder| { + builder.allowed_hosts(None).fetch(f.clone()) }, if multi_threaded { Remote::new_thread_per_future() } else { Remote::new_sync() }); (server, fetch, reg) } -pub fn serve_with_fetch(web_token: &'static str) -> (Server, FakeFetch) { +pub fn serve_with_fetch(web_token: &'static str) -> (ServerLoop, FakeFetch) { let fetch = FakeFetch::default(); let f = fetch.clone(); - let (server, _) = init_server(None, move |builder| { + let (server, _) = init_server(move |builder| { builder + .allowed_hosts(None) .fetch(f.clone()) .web_proxy_tokens(Arc::new(move |token| &token == web_token)) }, Remote::new_sync()); @@ -111,11 +143,11 @@ pub fn serve_with_fetch(web_token: &'static str) -> (Server, FakeFetch) { (server, fetch) } -pub fn serve() -> Server { - init_server(None, |builder| builder, Remote::new_sync()).0 +pub fn serve() -> ServerLoop { + init_server(|builder| builder.allowed_hosts(None), Remote::new_sync()).0 } -pub fn request(server: Server, request: &str) -> http_client::Response { +pub fn request(server: ServerLoop, request: &str) -> http_client::Response { http_client::request(server.addr(), request) } diff --git a/parity/dapps.rs b/parity/dapps.rs index 591c1759310..d1edcbd6595 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -22,9 +22,9 @@ use ethcore::client::Client; use ethsync::SyncProvider; use helpers::replace_home; use dir::default_data_path; +use jsonrpc_core::reactor::Remote; use rpc_apis::SignerService; use hash_fetch::fetch::Client as FetchClient; -use parity_reactor::Remote; #[derive(Debug, PartialEq, Clone)] pub struct Configuration { @@ -130,6 +130,8 @@ mod server { use rpc_apis; use ethcore_rpc::is_major_importing; use hash_fetch::urlhint::ContractClient; + use jsonrpc_core::reactor::RpcHandler; + use parity_reactor; pub use ethcore_dapps::Server as WebappServer; @@ -146,8 +148,9 @@ mod server { let server = dapps::ServerBuilder::new( &dapps_path, Arc::new(Registrar { client: deps.client.clone() }), - deps.remote.clone(), + parity_reactor::Remote::new(deps.remote.clone()), ); + let sync = deps.sync.clone(); let client = deps.client.clone(); let signer = deps.signer.clone(); @@ -156,15 +159,17 @@ mod server { .sync_status(Arc::new(move || is_major_importing(Some(sync.status().state), client.queue_info()))) .web_proxy_tokens(Arc::new(move |token| signer.is_valid_web_proxy_access_token(&token))) .extra_dapps(&extra_dapps) - .signer_address(deps.signer.address()); + .signer_address(deps.signer.address()) + .allowed_hosts(allowed_hosts); - let server = rpc_apis::setup_rpc(server, deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext); + let apis = rpc_apis::setup_rpc(Default::default(), deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext); + let handler = RpcHandler::new(Arc::new(apis), deps.remote); let start_result = match auth { None => { - server.start_unsecured_http(url, allowed_hosts) + server.start_unsecured_http(url, handler) }, Some((username, password)) => { - server.start_basic_auth_http(url, allowed_hosts, &username, &password) + server.start_basic_auth_http(url, &username, &password, handler) }, }; @@ -175,8 +180,9 @@ mod server { }, Err(e) => Err(format!("WebApps error: {:?}", e)), Ok(server) => { + let ph = deps.panic_handler; server.set_panic_handler(move || { - deps.panic_handler.notify_all("Panic in WebApp thread.".to_owned()); + ph.notify_all("Panic in WebApp thread.".to_owned()); }); Ok(server) }, diff --git a/parity/main.rs b/parity/main.rs index 7d2be8fb035..08287909181 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -41,6 +41,7 @@ extern crate ethcore_ipc as ipc; extern crate ethcore_ipc_nano as nanoipc; extern crate serde; extern crate serde_json; +extern crate jsonrpc_core; extern crate rlp; extern crate ethcore_light as light; extern crate parity_hash_fetch as hash_fetch; diff --git a/parity/rpc.rs b/parity/rpc.rs index 4fe126e89ce..178a7f14b3a 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -19,11 +19,14 @@ use std::sync::Arc; use std::net::SocketAddr; use std::io; use io::PanicHandler; -use ethcore_rpc::{RpcServerError, RpcServer as Server, IpcServerError}; + +use dir::default_data_path; +use ethcore_rpc::{self as rpc, RpcServerError, IpcServerError, Metadata}; +use helpers::parity_ipc_path; +use jsonrpc_core::MetaIoHandler; +use jsonrpc_core::reactor::{RpcHandler, Remote}; use rpc_apis; use rpc_apis::ApiSet; -use helpers::parity_ipc_path; -use dir::default_data_path; pub use ethcore_rpc::{IpcServer, Server as HttpServer}; @@ -81,6 +84,7 @@ impl fmt::Display for IpcConfiguration { pub struct Dependencies { pub panic_handler: Arc, pub apis: Arc, + pub remote: Remote, } pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Result, String> { @@ -93,9 +97,8 @@ pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Result Result { - let server = Server::new(); - Ok(rpc_apis::setup_rpc(server, deps.apis.clone(), apis)) +fn setup_apis(apis: ApiSet, deps: &Dependencies) -> MetaIoHandler { + rpc_apis::setup_rpc(MetaIoHandler::default(), deps.apis.clone(), apis) } pub fn setup_http_rpc_server( @@ -105,9 +108,10 @@ pub fn setup_http_rpc_server( allowed_hosts: Option>, apis: ApiSet ) -> Result { - let server = setup_rpc_server(apis, dependencies)?; + let apis = setup_apis(apis, dependencies); + let handler = RpcHandler::new(Arc::new(apis), dependencies.remote.clone()); let ph = dependencies.panic_handler.clone(); - let start_result = server.start_http(url, cors_domains, allowed_hosts, ph); + let start_result = rpc::start_http(url, cors_domains, allowed_hosts, ph, handler); match start_result { Err(RpcServerError::IoError(err)) => match err.kind() { io::ErrorKind::AddrInUse => Err(format!("RPC address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --jsonrpc-port and --jsonrpc-interface options.", url)), @@ -118,14 +122,15 @@ pub fn setup_http_rpc_server( } } -pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result, String> { +pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result>, String> { if !conf.enabled { return Ok(None); } Ok(Some(setup_ipc_rpc_server(deps, &conf.socket_addr, conf.apis)?)) } -pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: ApiSet) -> Result { - let server = setup_rpc_server(apis, dependencies)?; - match server.start_ipc(addr) { +pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: ApiSet) -> Result, String> { + let apis = setup_apis(apis, dependencies); + let handler = RpcHandler::new(Arc::new(apis), dependencies.remote.clone()); + match rpc::start_ipc(addr, handler) { 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/parity/rpc_apis.rs b/parity/rpc_apis.rs index 5260b9df57b..062ef02dbd3 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -20,16 +20,16 @@ use std::cmp::PartialEq; use std::str::FromStr; use std::sync::Arc; use util::RotatingLogger; +use jsonrpc_core::{MetaIoHandler}; use ethcore::miner::{Miner, ExternalMiner}; use ethcore::client::Client; use ethcore::account_provider::AccountProvider; use ethcore::snapshot::SnapshotService; use ethsync::{ManageNetwork, SyncProvider}; -use ethcore_rpc::{Extendable, NetworkSettings}; +use ethcore_rpc::{Metadata, NetworkSettings}; pub use ethcore_rpc::SignerService; use updater::Updater; use hash_fetch::fetch::Client as FetchClient; -use parity_reactor::Remote; #[derive(Debug, PartialEq, Clone, Eq, Hash)] pub enum Api { @@ -125,7 +125,6 @@ pub struct Dependencies { pub dapps_interface: Option, pub dapps_port: Option, pub fetch: FetchClient, - pub remote: Remote, } fn to_modules(apis: &[Api]) -> BTreeMap { @@ -170,18 +169,20 @@ impl ApiSet { } macro_rules! add_signing_methods { - ($namespace:ident, $server:expr, $deps:expr) => { - let server = &$server; - let deps = &$deps; - if deps.signer_service.is_enabled() { - server.add_delegate($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store))) - } else { - server.add_delegate($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner))) + ($namespace:ident, $handler:expr, $deps:expr) => { + { + let handler = &mut $handler; + let deps = &$deps; + if deps.signer_service.is_enabled() { + handler.extend_with($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store))) + } else { + handler.extend_with($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner))) + } } } } -pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet) -> T { +pub fn setup_rpc(mut handler: MetaIoHandler, deps: Arc, apis: ApiSet) -> MetaIoHandler { use ethcore_rpc::v1::*; // it's turned into vector, cause ont of the cases requires &[] @@ -189,10 +190,10 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet for api in &apis { match *api { Api::Web3 => { - server.add_delegate(Web3Client::new().to_delegate()); + handler.extend_with(Web3Client::new().to_delegate()); }, Api::Net => { - server.add_delegate(NetClient::new(&deps.sync).to_delegate()); + handler.extend_with(NetClient::new(&deps.sync).to_delegate()); }, Api::Eth => { let client = EthClient::new( @@ -207,25 +208,25 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet send_block_number_in_get_work: !deps.geth_compatibility, } ); - server.add_delegate(client.to_delegate()); + handler.extend_with(client.to_delegate()); let filter_client = EthFilterClient::new(&deps.client, &deps.miner); - server.add_delegate(filter_client.to_delegate()); + handler.extend_with(filter_client.to_delegate()); - add_signing_methods!(EthSigning, server, deps); + add_signing_methods!(EthSigning, handler, deps); }, Api::Personal => { - server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate()); + handler.extend_with(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate()); }, Api::Signer => { - server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate()); + handler.extend_with(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate()); }, Api::Parity => { let signer = match deps.signer_service.is_enabled() { true => Some(deps.signer_service.clone()), false => None, }; - server.add_delegate(ParityClient::new( + handler.extend_with(ParityClient::new( &deps.client, &deps.miner, &deps.sync, @@ -239,32 +240,31 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet deps.dapps_port, ).to_delegate()); - add_signing_methods!(EthSigning, server, deps); - add_signing_methods!(ParitySigning, server, deps); + add_signing_methods!(EthSigning, handler, deps); + add_signing_methods!(ParitySigning, handler, deps); }, Api::ParityAccounts => { - server.add_delegate(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate()); + handler.extend_with(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate()); }, Api::ParitySet => { - server.add_delegate(ParitySetClient::new( + handler.extend_with(ParitySetClient::new( &deps.client, &deps.miner, &deps.updater, &deps.net_service, deps.fetch.clone(), - deps.remote.clone(), ).to_delegate()) }, Api::Traces => { - server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate()) + handler.extend_with(TracesClient::new(&deps.client, &deps.miner).to_delegate()) }, Api::Rpc => { let modules = to_modules(&apis); - server.add_delegate(RpcClient::new(modules).to_delegate()); + handler.extend_with(RpcClient::new(modules).to_delegate()); } } } - server + handler } #[cfg(test)] diff --git a/parity/run.rs b/parity/run.rs index e4c5fca6feb..55a8bb8e642 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -347,7 +347,6 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> R ); service.add_notify(updater.clone()); - // set up dependencies for rpc servers let signer_path = cmd.signer_conf.signer_path.clone(); let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies { @@ -375,12 +374,12 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> R false => None, }, fetch: fetch.clone(), - remote: event_loop.remote(), }); let dependencies = rpc::Dependencies { panic_handler: panic_handler.clone(), apis: deps_for_rpc_apis.clone(), + remote: event_loop.raw_remote(), }; // start rpc servers @@ -393,7 +392,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> R apis: deps_for_rpc_apis.clone(), client: client.clone(), sync: sync_provider.clone(), - remote: event_loop.remote(), + remote: event_loop.raw_remote(), fetch: fetch.clone(), signer: deps_for_rpc_apis.signer_service.clone(), }; @@ -403,6 +402,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> R let signer_deps = signer::Dependencies { panic_handler: panic_handler.clone(), apis: deps_for_rpc_apis.clone(), + remote: event_loop.raw_remote(), }; let signer_server = signer::start(cmd.signer_conf.clone(), signer_deps)?; diff --git a/parity/signer.rs b/parity/signer.rs index 43bb080da63..69597e0a0a0 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -22,8 +22,9 @@ use io::{ForwardPanic, PanicHandler}; use util::path::restrict_permissions_owner; use rpc_apis; use ethcore_signer as signer; -use helpers::replace_home; use dir::default_data_path; +use helpers::replace_home; +use jsonrpc_core::reactor::{RpcHandler, Remote}; pub use ethcore_signer::Server as SignerServer; const CODES_FILENAME: &'static str = "authcodes"; @@ -53,6 +54,7 @@ impl Default for Configuration { pub struct Dependencies { pub panic_handler: Arc, pub apis: Arc, + pub remote: Remote, } pub struct NewToken { @@ -124,8 +126,9 @@ fn do_start(conf: Configuration, deps: Dependencies) -> Result(&self, delegate: IoDelegate); -} - -/// Http server. -pub struct RpcServer { - handler: Arc, -} - -impl Extendable for RpcServer { - /// Add io delegate. - fn add_delegate(&self, delegate: IoDelegate) { - self.handler.add_delegate(delegate); - } -} - -impl RpcServer { - /// Construct new http server object. - pub fn new() -> RpcServer { - RpcServer { - handler: Arc::new(IoHandler::new()), - } - } - - /// Start http server asynchronously and returns result with `Server` handle on success or an error. - pub fn start_http( - &self, - addr: &SocketAddr, - cors_domains: Option>, - allowed_hosts: Option>, - panic_handler: Arc, - ) -> Result { - - let cors_domains = cors_domains.map(|domains| { - domains.into_iter() - .map(|v| match v.as_str() { - "*" => jsonrpc_http_server::AccessControlAllowOrigin::Any, - "null" => jsonrpc_http_server::AccessControlAllowOrigin::Null, - v => jsonrpc_http_server::AccessControlAllowOrigin::Value(v.into()), - }) - .collect() - }); - - ServerBuilder::new(self.handler.clone()) - .cors(cors_domains.into()) - .allowed_hosts(allowed_hosts.into()) - .panic_handler(move || { - panic_handler.notify_all("Panic in RPC thread.".to_owned()); +/// Start http server asynchronously and returns result with `Server` handle on success or an error. +pub fn start_http( + addr: &SocketAddr, + cors_domains: Option>, + allowed_hosts: Option>, + panic_handler: Arc, + handler: RpcHandler, +) -> Result { + + let cors_domains = cors_domains.map(|domains| { + domains.into_iter() + .map(|v| match v.as_str() { + "*" => jsonrpc_http_server::AccessControlAllowOrigin::Any, + "null" => jsonrpc_http_server::AccessControlAllowOrigin::Null, + v => jsonrpc_http_server::AccessControlAllowOrigin::Value(v.into()), }) - .start_http(addr) - } + .collect() + }); + + ServerBuilder::with_rpc_handler(handler) + .cors(cors_domains.into()) + .allowed_hosts(allowed_hosts.into()) + .panic_handler(move || { + panic_handler.notify_all("Panic in RPC thread.".to_owned()); + }) + .start_http(addr) +} - /// Start ipc server asynchronously and returns result with `Server` handle on success or an error. - pub fn start_ipc(&self, addr: &str) -> Result { - let server = ipc::Server::new(addr, &self.handler)?; - server.run_async()?; - Ok(server) - } +/// Start ipc server asynchronously and returns result with `Server` handle on success or an error. +pub fn start_ipc(addr: &str, handler: RpcHandler) -> Result, ipc::Error> { + let server = ipc::Server::with_rpc_handler(addr, handler)?; + server.run_async()?; + Ok(server) } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 75817838d67..855b17e2e7c 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -16,41 +16,45 @@ //! Eth rpc implementation. -extern crate ethash; - use std::io::{Write}; use std::process::{Command, Stdio}; use std::thread; use std::time::{Instant, Duration}; use std::sync::{Arc, Weak}; + +use futures::{self, BoxFuture, Future}; +use rlp::{self, UntrustedRlp, View}; use time::get_time; -use ethsync::{SyncProvider}; -use ethcore::miner::{MinerService, ExternalMinerService}; -use jsonrpc_core::*; -use jsonrpc_macros::Trailing; use util::{H256, Address, FixedHash, U256, H64, Uint}; -use util::sha3::*; +use util::sha3::Hashable; use util::{FromHex, Mutex}; -use rlp::{self, UntrustedRlp, View}; + +use ethash::SeedHashCompute; use ethcore::account_provider::AccountProvider; -use ethcore::client::{MiningBlockChainClient, BlockId, TransactionId, UncleId}; -use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber}; use ethcore::block::IsBlock; +use ethcore::client::{MiningBlockChainClient, BlockId, TransactionId, UncleId}; use ethcore::ethereum::Ethash; -use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, PendingTransaction, Action}; -use ethcore::log_entry::LogEntry; use ethcore::filter::Filter as EthcoreFilter; +use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber}; +use ethcore::log_entry::LogEntry; +use ethcore::miner::{MinerService, ExternalMinerService}; +use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, PendingTransaction, Action}; use ethcore::snapshot::SnapshotService; -use self::ethash::SeedHashCompute; +use ethsync::{SyncProvider}; + +use jsonrpc_core::Error; +use jsonrpc_macros::Trailing; + use v1::traits::Eth; use v1::types::{ RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, - Transaction, CallRequest, Index, Filter, Log, Receipt, Work, DappId, + Transaction, CallRequest, Index, Filter, Log, Receipt, Work, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256, }; use v1::helpers::{CallRequest as CRequest, errors, limit_logs}; use v1::helpers::dispatch::{dispatch_transaction, default_gas_price}; use v1::helpers::block_import::is_major_importing; +use v1::metadata::Metadata; const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed"; @@ -271,7 +275,9 @@ impl Eth for EthClient where SN: SnapshotService + 'static, S: SyncProvider + 'static, M: MinerService + 'static, - EM: ExternalMinerService + 'static { + EM: ExternalMinerService + 'static, +{ + type Metadata = Metadata; fn protocol_version(&self) -> Result { self.active()?; @@ -338,18 +344,21 @@ impl Eth for EthClient where Ok(RpcU256::from(default_gas_price(&*client, &*miner))) } - fn accounts(&self, id: Trailing) -> Result, Error> { - self.active()?; + fn accounts(&self, meta: Metadata) -> BoxFuture, Error> { + let dapp = meta.dapp_id.unwrap_or_default(); - let dapp = id.0; + let accounts = move || { + self.active()?; - let store = take_weak!(self.accounts); - let accounts = store - .note_dapp_used(dapp.clone().into()) - .and_then(|_| store.dapps_addresses(dapp.into())) - .map_err(|e| errors::internal("Could not fetch accounts.", e))?; + let store = take_weak!(self.accounts); + let accounts = store + .note_dapp_used(dapp.clone().into()) + .and_then(|_| store.dapps_addresses(dapp.into())) + .map_err(|e| errors::internal("Could not fetch accounts.", e))?; + Ok(accounts.into_iter().map(Into::into).collect()) + }; - Ok(accounts.into_iter().map(Into::into).collect()) + futures::done(accounts()).boxed() } fn block_number(&self) -> Result { diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index e0f9bca5323..06ca70f2ad4 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -23,13 +23,11 @@ use ethcore::client::MiningBlockChainClient; use ethcore::mode::Mode; use ethsync::ManageNetwork; use fetch::{self, Fetch}; -use futures::Future; +use futures::{self, BoxFuture, Future}; use util::sha3; use updater::{Service as UpdateService}; -use parity_reactor::Remote; use jsonrpc_core::Error; -use jsonrpc_macros::Ready; use v1::helpers::errors; use v1::traits::ParitySet; use v1::types::{Bytes, H160, H256, U256, ReleaseInfo}; @@ -46,7 +44,6 @@ pub struct ParitySetClient where updater: Weak, net: Weak, fetch: F, - remote: Remote, } impl ParitySetClient where @@ -56,14 +53,13 @@ impl ParitySetClient where F: Fetch, { /// Creates new `ParitySetClient` with given `Fetch`. - pub fn new(client: &Arc, miner: &Arc, updater: &Arc, net: &Arc, fetch: F, remote: Remote) -> Self { + pub fn new(client: &Arc, miner: &Arc, updater: &Arc, net: &Arc, fetch: F) -> Self { ParitySetClient { client: Arc::downgrade(client), miner: Arc::downgrade(miner), updater: Arc::downgrade(updater), net: Arc::downgrade(net), fetch: fetch, - remote: remote, } } @@ -189,28 +185,19 @@ impl ParitySet for ParitySetClient where Ok(true) } - fn hash_content(&self, ready: Ready, url: String) { - let res = self.active(); - - match res { - Err(e) => ready.ready(Err(e)), - Ok(()) => { - let task = self.fetch.fetch(&url).then(move |result| { - let result = result - .map_err(errors::from_fetch_error) - .and_then(|response| { - sha3(&mut io::BufReader::new(response)).map_err(errors::from_fetch_error) - }) - .map(Into::into); - - // Receive ready and invoke with result. - ready.ready(result); - Ok(()) as Result<(), ()> - }); - - self.remote.spawn(task); - } + fn hash_content(&self, url: String) -> BoxFuture { + if let Err(e) = self.active() { + return futures::failed(e).boxed(); } + + self.fetch.process(self.fetch.fetch(&url).then(move |result| { + result + .map_err(errors::from_fetch_error) + .and_then(|response| { + sha3(&mut io::BufReader::new(response)).map_err(errors::from_fetch_error) + }) + .map(Into::into) + })) } fn upgrade_ready(&self) -> Result, Error> { diff --git a/rpc/src/v1/impls/signing.rs b/rpc/src/v1/impls/signing.rs index bd3f1ec3f53..301f086e27a 100644 --- a/rpc/src/v1/impls/signing.rs +++ b/rpc/src/v1/impls/signing.rs @@ -24,8 +24,8 @@ use ethcore::account_provider::AccountProvider; use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; +use futures::{self, BoxFuture, Future}; use jsonrpc_core::Error; -use jsonrpc_macros::Ready; use v1::helpers::{ errors, dispatch, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, SignerService @@ -164,17 +164,21 @@ impl ParitySigning for SigningQueueClient where res } - fn decrypt_message(&self, ready: Ready, address: RpcH160, data: RpcBytes) { + fn decrypt_message(&self, address: RpcH160, data: RpcBytes) -> BoxFuture { let res = self.active() .and_then(|_| self.dispatch(RpcConfirmationPayload::Decrypt((address, data).into()))); + + let (ready, p) = futures::oneshot(); // TODO [todr] typed handle_dispatch self.handle_dispatch(res, |response| { match response { - Ok(RpcConfirmationResponse::Decrypt(data)) => ready.ready(Ok(data)), - Err(e) => ready.ready(Err(e)), - e => ready.ready(Err(errors::internal("Unexpected result.", e))), + Ok(RpcConfirmationResponse::Decrypt(data)) => ready.complete(Ok(data)), + Err(e) => ready.complete(Err(e)), + e => ready.complete(Err(errors::internal("Unexpected result.", e))), } }); + + p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed() } } @@ -182,37 +186,49 @@ impl EthSigning for SigningQueueClient where C: MiningBlockChainClient, M: MinerService, { - fn sign(&self, ready: Ready, address: RpcH160, data: RpcBytes) { + fn sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture { let hash = data.0.sha3().into(); let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::Signature((address, hash).into()))); + + let (ready, p) = futures::oneshot(); self.handle_dispatch(res, |response| { match response { - Ok(RpcConfirmationResponse::Signature(signature)) => ready.ready(Ok(signature)), - Err(e) => ready.ready(Err(e)), - e => ready.ready(Err(errors::internal("Unexpected result.", e))), + Ok(RpcConfirmationResponse::Signature(signature)) => ready.complete(Ok(signature)), + Err(e) => ready.complete(Err(e)), + e => ready.complete(Err(errors::internal("Unexpected result.", e))), } }); + + p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed() } - fn send_transaction(&self, ready: Ready, request: RpcTransactionRequest) { + fn send_transaction(&self, request: RpcTransactionRequest) -> BoxFuture { let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SendTransaction(request))); + + let (ready, p) = futures::oneshot(); self.handle_dispatch(res, |response| { match response { - Ok(RpcConfirmationResponse::SendTransaction(hash)) => ready.ready(Ok(hash)), - Err(e) => ready.ready(Err(e)), - e => ready.ready(Err(errors::internal("Unexpected result.", e))), + Ok(RpcConfirmationResponse::SendTransaction(hash)) => ready.complete(Ok(hash)), + Err(e) => ready.complete(Err(e)), + e => ready.complete(Err(errors::internal("Unexpected result.", e))), } }); + + p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed() } - fn sign_transaction(&self, ready: Ready, request: RpcTransactionRequest) { + fn sign_transaction(&self, request: RpcTransactionRequest) -> BoxFuture { let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SignTransaction(request))); + + let (ready, p) = futures::oneshot(); self.handle_dispatch(res, |response| { match response { - Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.ready(Ok(tx)), - Err(e) => ready.ready(Err(e)), - e => ready.ready(Err(errors::internal("Unexpected result.", e))), + Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.complete(Ok(tx)), + Err(e) => ready.complete(Err(e)), + e => ready.complete(Err(errors::internal("Unexpected result.", e))), } }); + + p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled."))).boxed() } } diff --git a/rpc/src/v1/impls/signing_unsafe.rs b/rpc/src/v1/impls/signing_unsafe.rs index d64281bc931..41ef79998c8 100644 --- a/rpc/src/v1/impls/signing_unsafe.rs +++ b/rpc/src/v1/impls/signing_unsafe.rs @@ -23,8 +23,8 @@ use ethcore::account_provider::AccountProvider; use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; +use futures::{self, BoxFuture, Future}; use jsonrpc_core::Error; -use jsonrpc_macros::Ready; use v1::helpers::errors; use v1::helpers::dispatch; use v1::traits::{EthSigning, ParitySigning}; @@ -85,32 +85,35 @@ impl EthSigning for SigningUnsafeClient where C: MiningBlockChainClient, M: MinerService, { - fn sign(&self, ready: Ready, address: RpcH160, data: RpcBytes) { + fn sign(&self, address: RpcH160, data: RpcBytes) -> BoxFuture { let hash = data.0.sha3().into(); let result = match self.handle(RpcConfirmationPayload::Signature((address, hash).into())) { Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature), Err(e) => Err(e), e => Err(errors::internal("Unexpected result", e)), }; - ready.ready(result); + + futures::done(result).boxed() } - fn send_transaction(&self, ready: Ready, request: RpcTransactionRequest) { + fn send_transaction(&self, request: RpcTransactionRequest) -> BoxFuture { let result = match self.handle(RpcConfirmationPayload::SendTransaction(request)) { Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash), Err(e) => Err(e), e => Err(errors::internal("Unexpected result", e)), }; - ready.ready(result); + + futures::done(result).boxed() } - fn sign_transaction(&self, ready: Ready, request: RpcTransactionRequest) { + fn sign_transaction(&self, request: RpcTransactionRequest) -> BoxFuture { let result = match self.handle(RpcConfirmationPayload::SignTransaction(request)) { Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx), Err(e) => Err(e), e => Err(errors::internal("Unexpected result", e)), }; - ready.ready(result); + + futures::done(result).boxed() } } @@ -118,13 +121,14 @@ impl ParitySigning for SigningUnsafeClient where C: MiningBlockChainClient, M: MinerService, { - fn decrypt_message(&self, ready: Ready, address: RpcH160, data: RpcBytes) { + fn decrypt_message(&self, address: RpcH160, data: RpcBytes) -> BoxFuture { let result = match self.handle(RpcConfirmationPayload::Decrypt((address, data).into())) { Ok(RpcConfirmationResponse::Decrypt(data)) => Ok(data), Err(e) => Err(e), e => Err(errors::internal("Unexpected result", e)), }; - ready.ready(result); + + futures::done(result).boxed() } fn post_sign(&self, _: RpcH160, _: RpcH256) -> Result, Error> { diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 21f81cc1696..cb1fb524ae4 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -77,7 +77,6 @@ impl TracesClient where C: BlockChainClient, M: MinerService { impl Traces for TracesClient where C: BlockChainClient + 'static, M: MinerService + 'static { fn filter(&self, filter: TraceFilter) -> Result, Error> { self.active()?; - let client = take_weak!(self.client); let traces = client.filter_traces(filter.into()); let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); @@ -94,7 +93,6 @@ impl Traces for TracesClient where C: BlockChainClient + 'static, M: fn transaction_traces(&self, transaction_hash: H256) -> Result, Error> { self.active()?; - let client = take_weak!(self.client); let traces = client.transaction_traces(TransactionId::Hash(transaction_hash.into())); let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); diff --git a/rpc/src/v1/metadata.rs b/rpc/src/v1/metadata.rs new file mode 100644 index 00000000000..322d8a479d6 --- /dev/null +++ b/rpc/src/v1/metadata.rs @@ -0,0 +1,50 @@ +// Copyright 2015, 2016 Parity Technologies (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 . + +use jsonrpc_core; + +/// RPC methods metadata. +#[derive(Clone, Default, Debug, PartialEq)] +pub struct Metadata { + /// Current dapplication identifier + pub dapp_id: Option, + /// Request origin + pub origin: Origin, +} + +/// RPC request origin +#[derive(Clone, Debug, PartialEq)] +pub enum Origin { + /// RPC server + Rpc, + /// Dapps server + Dapps, + /// IPC server + Ipc, + /// Signer + Signer, + /// Unknown + Unknown, +} + +impl Default for Origin { + fn default() -> Self { + Origin::Unknown + } +} + +impl jsonrpc_core::Metadata for Metadata {} + diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index 2942d81ed02..96563d4127b 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -21,6 +21,7 @@ #[macro_use] mod helpers; mod impls; +mod metadata; pub mod traits; pub mod tests; @@ -29,3 +30,4 @@ pub mod types; pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, Signer, Personal, Traces, Rpc}; pub use self::impls::*; pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, block_import}; +pub use self::metadata::{Metadata, Origin}; diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 27e25b64ec5..154c700f916 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -18,6 +18,7 @@ use std::sync::Arc; use std::time::Duration; +use devtools::RandomTempPath; use ethcore::client::{BlockChainClient, Client, ClientConfig}; use ethcore::ids::BlockId; use ethcore::spec::{Genesis, Spec}; @@ -26,18 +27,17 @@ use ethcore::views::BlockView; use ethcore::ethereum; use ethcore::miner::{MinerOptions, Banning, GasPricer, MinerService, ExternalMiner, Miner, PendingSet, PrioritizationStrategy, GasLimit}; use ethcore::account_provider::AccountProvider; -use devtools::RandomTempPath; -use util::Hashable; -use io::IoChannel; -use util::{U256, H256, Uint, Address}; -use jsonrpc_core::{IoHandler, GenericIoHandler}; use ethjson::blockchain::BlockChain; +use io::IoChannel; +use util::{U256, H256, Uint, Address, Hashable}; +use jsonrpc_core::IoHandler; use v1::impls::{EthClient, SigningUnsafeClient}; -use v1::types::U256 as NU256; +use v1::metadata::Metadata; +use v1::tests::helpers::{TestSnapshotService, TestSyncProvider, Config}; use v1::traits::eth::Eth; use v1::traits::eth_signing::EthSigning; -use v1::tests::helpers::{TestSnapshotService, TestSyncProvider, Config}; +use v1::types::U256 as NU256; fn account_provider() -> Arc { Arc::new(AccountProvider::transient_provider()) @@ -92,7 +92,7 @@ struct EthTester { _miner: Arc, _snapshot: Arc, accounts: Arc, - handler: IoHandler, + handler: IoHandler, } impl EthTester { @@ -147,9 +147,9 @@ impl EthTester { &miner_service ); - let handler = IoHandler::new(); - handler.add_delegate(eth_client.to_delegate()); - handler.add_delegate(eth_sign.to_delegate()); + let mut handler = IoHandler::default(); + handler.extend_with(eth_client.to_delegate()); + handler.extend_with(eth_sign.to_delegate()); EthTester { _miner: miner_service, diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 5f44243138d..2ca4918d178 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -31,9 +31,10 @@ use ethcore::transaction::{Transaction, Action}; use ethcore::miner::{ExternalMiner, MinerService}; use ethsync::SyncState; -use jsonrpc_core::{IoHandler, GenericIoHandler}; +use jsonrpc_core::IoHandler; use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService}; +use v1::metadata::Metadata; fn blockchain_client() -> Arc { let client = TestBlockChainClient::new(); @@ -66,7 +67,7 @@ struct EthTester { pub miner: Arc, pub snapshot: Arc, hashrates: Arc>>, - pub io: IoHandler, + pub io: IoHandler, } impl Default for EthTester { @@ -87,10 +88,10 @@ impl EthTester { let eth = EthClient::new(&client, &snapshot, &sync, &ap, &miner, &external_miner, options).to_delegate(); let filter = EthFilterClient::new(&client, &miner).to_delegate(); let sign = SigningUnsafeClient::new(&client, &ap, &miner).to_delegate(); - let io = IoHandler::new(); - io.add_delegate(eth); - io.add_delegate(sign); - io.add_delegate(filter); + let mut io: IoHandler = IoHandler::default(); + io.extend_with(eth); + io.extend_with(sign); + io.extend_with(filter); EthTester { client: client, @@ -373,9 +374,11 @@ fn rpc_eth_accounts() { // 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 request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#; - assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); + let mut meta = Metadata::default(); + meta.dapp_id = Some("app1".into()); + assert_eq!((*tester.io).handle_request_sync(request, meta), Some(response.to_owned())); } #[test] diff --git a/rpc/src/v1/tests/mocked/net.rs b/rpc/src/v1/tests/mocked/net.rs index 1c4a4c1ac80..81650590c97 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, GenericIoHandler}; +use jsonrpc_core::IoHandler; use v1::{Net, NetClient}; use v1::tests::helpers::{Config, TestSyncProvider}; @@ -30,8 +30,8 @@ fn sync_provider() -> Arc { fn rpc_net_version() { let sync = sync_provider(); let net = NetClient::new(&sync).to_delegate(); - let io = IoHandler::new(); - io.add_delegate(net); + let mut io = IoHandler::new(); + io.extend_with(net); let request = r#"{"jsonrpc": "2.0", "method": "net_version", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"3","id":1}"#; @@ -43,8 +43,8 @@ fn rpc_net_version() { fn rpc_net_peer_count() { let sync = sync_provider(); let net = NetClient::new(&sync).to_delegate(); - let io = IoHandler::new(); - io.add_delegate(net); + let mut io = IoHandler::new(); + io.extend_with(net); let request = r#"{"jsonrpc": "2.0", "method": "net_peerCount", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x78","id":1}"#; @@ -56,8 +56,8 @@ fn rpc_net_peer_count() { fn rpc_net_listening() { let sync = sync_provider(); let net = NetClient::new(&sync).to_delegate(); - let io = IoHandler::new(); - io.add_delegate(net); + let mut io = IoHandler::new(); + io.extend_with(net); let request = r#"{"jsonrpc": "2.0", "method": "net_listening", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 0fae89c1e15..eb1f3e3ebcd 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, GenericIoHandler}; +use jsonrpc_core::IoHandler; use v1::{Parity, ParityClient}; use v1::helpers::{SignerService, NetworkSettings}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater}; @@ -87,14 +87,14 @@ impl Dependencies { } fn default_client(&self) -> IoHandler { - let io = IoHandler::new(); - io.add_delegate(self.client(None).to_delegate()); + let mut io = IoHandler::default(); + io.extend_with(self.client(None).to_delegate()); io } fn with_signer(&self, signer: SignerService) -> IoHandler { - let io = IoHandler::new(); - io.add_delegate(self.client(Some(Arc::new(signer))).to_delegate()); + let mut io = IoHandler::default(); + io.extend_with(self.client(Some(Arc::new(signer))).to_delegate()); io } } diff --git a/rpc/src/v1/tests/mocked/parity_accounts.rs b/rpc/src/v1/tests/mocked/parity_accounts.rs index 0c8443dde20..4b031c9f984 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, GenericIoHandler}; +use jsonrpc_core::IoHandler; use v1::{ParityAccounts, ParityAccountsClient}; struct ParityAccountsTester { @@ -44,8 +44,8 @@ fn setup() -> ParityAccountsTester { let client = blockchain_client(); let parity_accounts = ParityAccountsClient::new(&accounts, &client); - let io = IoHandler::new(); - io.add_delegate(parity_accounts.to_delegate()); + let mut io = IoHandler::default(); + io.extend_with(parity_accounts.to_delegate()); let tester = ParityAccountsTester { accounts: accounts, diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index e36b69058dd..f118c35c63a 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -22,9 +22,8 @@ use util::{U256, Address}; use ethcore::miner::MinerService; use ethcore::client::TestBlockChainClient; use ethsync::ManageNetwork; -use parity_reactor::Remote; -use jsonrpc_core::{IoHandler, GenericIoHandler}; +use jsonrpc_core::IoHandler; use v1::{ParitySet, ParitySetClient}; use v1::tests::helpers::{TestMinerService, TestFetch, TestUpdater}; use super::manage_network::TestManageNetwork; @@ -48,7 +47,7 @@ fn updater_service() -> Arc { pub type TestParitySetClient = ParitySetClient; fn parity_set_client(client: &Arc, miner: &Arc, updater: &Arc, net: &Arc) -> TestParitySetClient { - ParitySetClient::new(client, miner, updater, &(net.clone() as Arc), TestFetch::default(), Remote::new_sync()) + ParitySetClient::new(client, miner, updater, &(net.clone() as Arc), TestFetch::default()) } #[test] @@ -57,8 +56,8 @@ fn rpc_parity_execute_upgrade() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_executeUpgrade", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -75,8 +74,8 @@ fn rpc_parity_upgrade_ready() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_upgradeReady", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"binary":"0x00000000000000000000000000000000000000000000000000000000000005e6","fork":15100,"is_critical":true,"version":{"hash":"0x0000000000000000000000000000000000000097","track":"beta","version":{"major":1,"minor":5,"patch":1}}},"id":1}"#; @@ -95,8 +94,9 @@ fn rpc_parity_set_min_gas_price() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -111,8 +111,9 @@ fn rpc_parity_set_gas_floor_target() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -127,8 +128,9 @@ fn rpc_parity_set_extra_data() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -143,8 +145,8 @@ fn rpc_parity_set_author() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -159,8 +161,8 @@ fn rpc_parity_set_engine_signer() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681", "password"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -177,8 +179,8 @@ fn rpc_parity_set_transactions_limit() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setTransactionsLimit", "params":[10240240], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -193,8 +195,8 @@ fn rpc_parity_set_hash_content() { let client = client_service(); let network = network_service(); let updater = updater_service(); - let io = IoHandler::new(); - io.add_delegate(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + let mut io = IoHandler::new(); + io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_hashContent", "params":["https://ethcore.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#; diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index c2984240f5d..8ee936934ef 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, GenericIoHandler}; +use jsonrpc_core::IoHandler; use util::{U256, Uint, Address}; use ethcore::account_provider::AccountProvider; use v1::{PersonalClient, Personal}; @@ -52,8 +52,8 @@ fn setup() -> PersonalTester { let miner = miner_service(); let personal = PersonalClient::new(&accounts, &client, &miner, false); - let io = IoHandler::new(); - io.add_delegate(personal.to_delegate()); + let mut io = IoHandler::default(); + io.extend_with(personal.to_delegate()); let tester = PersonalTester { accounts: accounts, diff --git a/rpc/src/v1/tests/mocked/rpc.rs b/rpc/src/v1/tests/mocked/rpc.rs index 52ba7885953..b1e20ebdf4d 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, GenericIoHandler}; +use jsonrpc_core::IoHandler; use v1::{Rpc, RpcClient}; @@ -30,8 +30,8 @@ fn rpc_client() -> RpcClient { #[test] fn modules() { let rpc = rpc_client().to_delegate(); - let io = IoHandler::new(); - io.add_delegate(rpc); + let mut io = IoHandler::new(); + io.extend_with(rpc); let request = r#"{"jsonrpc": "2.0", "method": "modules", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"rpc":"1.0","web3":"1.0"},"id":1}"#; @@ -42,8 +42,8 @@ fn modules() { #[test] fn rpc_modules() { let rpc = rpc_client().to_delegate(); - let io = IoHandler::new(); - io.add_delegate(rpc); + let mut io = IoHandler::new(); + io.extend_with(rpc); let request = r#"{"jsonrpc": "2.0", "method": "rpc_modules", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"ethcore":"1.0","rpc":"1.0","web3":"1.0"},"id":1}"#; diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index 4001dd99678..5ed231db457 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -24,7 +24,7 @@ use ethcore::transaction::{Transaction, Action}; use rlp::encode; use serde_json; -use jsonrpc_core::{IoHandler, GenericIoHandler}; +use jsonrpc_core::IoHandler; use v1::{SignerClient, Signer}; use v1::tests::helpers::TestMinerService; use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload}; @@ -58,8 +58,8 @@ fn signer_tester() -> SignerTester { let client = blockchain_client(); let miner = miner_service(); - let io = IoHandler::new(); - io.add_delegate(SignerClient::new(&accounts, &client, &miner, &signer).to_delegate()); + let mut io = IoHandler::default(); + io.extend_with(SignerClient::new(&accounts, &client, &miner, &signer).to_delegate()); SignerTester { signer: signer, diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index 4040b57b1a7..e6a27f832b4 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::{mpsc, Arc}; +use std::sync::Arc; use rlp; -use jsonrpc_core::{IoHandler, Success, GenericIoHandler}; +use jsonrpc_core::{IoHandler, Success}; use v1::impls::SigningQueueClient; use v1::traits::{EthSigning, ParitySigning, Parity}; use v1::helpers::{SignerService, SigningQueue}; @@ -31,6 +31,7 @@ use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; use ethcore::transaction::{Transaction, Action}; use ethstore::ethkey::{Generator, Random}; +use futures::Future; use serde_json; struct SigningTester { @@ -47,11 +48,11 @@ impl Default for SigningTester { let client = Arc::new(TestBlockChainClient::default()); let miner = Arc::new(TestMinerService::default()); let accounts = Arc::new(AccountProvider::transient_provider()); - let io = IoHandler::new(); + let mut io = IoHandler::default(); let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts); - io.add_delegate(EthSigning::to_delegate(rpc)); + io.extend_with(EthSigning::to_delegate(rpc)); let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts); - io.add_delegate(ParitySigning::to_delegate(rpc)); + io.extend_with(ParitySigning::to_delegate(rpc)); SigningTester { signer: signer, @@ -87,15 +88,12 @@ fn should_add_sign_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","id":1}"#; // then - let (tx, rx) = mpsc::channel(); - tester.io.handle_request(&request, move |response| { - tx.send(response).unwrap(); - }); + let promise = tester.io.handle_request(&request); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Signature(0.into()))); - let res = rx.try_recv().unwrap(); + let res = promise.wait().unwrap(); assert_eq!(res, Some(response.to_owned())); } @@ -230,15 +228,12 @@ fn should_add_transaction_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#; // then - let (tx, rx) = mpsc::channel(); - tester.io.handle_request(&request, move |response| { - tx.send(response).unwrap(); - }); + let promise = tester.io.handle_request(&request); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SendTransaction(0.into()))); - let res = rx.try_recv().unwrap(); + let res = promise.wait().unwrap(); assert_eq!(res, Some(response.to_owned())); } @@ -299,16 +294,13 @@ 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()); - tester.io.handle_request(&request, move |response| { - tx.send(response).unwrap(); - }); + let promise = tester.io.handle_request(&request); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into()))); - let res = rx.try_recv().unwrap(); + let res = promise.wait().unwrap(); assert_eq!(res, Some(response.to_owned())); } @@ -352,9 +344,9 @@ fn should_dispatch_transaction_if_account_is_unlock() { #[test] fn should_decrypt_message_if_account_is_unlocked() { // given - let tester = eth_signing(); + let mut tester = eth_signing(); let parity = parity::Dependencies::new(); - tester.io.add_delegate(parity.client(None).to_delegate()); + tester.io.extend_with(parity.client(None).to_delegate()); let (address, public) = tester.accounts.new_account_and_public("test").unwrap(); tester.accounts.unlock_account_permanently(address, "test".into()).unwrap(); @@ -400,14 +392,11 @@ fn should_add_decryption_to_the_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0102","id":1}"#; // then - let (tx, rx) = mpsc::channel(); - tester.io.handle_request(&request, move |response| { - tx.send(response).unwrap(); - }); + let promise = tester.io.handle_request(&request); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Decrypt(vec![0x1, 0x2].into()))); - let res = rx.try_recv().unwrap(); + let res = promise.wait().unwrap(); assert_eq!(res, Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/traces.rs b/rpc/src/v1/tests/mocked/traces.rs index f9a9baa0090..d12f8dbb550 100644 --- a/rpc/src/v1/tests/mocked/traces.rs +++ b/rpc/src/v1/tests/mocked/traces.rs @@ -21,7 +21,7 @@ use ethcore::trace::trace::{Action, Res, Call}; use ethcore::trace::LocalizedTrace; use ethcore::client::{TestBlockChainClient}; -use jsonrpc_core::{IoHandler, GenericIoHandler}; +use jsonrpc_core::IoHandler; use v1::tests::helpers::{TestMinerService}; use v1::{Traces, TracesClient}; @@ -64,8 +64,8 @@ fn io() -> Tester { })); let miner = Arc::new(TestMinerService::default()); let traces = TracesClient::new(&client, &miner); - let io = IoHandler::new(); - io.add_delegate(traces.to_delegate()); + let mut io = IoHandler::new(); + io.extend_with(traces.to_delegate()); Tester { _client: client, diff --git a/rpc/src/v1/tests/mocked/web3.rs b/rpc/src/v1/tests/mocked/web3.rs index c7ad42426a3..953dab22de8 100644 --- a/rpc/src/v1/tests/mocked/web3.rs +++ b/rpc/src/v1/tests/mocked/web3.rs @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use jsonrpc_core::{IoHandler, GenericIoHandler}; +use jsonrpc_core::IoHandler; use util::version; use v1::{Web3, Web3Client}; #[test] fn rpc_web3_version() { let web3 = Web3Client::new().to_delegate(); - let io = IoHandler::new(); - io.add_delegate(web3); + let mut io = IoHandler::new(); + io.extend_with(web3); let v = version().to_owned().replace("Parity/", "Parity//"); @@ -35,8 +35,8 @@ fn rpc_web3_version() { #[test] fn rpc_web3_sha3() { let web3 = Web3Client::new().to_delegate(); - let io = IoHandler::new(); - io.add_delegate(web3); + let mut io = IoHandler::new(); + io.extend_with(web3); let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x00"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a","id":1}"#; @@ -47,8 +47,8 @@ fn rpc_web3_sha3() { #[test] fn rpc_web3_sha3_wiki() { let web3 = Web3Client::new().to_delegate(); - let io = IoHandler::new(); - io.add_delegate(web3); + let mut io = IoHandler::new(); + io.extend_with(web3); let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x68656c6c6f20776f726c64"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad","id":1}"#; diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 2d52b7c7002..fa63858db78 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -16,16 +16,19 @@ //! Eth rpc interface. use jsonrpc_core::Error; +use jsonrpc_macros::Trailing; + +use futures::BoxFuture; -use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index, DappId}; +use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index}; use v1::types::{Log, Receipt, SyncStatus, Transaction, Work}; use v1::types::{H64, H160, H256, U256}; -use jsonrpc_macros::Trailing; - build_rpc_trait! { /// Eth rpc interface. pub trait Eth { + type Metadata; + /// Returns protocol version encoded as a string (quotes are necessary). #[rpc(name = "eth_protocolVersion")] fn protocol_version(&self) -> Result; @@ -51,8 +54,8 @@ build_rpc_trait! { fn gas_price(&self) -> Result; /// Returns accounts list. - #[rpc(name = "eth_accounts")] - fn accounts(&self, Trailing) -> Result, Error>; + #[rpc(meta, name = "eth_accounts")] + fn accounts(&self, Self::Metadata) -> BoxFuture, Error>; /// Returns highest block number. #[rpc(name = "eth_blockNumber")] diff --git a/rpc/src/v1/traits/eth_signing.rs b/rpc/src/v1/traits/eth_signing.rs index 44288333934..bc16e9e04df 100644 --- a/rpc/src/v1/traits/eth_signing.rs +++ b/rpc/src/v1/traits/eth_signing.rs @@ -16,7 +16,8 @@ //! Eth rpc interface. -use jsonrpc_macros::Ready; +use jsonrpc_core::Error; +use futures::BoxFuture; use v1::types::{Bytes, H160, H256, H520, TransactionRequest, RichRawTransaction}; @@ -25,18 +26,18 @@ build_rpc_trait! { pub trait EthSigning { /// Signs the hash of data with given address signature. #[rpc(async, name = "eth_sign")] - fn sign(&self, Ready, H160, Bytes); + fn sign(&self, H160, Bytes) -> BoxFuture; /// Sends transaction; will block waiting for signer to return the /// transaction hash. /// If Signer is disable it will require the account to be unlocked. #[rpc(async, name = "eth_sendTransaction")] - fn send_transaction(&self, Ready, TransactionRequest); + fn send_transaction(&self, TransactionRequest) -> BoxFuture; /// Signs transactions without dispatching it to the network. /// Returns signed transaction RLP representation and the transaction itself. /// It can be later submitted using `eth_sendRawTransaction/eth_submitTransaction`. #[rpc(async, name = "eth_signTransaction")] - fn sign_transaction(&self, Ready, TransactionRequest); + fn sign_transaction(&self, TransactionRequest) -> BoxFuture; } } diff --git a/rpc/src/v1/traits/parity_set.rs b/rpc/src/v1/traits/parity_set.rs index f3e83bb5589..197be547138 100644 --- a/rpc/src/v1/traits/parity_set.rs +++ b/rpc/src/v1/traits/parity_set.rs @@ -17,7 +17,7 @@ //! Parity-specific rpc interface for operations altering the settings. use jsonrpc_core::Error; -use jsonrpc_macros::Ready; +use futures::BoxFuture; use v1::types::{Bytes, H160, H256, U256, ReleaseInfo}; @@ -90,7 +90,7 @@ build_rpc_trait! { /// Hash a file content under given URL. #[rpc(async, name = "parity_hashContent")] - fn hash_content(&self, Ready, String); + fn hash_content(&self, String) -> BoxFuture; /// Is there a release ready for install? #[rpc(name = "parity_upgradeReady")] diff --git a/rpc/src/v1/traits/parity_signing.rs b/rpc/src/v1/traits/parity_signing.rs index a6fdbe2cdea..9b21fee17c4 100644 --- a/rpc/src/v1/traits/parity_signing.rs +++ b/rpc/src/v1/traits/parity_signing.rs @@ -16,7 +16,7 @@ //! ParitySigning rpc interface. use jsonrpc_core::Error; -use jsonrpc_macros::Ready; +use futures::BoxFuture; use v1::types::{U256, H160, H256, Bytes, ConfirmationResponse, TransactionRequest, Either}; @@ -41,6 +41,6 @@ build_rpc_trait! { /// Decrypt some ECIES-encrypted message. /// First parameter is the address with which it is encrypted, second is the ciphertext. #[rpc(async, name = "parity_decryptMessage")] - fn decrypt_message(&self, Ready, H160, Bytes); + fn decrypt_message(&self, H160, Bytes) -> BoxFuture; } } diff --git a/signer/src/lib.rs b/signer/src/lib.rs index 196fb4fae6e..9797483a5da 100644 --- a/signer/src/lib.rs +++ b/signer/src/lib.rs @@ -29,16 +29,22 @@ //! the transaction for you. //! //! ``` +//! extern crate jsonrpc_core; //! extern crate ethcore_signer; //! extern crate ethcore_rpc; //! //! use std::sync::Arc; +//! use jsonrpc_core::IoHandler; +//! use jsonrpc_core::reactor::RpcEventLoop; //! use ethcore_signer::ServerBuilder; //! use ethcore_rpc::ConfirmationsQueue; //! //! fn main() { //! let queue = Arc::new(ConfirmationsQueue::default()); -//! let _server = ServerBuilder::new(queue, "/tmp/authcodes".into()).start("127.0.0.1:8084".parse().unwrap()); +//! let io = Arc::new(IoHandler::new().into()); +//! let event_loop = RpcEventLoop::spawn(); +//! let _server = ServerBuilder::new(queue, "/tmp/authcodes".into()) +//! .start("127.0.0.1:8084".parse().unwrap(), event_loop.handler(io)); //! } //! ``` @@ -48,8 +54,8 @@ extern crate env_logger; extern crate rand; extern crate ethcore_util as util; -extern crate ethcore_io as io; extern crate ethcore_rpc as rpc; +extern crate ethcore_io as io; extern crate jsonrpc_core; extern crate ws; diff --git a/signer/src/tests/mod.rs b/signer/src/tests/mod.rs index ab46a0e6f9c..3139aaf99fc 100644 --- a/signer/src/tests/mod.rs +++ b/signer/src/tests/mod.rs @@ -21,6 +21,8 @@ use devtools::http_client; use devtools::RandomTempPath; use rpc::ConfirmationsQueue; +use jsonrpc_core::IoHandler; +use jsonrpc_core::reactor::RpcEventLoop; use rand; use ServerBuilder; @@ -45,14 +47,36 @@ impl DerefMut for GuardedAuthCodes { } } -/// Setup a mock signer for testsp -pub fn serve() -> (Server, usize, GuardedAuthCodes) { +/// Server with event loop +pub struct ServerLoop { + /// Signer Server + pub server: Server, + /// RPC Event Loop + pub event_loop: RpcEventLoop, +} + +impl Deref for ServerLoop { + type Target = Server; + + fn deref(&self) -> &Self::Target { + &self.server + } +} + +/// Setup a mock signer for tests +pub fn serve() -> (ServerLoop, usize, GuardedAuthCodes) { let mut path = RandomTempPath::new(); path.panic_on_drop_failure = false; let queue = Arc::new(ConfirmationsQueue::default()); let builder = ServerBuilder::new(queue, path.to_path_buf()); let port = 35000 + rand::random::() % 10000; - let res = builder.start(format!("127.0.0.1:{}", port).parse().unwrap()).unwrap(); + let event_loop = RpcEventLoop::spawn(); + let handler = event_loop.handler(Arc::new(IoHandler::default().into())); + let server = builder.start(format!("127.0.0.1:{}", port).parse().unwrap(), handler).unwrap(); + let res = ServerLoop { + server: server, + event_loop: event_loop, + }; (res, port, GuardedAuthCodes { authcodes: AuthCodes::from_file(&path).unwrap(), @@ -61,8 +85,8 @@ pub fn serve() -> (Server, usize, GuardedAuthCodes) { } /// Test a single request to running server -pub fn request(server: Server, request: &str) -> http_client::Response { - http_client::request(server.addr(), request) +pub fn request(server: ServerLoop, request: &str) -> http_client::Response { + http_client::request(server.server.addr(), request) } #[cfg(test)] diff --git a/signer/src/ws_server/mod.rs b/signer/src/ws_server/mod.rs index 83b0e23e6ce..e73f9dd6d71 100644 --- a/signer/src/ws_server/mod.rs +++ b/signer/src/ws_server/mod.rs @@ -25,8 +25,9 @@ use std::ops::Drop; use std::sync::Arc; use std::net::SocketAddr; use io::{PanicHandler, OnPanicListener, MayPanic}; -use jsonrpc_core::{IoHandler, IoDelegate}; -use rpc::{Extendable, ConfirmationsQueue}; +use jsonrpc_core::Metadata; +use jsonrpc_core::reactor::RpcHandler; +use rpc::ConfirmationsQueue; mod session; @@ -51,23 +52,15 @@ impl From for ServerError { /// Builder for `WebSockets` server pub struct ServerBuilder { queue: Arc, - handler: Arc, authcodes_path: PathBuf, skip_origin_validation: bool, } -impl Extendable for ServerBuilder { - fn add_delegate(&self, delegate: IoDelegate) { - self.handler.add_delegate(delegate); - } -} - impl ServerBuilder { /// Creates new `ServerBuilder` pub fn new(queue: Arc, authcodes_path: PathBuf) -> Self { ServerBuilder { queue: queue, - handler: Arc::new(IoHandler::new()), authcodes_path: authcodes_path, skip_origin_validation: false, } @@ -82,14 +75,14 @@ impl ServerBuilder { /// Starts a new `WebSocket` server in separate thread. /// Returns a `Server` handle which closes the server when droped. - pub fn start(self, addr: SocketAddr) -> Result { - Server::start(addr, self.handler, self.queue, self.authcodes_path, self.skip_origin_validation) + pub fn start(self, addr: SocketAddr, handler: RpcHandler) -> Result { + Server::start(addr, handler, self.queue, self.authcodes_path, self.skip_origin_validation) } } /// `WebSockets` server implementation. pub struct Server { - handle: Option>>, + handle: Option>, broadcaster_handle: Option>, queue: Arc, panic_handler: Arc, @@ -104,7 +97,7 @@ impl Server { /// Starts a new `WebSocket` server in separate thread. /// Returns a `Server` handle which closes the server when droped. - fn start(addr: SocketAddr, handler: Arc, queue: Arc, authcodes_path: PathBuf, skip_origin_validation: bool) -> Result { + fn start(addr: SocketAddr, handler: RpcHandler, queue: Arc, authcodes_path: PathBuf, skip_origin_validation: bool) -> Result { let config = { let mut config = ws::Settings::default(); // accept only handshakes beginning with GET @@ -138,7 +131,7 @@ impl Server { )), Ok(server) => server, } - }).unwrap() + }).unwrap(); }); // Spawn a thread for broadcasting diff --git a/signer/src/ws_server/session.rs b/signer/src/ws_server/session.rs index 852b83f15d7..bf54e01593f 100644 --- a/signer/src/ws_server/session.rs +++ b/signer/src/ws_server/session.rs @@ -21,7 +21,8 @@ use authcode_store::AuthCodes; use std::path::{PathBuf, Path}; use std::sync::Arc; use std::str::FromStr; -use jsonrpc_core::{IoHandler, GenericIoHandler}; +use jsonrpc_core::{Metadata}; +use jsonrpc_core::reactor::RpcHandler; use util::{H256, version}; #[cfg(feature = "parity-ui")] @@ -129,16 +130,16 @@ fn add_headers(mut response: ws::Response, mime: &str) -> ws::Response { response } -pub struct Session { +pub struct Session { out: ws::Sender, skip_origin_validation: bool, self_origin: String, authcodes_path: PathBuf, - handler: Arc, + handler: RpcHandler, file_handler: Arc, } -impl ws::Handler for Session { +impl ws::Handler for Session { #[cfg_attr(feature="dev", allow(collapsible_if))] fn on_request(&mut self, req: &ws::Request) -> ws::Result<(ws::Response)> { trace!(target: "signer", "Handling request: {:?}", req); @@ -209,7 +210,10 @@ impl ws::Handler for Session { fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> { let req = msg.as_text()?; let out = self.out.clone(); - self.handler.handle_request(req, move |response| { + // TODO [ToDr] Extract metadata for PubSub/Session + let metadata = Default::default(); + + self.handler.handle_request(req, metadata, move |response| { if let Some(result) = response { let res = out.send(result); if let Err(e) = res { @@ -221,16 +225,16 @@ impl ws::Handler for Session { } } -pub struct Factory { - handler: Arc, +pub struct Factory { + handler: RpcHandler, skip_origin_validation: bool, self_origin: String, authcodes_path: PathBuf, file_handler: Arc, } -impl Factory { - pub fn new(handler: Arc, self_origin: String, authcodes_path: PathBuf, skip_origin_validation: bool) -> Self { +impl Factory { + pub fn new(handler: RpcHandler, self_origin: String, authcodes_path: PathBuf, skip_origin_validation: bool) -> Self { Factory { handler: handler, skip_origin_validation: skip_origin_validation, @@ -241,8 +245,8 @@ impl Factory { } } -impl ws::Factory for Factory { - type Handler = Session; +impl ws::Factory for Factory { + type Handler = Session; fn connection_made(&mut self, sender: ws::Sender) -> Self::Handler { Session { diff --git a/stratum/Cargo.toml b/stratum/Cargo.toml index 3b467b8f3da..412d08904c9 100644 --- a/stratum/Cargo.toml +++ b/stratum/Cargo.toml @@ -12,6 +12,7 @@ ethcore-ipc-codegen = { path = "../ipc/codegen" } [dependencies] log = "0.3" jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-macros = { 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" } diff --git a/stratum/src/lib.rs b/stratum/src/lib.rs index bb0ca7b22ea..1ff0100b3be 100644 --- a/stratum/src/lib.rs +++ b/stratum/src/lib.rs @@ -18,6 +18,7 @@ extern crate jsonrpc_tcp_server; extern crate jsonrpc_core; +extern crate jsonrpc_macros; #[macro_use] extern crate log; extern crate ethcore_util as util; extern crate ethcore_ipc as ipc; @@ -45,16 +46,33 @@ pub use traits::{ }; use jsonrpc_tcp_server::Server as JsonRpcServer; -use jsonrpc_core::{IoHandler, Params, IoDelegate, to_value, from_params}; +use jsonrpc_core::{IoHandler, Params, to_value}; +use jsonrpc_macros::IoDelegate; use std::sync::Arc; use std::net::SocketAddr; use std::collections::{HashSet, HashMap}; use util::{H256, Hashable, RwLock, RwLockReadGuard}; +type RpcResult = Result; + +struct StratumRpc { + stratum: RwLock>>, +} +impl StratumRpc { + fn subscribe(&self, params: Params) -> RpcResult { + self.stratum.read().as_ref().expect("RPC methods are called after stratum is set.") + .subscribe(params) + } + + fn authorize(&self, params: Params) -> RpcResult { + self.stratum.read().as_ref().expect("RPC methods are called after stratum is set.") + .authorize(params) + } +} + pub struct Stratum { - rpc_server: JsonRpcServer, - handler: Arc, + rpc_server: JsonRpcServer<()>, /// Subscribed clients subscribers: RwLock>, /// List of workers supposed to receive job update @@ -73,29 +91,32 @@ impl Stratum { dispatcher: Arc, secret: Option, ) -> Result, jsonrpc_tcp_server::Error> { - let handler = Arc::new(IoHandler::new()); - let server = JsonRpcServer::new(addr, &handler)?; + let rpc = Arc::new(StratumRpc { + stratum: RwLock::new(None), + }); + let mut delegate = IoDelegate::::new(rpc.clone()); + delegate.add_method("miner.subscribe", StratumRpc::subscribe); + delegate.add_method("miner.authorize", StratumRpc::authorize); + + let mut handler = IoHandler::default(); + handler.extend_with(delegate); + let server = JsonRpcServer::new(addr, handler)?; let stratum = Arc::new(Stratum { rpc_server: server, - handler: handler, subscribers: RwLock::new(Vec::new()), job_que: RwLock::new(HashSet::new()), dispatcher: dispatcher, workers: Arc::new(RwLock::new(HashMap::new())), secret: secret, }); - - let mut delegate = IoDelegate::::new(stratum.clone()); - delegate.add_method("miner.subscribe", Stratum::subscribe); - delegate.add_method("miner.authorize", Stratum::authorize); - stratum.handler.add_delegate(delegate); + *rpc.stratum.write() = Some(stratum.clone()); stratum.rpc_server.run_async()?; Ok(stratum) } - fn subscribe(&self, _params: Params) -> std::result::Result { + fn subscribe(&self, _params: Params) -> RpcResult { use std::str::FromStr; if let Some(context) = self.rpc_server.request_context() { @@ -115,8 +136,8 @@ impl Stratum { }) } - fn authorize(&self, params: Params) -> std::result::Result { - from_params::<(String, String)>(params).map(|(worker_id, secret)|{ + fn authorize(&self, params: Params) -> RpcResult { + params.parse::<(String, String)>().map(|(worker_id, secret)|{ if let Some(valid_secret) = self.secret { let hash = secret.sha3(); if hash != valid_secret { diff --git a/util/fetch/src/client.rs b/util/fetch/src/client.rs index bbc9f11e8ce..6c8921432fe 100644 --- a/util/fetch/src/client.rs +++ b/util/fetch/src/client.rs @@ -47,8 +47,10 @@ pub trait Fetch: Clone + Send + Sync + 'static { /// Spawn the future in context of this `Fetch` thread pool. /// Implementation is optional. - fn process(&self, f: F) -> BoxFuture<(), ()> where - F: Future + Send + 'static, + fn process(&self, f: F) -> BoxFuture where + F: Future + Send + 'static, + I: Send + 'static, + E: Send + 'static, { f.boxed() } @@ -99,8 +101,10 @@ impl Fetch for Client { Self::with_limit(Some(50*1024*1024)) } - fn process(&self, f: F) -> BoxFuture<(), ()> where - F: Future + Send + 'static, + fn process(&self, f: F) -> BoxFuture where + F: Future + Send + 'static, + I: Send + 'static, + E: Send + 'static, { self.pool.spawn(f).boxed() } diff --git a/util/reactor/src/lib.rs b/util/reactor/src/lib.rs index dc33393767a..a9d2aedbd4c 100644 --- a/util/reactor/src/lib.rs +++ b/util/reactor/src/lib.rs @@ -57,6 +57,17 @@ impl EventLoop { } } + /// Returns this event loop raw remote. + /// + /// Deprecated: Exists only to connect with current JSONRPC implementation. + pub fn raw_remote(&self) -> TokioRemote { + if let Mode::Tokio(ref remote) = self.remote.inner { + remote.clone() + } else { + panic!("Event loop is never initialized in other mode then Tokio.") + } + } + /// Returns event loop remote. pub fn remote(&self) -> Remote { self.remote.clone() @@ -76,6 +87,15 @@ pub struct Remote { } impl Remote { + /// Remote for existing event loop. + /// + /// Deprecated: Exists only to connect with current JSONRPC implementation. + pub fn new(remote: TokioRemote) -> Self { + Remote { + inner: Mode::Tokio(remote), + } + } + /// Synchronous remote, used mostly for tests. pub fn new_sync() -> Self { Remote {