From 53bf8a26ac23acd92f33b3347660ee7616a2addd Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 7 Dec 2016 13:30:31 +0300 Subject: [PATCH 1/4] copypasted RPC framework from Parity --- Cargo.lock | 214 ++++++++++++++++++++ Cargo.toml | 1 + rpc/Cargo.toml | 22 +++ rpc/build.rs | 41 ++++ rpc/src/lib.rs | 10 + rpc/src/v1/helpers/auto_args.rs | 294 ++++++++++++++++++++++++++++ rpc/src/v1/helpers/errors.rs | 24 +++ rpc/src/v1/helpers/mod.rs | 5 + rpc/src/v1/helpers/params.rs | 11 ++ rpc/src/v1/impls/mod.rs | 3 + rpc/src/v1/impls/raw.rs | 11 ++ rpc/src/v1/mod.rs | 5 + rpc/src/v1/traits/mod.rs | 3 + rpc/src/v1/traits/raw.rs | 13 ++ rpc/src/v1/types/bytes.rs | 98 ++++++++++ rpc/src/v1/types/mod.rs | 7 + rpc/src/v1/types/mod.rs.in | 4 + rpc/src/v1/types/raw_transaction.rs | 9 + tools/clippy.sh | 1 + tools/test.sh | 1 + 20 files changed, 777 insertions(+) create mode 100644 rpc/Cargo.toml create mode 100644 rpc/build.rs create mode 100644 rpc/src/lib.rs create mode 100644 rpc/src/v1/helpers/auto_args.rs create mode 100644 rpc/src/v1/helpers/errors.rs create mode 100644 rpc/src/v1/helpers/mod.rs create mode 100644 rpc/src/v1/helpers/params.rs create mode 100644 rpc/src/v1/impls/mod.rs create mode 100644 rpc/src/v1/impls/raw.rs create mode 100644 rpc/src/v1/mod.rs create mode 100644 rpc/src/v1/traits/mod.rs create mode 100644 rpc/src/v1/traits/raw.rs create mode 100644 rpc/src/v1/types/bytes.rs create mode 100644 rpc/src/v1/types/mod.rs create mode 100644 rpc/src/v1/types/mod.rs.in create mode 100644 rpc/src/v1/types/raw_transaction.rs diff --git a/Cargo.lock b/Cargo.lock index 0ada53b9..7f759416 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,6 +61,14 @@ dependencies = [ "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aster" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "base58" version = "0.1.0" @@ -190,6 +198,11 @@ dependencies = [ "tokio-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dtoa" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" version = "0.5.0" @@ -267,6 +280,23 @@ dependencies = [ "serialization 0.1.0", ] +[[package]] +name = "itoa" +version = "0.1.1" +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#1500da1b9613a0a17fc0109d825f3ccc60199a53" +dependencies = [ + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -444,6 +474,11 @@ dependencies = [ "tokio-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" version = "1.2.0" @@ -492,6 +527,17 @@ dependencies = [ "tokio-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot" version = "0.3.6" @@ -531,6 +577,7 @@ dependencies = [ "miner 0.1.0", "network 0.1.0", "p2p 0.1.0", + "rpc 0.1.0", "script 0.1.0", "sync 0.1.0", "verification 0.1.0", @@ -545,6 +592,34 @@ dependencies = [ "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quasi" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quasi_codegen" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aster 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quasi_macros" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quasi_codegen 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.1.0" @@ -604,6 +679,19 @@ dependencies = [ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rpc" +version = "0.1.0" +dependencies = [ + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.21 (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.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_macros 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rust-crypto" version = "0.2.36" @@ -666,6 +754,53 @@ name = "semver" version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "serde" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_codegen" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aster 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_codegen 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_macros 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen_internals 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_codegen_internals" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +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)", + "itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_macros" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_codegen 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serialization" version = "0.1.0" @@ -733,6 +868,60 @@ dependencies = [ "verification 0.1.0", ] +[[package]] +name = "syntex" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_errors" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.17 (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.21 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.44.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.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_syntax" +version = "0.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.17 (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.21 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.44.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 = "term" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "term_size" version = "0.2.1" @@ -802,6 +991,11 @@ name = "unicode-width" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "utf8-ranges" version = "0.1.3" @@ -857,6 +1051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4" "checksum arrayvec 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d89f1b0e242270b5b797778af0c8d182a1a2ccac5d8d6fadf414223cc0fab096" +"checksum aster 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258989846dd255a1e0eeef92d425d345477c9999433cecc9f0879f4549d5e5c9" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" @@ -868,6 +1063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf" "checksum domain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "725459994103308a8476a95d8115280b1359dccc06ca14291df75f37459a9e30" +"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d" "checksum elastic-array 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bc9250a632e7c001b741eb0ec6cee93c9a5b6d5f1879696a4b94d62b012210a" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum eth-secp256k1 0.5.6 (git+https://github.com/ethcore/rust-secp256k1)" = "" @@ -875,6 +1071,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82" "checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5" "checksum heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8c80e194758495a9109566134dc06e42ea0423987d6ceca016edaa90381b3549" +"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 kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b" "checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b" @@ -889,12 +1087,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b" "checksum nodrop 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbadd3f4c98dea0bd3d9b4be4c0cdaf1ab57035cb2e41fce3983db5add7cc5" "checksum ns-dns-tokio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43330aab5077c311b390b62147feb44316cb5b754b97d28c92210e6c6b7baff7" +"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c" "checksum num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55aabf4e2d6271a2e4e4c0f2ea1f5b07cc589cc1a9e9213013b54a76678ca4f3" "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" +"checksum parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "968f685642555d2f7e202c48b8b11de80569e9bfea817f7f12d7c61aac62d4e6" "checksum parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e1435e7a2a00dfebededd6c6bdbd54008001e94b4a2aadd6aef0dc4c56317621" "checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" +"checksum quasi 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94a532453b931a4483a5b2e40f0fe04aee35b6bc2c0eeec876f1bd2358a134d3" +"checksum quasi_codegen 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb4a9a5410fdbdacbeda8063ddb8add9838dfd4cf50ac486db98abb762d8bd6" +"checksum quasi_macros 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "adc2b36285ea5e54e4e267f83896267ff8c5aba4f66b2e7d186ed6d968f3715f" "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum rayon 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0783f5880c56f5a308e219ac9309dbe781e064741dd5def4c617c440890305" @@ -909,11 +1112,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" +"checksum serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)" = "58a19c0871c298847e6b68318484685cd51fa5478c0c905095647540031356e5" +"checksum serde_codegen 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "da68810d845f8e33a80243c28794650397056cbe7aea4c9c7516f55d1061c94e" +"checksum serde_codegen_internals 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0115c5c602e81c61b787fb0f0fa76a614f8dbe9100b2b59b7d590155672c80" +"checksum serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7d3c184d35801fb8b32b46a7d58d57dbcc150b0eb2b46a1eb79645e8ecfd5b" +"checksum serde_macros 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c3cf1c01933271e1e72bb788e0499d1bca8af2c09efcc3ddc0b04ff22d080b83" "checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d" "checksum siphasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "833011ca526bd88f16778d32c699d325a9ad302fa06381cd66f7be63351d3f6d" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410" "checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" +"checksum syntex 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84f37b94d7ee762bcac58741f73a95465cf87188c3b93f10df9245aff821b2b4" +"checksum syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0d95d2141ae79f312a01c6934d9984f9d7f5cfaf0c74aae5fbbc234a6dcb77a" +"checksum syntex_pos 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2cbf0598c5970f2dca122a4e6f7e93bf42f2d0b2dd88c3ea112413152864df" +"checksum syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5a89ee386d492cdd3855becec489c25797bb91bcbb3c2478c41969b24cb318a2" +"checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a" "checksum term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7f5f3f71b0040cecc71af239414c23fd3c73570f5ff54cf50e03cef637f2a0" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" @@ -921,6 +1134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "06f40e15561569e24dab3dcf270c0bb950195b84dbed591dfb6591e28c9b9cff" "checksum unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b905d0fc2a1f0befd86b0e72e31d1787944efef9d38b9358a9e92a69757f7e3b" "checksum unicode-width 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6722facc10989f63ee0e20a83cd4e1714a9ae11529403ac7e0afd069abc39e" +"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum variance 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3abfc2be1fb59663871379ea884fd81de80c496f2274e021c01d6fe56cd77b05" "checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f" diff --git a/Cargo.toml b/Cargo.toml index 0b68f84d..2e72bc53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ sync = { path = "sync" } import = { path = "import" } bencher = { path = "bencher" } logs = { path = "logs" } +rpc = { path = "rpc" } [[bin]] path = "pbtc/main.rs" diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml new file mode 100644 index 00000000..37b7743f --- /dev/null +++ b/rpc/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "rpc" +version = "0.1.0" +authors = ["Ethcore "] +build = "build.rs" + +[lib] + +[dependencies] +log = "0.3" +serde = "0.8" +serde_json = "0.8" +rustc-serialize = "0.3" +serde_macros = { version = "0.8.0", optional = true } +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } + +[build-dependencies] +serde_codegen = { version = "0.8.0", optional = true } + +[features] +default = ["serde_codegen"] +nightly = ["serde_macros"] diff --git a/rpc/build.rs b/rpc/build.rs new file mode 100644 index 00000000..31dc032d --- /dev/null +++ b/rpc/build.rs @@ -0,0 +1,41 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +#[cfg(not(feature = "serde_macros"))] +mod inner { + extern crate serde_codegen; + + use std::env; + use std::path::Path; + + pub fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let src = Path::new("src/v1/types/mod.rs.in"); + let dst = Path::new(&out_dir).join("mod.rs"); + + serde_codegen::expand(&src, &dst).unwrap(); + } +} + +#[cfg(feature = "serde_macros")] +mod inner { + pub fn main() {} +} + +fn main() { + inner::main(); +} \ No newline at end of file diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs new file mode 100644 index 00000000..d0975afe --- /dev/null +++ b/rpc/src/lib.rs @@ -0,0 +1,10 @@ +#![cfg_attr(feature="nightly", plugin(serde_macros))] + +#[macro_use] +extern crate log; +extern crate rustc_serialize; +extern crate serde; +extern crate serde_json; +extern crate jsonrpc_core; + +pub mod v1; diff --git a/rpc/src/v1/helpers/auto_args.rs b/rpc/src/v1/helpers/auto_args.rs new file mode 100644 index 00000000..f60f7425 --- /dev/null +++ b/rpc/src/v1/helpers/auto_args.rs @@ -0,0 +1,294 @@ +// because we reuse the type names as idents in the macros as a dirty hack to +// work around `concat_idents!` being unstable. +#![allow(non_snake_case)] + +///! Automatically serialize and deserialize parameters around a strongly-typed function. + +use super::errors; + +use jsonrpc_core::{Error, Params, Value, from_params, to_value}; +use serde::{Serialize, Deserialize}; + +/// Auto-generates an RPC trait from trait definition. +/// +/// This just copies out all the methods, docs, and adds another +/// function `to_delegate` which will automatically wrap each strongly-typed +/// function in a wrapper which handles parameter and output type serialization. +/// +/// RPC functions may come in a couple forms: async and synchronous. +/// These are parsed with the custom `#[rpc]` attribute, which must follow +/// documentation. +/// +/// ## The #[rpc] attribute +/// +/// Valid forms: +/// - `#[rpc(name = "name_here")]` (a synchronous rpc function which should be bound to the given name) +/// - `#[rpc(async, name = "name_here")]` (an async rpc function which should be bound to the given name) +/// +/// Synchronous function format: +/// `fn foo(&self, Param1, Param2, Param3) -> Out`. +/// +/// Asynchronous RPC functions must come in this form: +/// `fn foo(&self, Param1, Param2, Param3, Ready); +/// +/// Anything else will be rejected by the code generator. +macro_rules! build_rpc_trait { + // entry-point. todo: make another for traits w/ bounds. + ( + $(#[$t_attr: meta])* + pub trait $name: ident { + $( + $( #[doc=$m_doc:expr] )* + #[ rpc( $($t:tt)* ) ] + fn $m_name: ident ( $($p: tt)* ) $( -> Result<$out: ty, Error> )* ; + )* + } + ) => { + $(#[$t_attr])* + pub trait $name: Sized + Send + Sync + 'static { + $( + $(#[doc=$m_doc])* + fn $m_name ( $($p)* ) $( -> Result<$out, Error> )* ; + )* + + /// Transform this into an `IoDelegate`, automatically wrapping + /// the parameters. + fn to_delegate(self) -> ::jsonrpc_core::IoDelegate { + let mut del = ::jsonrpc_core::IoDelegate::new(self.into()); + $( + build_rpc_trait!(WRAP del => + ( $($t)* ) + fn $m_name ( $($p)* ) $( -> Result<$out, Error> )* + ); + )* + del + } + } + }; + + ( WRAP $del: expr => + (name = $name: expr) + fn $method: ident (&self $(, $param: ty)*) -> Result<$out: ty, Error> + ) => { + $del.add_method($name, move |base, params| { + (Self::$method as fn(&_ $(, $param)*) -> Result<$out, Error>).wrap_rpc(base, params) + }) + }; + + ( WRAP $del: expr => + (async, name = $name: expr) + fn $method: ident (&self, Ready<$out: ty> $(, $param: ty)*) + ) => { + $del.add_async_method($name, move |base, params, ready| { + (Self::$method as fn(&_, Ready<$out> $(, $param)*)).wrap_rpc(base, params, ready) + }) + }; +} + +/// A wrapper type without an implementation of `Deserialize` +/// which allows a special implementation of `Wrap` for functions +/// that take a trailing default parameter. +pub struct Trailing(pub T); + +/// A wrapper type for `jsonrpc_core`'s weakly-typed `Ready` struct. +pub struct Ready { + inner: ::jsonrpc_core::Ready, + _marker: ::std::marker::PhantomData, +} + +impl From<::jsonrpc_core::Ready> for Ready { + fn from(ready: ::jsonrpc_core::Ready) -> Self { + Ready { inner: ready, _marker: ::std::marker::PhantomData } + } +} + +impl Ready { + /// Respond withthe asynchronous result. + pub fn ready(self, result: Result) { + self.inner.ready(result.map(to_value)) + } +} + +/// Wrapper trait for synchronous RPC functions. +pub trait Wrap { + fn wrap_rpc(&self, base: &B, params: Params) -> Result; +} + +/// Wrapper trait for asynchronous RPC functions. +pub trait WrapAsync { + fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready); +} + +// special impl for no parameters. +impl Wrap for fn(&B) -> Result + where B: Send + Sync + 'static, OUT: Serialize +{ + fn wrap_rpc(&self, base: &B, params: Params) -> Result { + ::v1::helpers::params::expect_no_params(params) + .and_then(|()| (self)(base)) + .map(to_value) + } +} + +impl WrapAsync for fn(&B, Ready) + where B: Send + Sync + 'static, OUT: Serialize +{ + fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready) { + match ::v1::helpers::params::expect_no_params(params) { + Ok(()) => (self)(base, ready.into()), + Err(e) => ready.ready(Err(e)), + } + } +} + +// creates a wrapper implementation which deserializes the parameters, +// calls the function with concrete type, and serializes the output. +macro_rules! wrap { + ($($x: ident),+) => { + + // synchronous implementation + impl < + BASE: Send + Sync + 'static, + OUT: Serialize, + $($x: Deserialize,)+ + > Wrap for fn(&BASE, $($x,)+) -> Result { + fn wrap_rpc(&self, base: &BASE, params: Params) -> Result { + from_params::<($($x,)+)>(params).and_then(|($($x,)+)| { + (self)(base, $($x,)+) + }).map(to_value) + } + } + + // asynchronous implementation + impl < + BASE: Send + Sync + 'static, + OUT: Serialize, + $($x: Deserialize,)+ + > WrapAsync for fn(&BASE, Ready, $($x,)+ ) { + fn wrap_rpc(&self, base: &BASE, params: Params, ready: ::jsonrpc_core::Ready) { + match from_params::<($($x,)+)>(params) { + Ok(($($x,)+)) => (self)(base, ready.into(), $($x,)+), + Err(e) => ready.ready(Err(e)), + } + } + } + } +} + +// special impl for no parameters other than block parameter. +impl Wrap for fn(&B, Trailing) -> Result + where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize +{ + fn wrap_rpc(&self, base: &B, params: Params) -> Result { + let len = match params { + Params::Array(ref v) => v.len(), + Params::None => 0, + _ => return Err(errors::invalid_params("not an array", "")), + }; + + let (id,) = match len { + 0 => (T::default(),), + 1 => try!(from_params::<(T,)>(params)), + _ => return Err(Error::invalid_params()), + }; + + (self)(base, Trailing(id)).map(to_value) + } +} + +impl WrapAsync for fn(&B, Ready, Trailing) + where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize +{ + fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready) { + let len = match params { + Params::Array(ref v) => v.len(), + Params::None => 0, + _ => return ready.ready(Err(errors::invalid_params("not an array", ""))), + }; + + let id = match len { + 0 => Ok((T::default(),)), + 1 => from_params::<(T,)>(params), + _ => Err(Error::invalid_params()), + }; + + match id { + Ok((id,)) => (self)(base, ready.into(), Trailing(id)), + Err(e) => ready.ready(Err(e)), + } + } +} + +// similar to `wrap!`, but handles a single default trailing parameter +// accepts an additional argument indicating the number of non-trailing parameters. +macro_rules! wrap_with_trailing { + ($num: expr, $($x: ident),+) => { + // synchronous implementation + impl < + BASE: Send + Sync + 'static, + OUT: Serialize, + $($x: Deserialize,)+ + TRAILING: Default + Deserialize, + > Wrap for fn(&BASE, $($x,)+ Trailing) -> Result { + fn wrap_rpc(&self, base: &BASE, params: Params) -> Result { + let len = match params { + Params::Array(ref v) => v.len(), + Params::None => 0, + _ => return Err(errors::invalid_params("not an array", "")), + }; + + let params = match len - $num { + 0 => from_params::<($($x,)+)>(params) + .map(|($($x,)+)| ($($x,)+ TRAILING::default())), + 1 => from_params::<($($x,)+ TRAILING)>(params) + .map(|($($x,)+ id)| ($($x,)+ id)), + _ => Err(Error::invalid_params()), + }; + + let ($($x,)+ id) = try!(params); + (self)(base, $($x,)+ Trailing(id)).map(to_value) + } + } + + // asynchronous implementation + impl < + BASE: Send + Sync + 'static, + OUT: Serialize, + $($x: Deserialize,)+ + TRAILING: Default + Deserialize, + > WrapAsync for fn(&BASE, Ready, $($x,)+ Trailing) { + fn wrap_rpc(&self, base: &BASE, params: Params, ready: ::jsonrpc_core::Ready) { + let len = match params { + Params::Array(ref v) => v.len(), + Params::None => 0, + _ => return ready.ready(Err(errors::invalid_params("not an array", ""))), + }; + + let params = match len - $num { + 0 => from_params::<($($x,)+)>(params) + .map(|($($x,)+)| ($($x,)+ TRAILING::default())), + 1 => from_params::<($($x,)+ TRAILING)>(params) + .map(|($($x,)+ id)| ($($x,)+ id)), + _ => Err(Error::invalid_params()), + }; + + match params { + Ok(($($x,)+ id)) => (self)(base, ready.into(), $($x,)+ Trailing(id)), + Err(e) => ready.ready(Err(e)) + } + } + } + } +} + +wrap!(A, B, C, D, E); +wrap!(A, B, C, D); +wrap!(A, B, C); +wrap!(A, B); +wrap!(A); + +wrap_with_trailing!(5, A, B, C, D, E); +wrap_with_trailing!(4, A, B, C, D); +wrap_with_trailing!(3, A, B, C); +wrap_with_trailing!(2, A, B); +wrap_with_trailing!(1, A); diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs new file mode 100644 index 00000000..f3dccfb0 --- /dev/null +++ b/rpc/src/v1/helpers/errors.rs @@ -0,0 +1,24 @@ +///! RPC Error codes and error objects + +macro_rules! rpc_unimplemented { + () => (Err(::v1::helpers::errors::unimplemented(None))) +} + +use std::fmt; +use jsonrpc_core::{Error, ErrorCode, Value}; + +pub fn unimplemented(details: Option) -> Error { + Error { + code: ErrorCode::InternalError, + message: "This request is not implemented yet. Please create an issue on Github repo.".into(), + data: details.map(Value::String), + } +} + +pub fn invalid_params(param: &str, details: T) -> Error { + Error { + code: ErrorCode::InvalidParams, + message: format!("Couldn't parse parameters: {}", param), + data: Some(Value::String(format!("{:?}", details))), + } +} diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs new file mode 100644 index 00000000..d2f54233 --- /dev/null +++ b/rpc/src/v1/helpers/mod.rs @@ -0,0 +1,5 @@ +#[macro_use] +pub mod auto_args; +#[macro_use] +pub mod errors; +mod params; diff --git a/rpc/src/v1/helpers/params.rs b/rpc/src/v1/helpers/params.rs new file mode 100644 index 00000000..c0ea9c10 --- /dev/null +++ b/rpc/src/v1/helpers/params.rs @@ -0,0 +1,11 @@ +///! Parameters parsing helpers + +use jsonrpc_core::{Error, Params}; +use v1::helpers::errors; + +pub fn expect_no_params(params: Params) -> Result<(), Error> { + match params { + Params::None => Ok(()), + p => Err(errors::invalid_params("No parameters were expected", p)), + } +} diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs new file mode 100644 index 00000000..f1627f3f --- /dev/null +++ b/rpc/src/v1/impls/mod.rs @@ -0,0 +1,3 @@ +mod raw; + +pub use self::raw::RawClient; diff --git a/rpc/src/v1/impls/raw.rs b/rpc/src/v1/impls/raw.rs new file mode 100644 index 00000000..e8a884a9 --- /dev/null +++ b/rpc/src/v1/impls/raw.rs @@ -0,0 +1,11 @@ +use v1::traits::Raw; +use v1::types::RawTransaction; +use jsonrpc_core::Error; + +pub struct RawClient; + +impl Raw for RawClient { + fn send_raw_transaction(&self, _tx: RawTransaction) -> Result { + rpc_unimplemented!() + } +} diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs new file mode 100644 index 00000000..c3c7a216 --- /dev/null +++ b/rpc/src/v1/mod.rs @@ -0,0 +1,5 @@ +#[macro_use] +pub mod helpers; +pub mod impls; +pub mod traits; +pub mod types; diff --git a/rpc/src/v1/traits/mod.rs b/rpc/src/v1/traits/mod.rs new file mode 100644 index 00000000..e1f17297 --- /dev/null +++ b/rpc/src/v1/traits/mod.rs @@ -0,0 +1,3 @@ +mod raw; + +pub use self::raw::Raw; \ No newline at end of file diff --git a/rpc/src/v1/traits/raw.rs b/rpc/src/v1/traits/raw.rs new file mode 100644 index 00000000..516553d0 --- /dev/null +++ b/rpc/src/v1/traits/raw.rs @@ -0,0 +1,13 @@ +use jsonrpc_core::Error; + +use v1::helpers::auto_args::Wrap; +use v1::types::RawTransaction; + +build_rpc_trait! { + /// Eth rpc interface. + pub trait Raw { + /// Returns protocol version encoded as a string (quotes are necessary). + #[rpc(name = "sendrawtransaction")] + fn send_raw_transaction(&self, RawTransaction) -> Result; + } +} diff --git a/rpc/src/v1/types/bytes.rs b/rpc/src/v1/types/bytes.rs new file mode 100644 index 00000000..348029e8 --- /dev/null +++ b/rpc/src/v1/types/bytes.rs @@ -0,0 +1,98 @@ +///! Serializable wrapper around vector of bytes +use rustc_serialize::hex::{ToHex, FromHex}; +use serde::{Serialize, Serializer, Deserialize, Deserializer, Error}; +use serde::de::Visitor; + +/// Wrapper structure around vector of bytes. +#[derive(Debug, PartialEq, Eq, Default, Hash, Clone)] +pub struct Bytes(pub Vec); + +impl Bytes { + /// Simple constructor. + pub fn new(bytes: Vec) -> Bytes { + Bytes(bytes) + } + + /// Convert back to vector + pub fn to_vec(self) -> Vec { + self.0 + } +} + +impl From> for Bytes { + fn from(bytes: Vec) -> Bytes { + Bytes(bytes) + } +} + +impl Into> for Bytes { + fn into(self) -> Vec { + self.0 + } +} + +impl Serialize for Bytes { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + let mut serialized = "0x".to_owned(); + serialized.push_str(self.0.to_hex().as_ref()); + serializer.serialize_str(serialized.as_ref()) + } +} + +impl Deserialize for Bytes { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(BytesVisitor) + } +} + +struct BytesVisitor; + +impl Visitor for BytesVisitor { + type Value = Bytes; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { + Ok(Bytes::new(try!(FromHex::from_hex(&value[2..]).map_err(|_| Error::custom("invalid hex"))))) + } else { + Err(Error::custom("invalid format")) + } + } + + fn visit_string(&mut self, value: String) -> Result where E: Error { + self.visit_str(value.as_ref()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json; + use rustc_serialize::hex::FromHex; + + #[test] + fn test_bytes_serialize() { + let bytes = Bytes("0123456789abcdef".from_hex().unwrap()); + let serialized = serde_json::to_string(&bytes).unwrap(); + assert_eq!(serialized, r#""0x0123456789abcdef""#); + } + + #[test] + fn test_bytes_deserialize() { + let bytes1: Result = serde_json::from_str(r#""""#); + let bytes2: Result = serde_json::from_str(r#""0x123""#); + let bytes3: Result = serde_json::from_str(r#""0xgg""#); + + let bytes4: Bytes = serde_json::from_str(r#""0x""#).unwrap(); + let bytes5: Bytes = serde_json::from_str(r#""0x12""#).unwrap(); + let bytes6: Bytes = serde_json::from_str(r#""0x0123""#).unwrap(); + + assert!(bytes1.is_err()); + assert!(bytes2.is_err()); + assert!(bytes3.is_err()); + assert_eq!(bytes4, Bytes(vec![])); + assert_eq!(bytes5, Bytes(vec![0x12])); + assert_eq!(bytes6, Bytes(vec![0x1, 0x23])); + } +} diff --git a/rpc/src/v1/types/mod.rs b/rpc/src/v1/types/mod.rs new file mode 100644 index 00000000..208f9f3d --- /dev/null +++ b/rpc/src/v1/types/mod.rs @@ -0,0 +1,7 @@ +///! Structures used in RPC communication + +#[cfg(feature = "serde_macros")] +include!("mod.rs.in"); + +#[cfg(not(feature = "serde_macros"))] +include!(concat!(env!("OUT_DIR"), "/mod.rs")); diff --git a/rpc/src/v1/types/mod.rs.in b/rpc/src/v1/types/mod.rs.in new file mode 100644 index 00000000..61b3b4a6 --- /dev/null +++ b/rpc/src/v1/types/mod.rs.in @@ -0,0 +1,4 @@ +mod bytes; +mod raw_transaction; + +pub use self::raw_transaction::RawTransaction; diff --git a/rpc/src/v1/types/raw_transaction.rs b/rpc/src/v1/types/raw_transaction.rs new file mode 100644 index 00000000..e86b0a18 --- /dev/null +++ b/rpc/src/v1/types/raw_transaction.rs @@ -0,0 +1,9 @@ +//use serde::{Serialize, Deserialize}; +use super::bytes::Bytes; + +/// Raw (serialized) transaction +#[derive(Debug, Serialize, Deserialize)] +pub struct RawTransaction { + /// Serialized transaction data bytes + pub data: Bytes, +} diff --git a/tools/clippy.sh b/tools/clippy.sh index 94b33804..5dfaabcf 100755 --- a/tools/clippy.sh +++ b/tools/clippy.sh @@ -25,6 +25,7 @@ cargo clippy -p miner cargo clippy -p network cargo clippy -p p2p cargo clippy -p primitives +cargo clippy -p rpc cargo clippy -p script cargo clippy -p serialization cargo clippy -p sync diff --git a/tools/test.sh b/tools/test.sh index c6d73892..cc93ee18 100755 --- a/tools/test.sh +++ b/tools/test.sh @@ -13,6 +13,7 @@ cargo test\ -p pbtc\ -p p2p\ -p primitives\ + -p rpc\ -p script\ -p serialization\ -p sync\ From 99aa1c2330046cc42ec04e9dfd4234eea1edf385 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 7 Dec 2016 16:14:52 +0300 Subject: [PATCH 2/4] another porion of parity RPC copypaste --- Cargo.lock | 161 ++++++++++++++++++++++++++++ pbtc/cli.yml | 28 +++++ pbtc/commands/start.rs | 3 + pbtc/config.rs | 23 ++++ pbtc/main.rs | 3 + pbtc/rpc.rs | 61 +++++++++++ pbtc/rpc_apis.rs | 50 +++++++++ rpc/Cargo.toml | 1 + rpc/build.rs | 16 --- rpc/src/lib.rs | 5 + rpc/src/rpc_server.rs | 56 ++++++++++ rpc/src/v1/impls/raw.rs | 8 +- rpc/src/v1/mod.rs | 3 + rpc/src/v1/traits/raw.rs | 6 +- rpc/src/v1/types/bytes.rs | 18 ++-- rpc/src/v1/types/raw_transaction.rs | 8 +- 16 files changed, 414 insertions(+), 36 deletions(-) create mode 100644 pbtc/rpc.rs create mode 100644 pbtc/rpc_apis.rs create mode 100644 rpc/src/rpc_server.rs diff --git a/Cargo.lock b/Cargo.lock index 7f759416..9ff27fd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,6 +148,15 @@ dependencies = [ "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cookie" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam" version = "0.2.10" @@ -270,6 +279,40 @@ dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "httparse" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hyper" +version = "0.10.0-a.0" +source = "git+https://github.com/ethcore/hyper#7d4f7fa0baddcb2b0c523f7c05855d67de94fe88" +dependencies = [ + "cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rotor 0.6.3 (git+https://github.com/ethcore/rotor)", + "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", + "spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "import" version = "0.1.0" @@ -297,6 +340,17 @@ dependencies = [ "serde_json 0.8.4 (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#1500da1b9613a0a17fc0109d825f3ccc60199a53" +dependencies = [ + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -319,6 +373,11 @@ dependencies = [ "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazy_static" version = "0.2.2" @@ -354,6 +413,11 @@ dependencies = [ "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "matches" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memchr" version = "0.1.11" @@ -374,6 +438,14 @@ dependencies = [ "serialization 0.1.0", ] +[[package]] +name = "mime" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miner" version = "0.1.0" @@ -386,6 +458,22 @@ dependencies = [ "test-data 0.1.0", ] +[[package]] +name = "mio" +version = "0.6.1" +source = "git+https://github.com/ethcore/mio.git#ef182bae193a9c7457cd2cf661fcaffb226e3eef" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.6.1" @@ -679,11 +767,24 @@ dependencies = [ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rotor" +version = "0.6.3" +source = "git+https://github.com/ethcore/rotor#c1a2dd0046c5ea2517a5b637fca8ee2e77021e82" +dependencies = [ + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.1 (git+https://github.com/ethcore/mio.git)", + "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rpc" version = "0.1.0" dependencies = [ "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)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -833,6 +934,11 @@ name = "smallvec" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "spmc" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.5.2" @@ -981,6 +1087,27 @@ dependencies = [ "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicase" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-segmentation" version = "0.1.2" @@ -996,6 +1123,15 @@ name = "unicode-xid" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "url" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "utf8-ranges" version = "0.1.3" @@ -1011,6 +1147,15 @@ name = "vec_map" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vecio" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "void" version = "1.0.2" @@ -1059,6 +1204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" "checksum clap 2.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef87e92396a3d29bf7e611c8a595be35ae90d9cb844a3571425900eaca4f51c8" +"checksum cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d53b80dde876f47f03cda35303e368a79b91c70b0d65ecba5fd5280944a08591" "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" "checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf" @@ -1071,15 +1217,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82" "checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5" "checksum heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8c80e194758495a9109566134dc06e42ea0423987d6ceca016edaa90381b3549" +"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" +"checksum hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)" = "" +"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" "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 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.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b" "checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b" "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" "checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" +"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +"checksum mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c93a4bd787ddc6e7833c519b73a50883deb5863d76d9b71eb8216fb7f94e66" +"checksum mio 0.6.1 (git+https://github.com/ethcore/mio.git)" = "" "checksum mio 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "410a1a0ff76f5a226f1e4e3ff1756128e65cd30166e39c3892283e2ac09d5b67" "checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a" "checksum murmur3 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ece7fe85164ffce69891c581b6b035a3c2f66dd3459f299d43d5efff90663e22" @@ -1105,6 +1259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum rocksdb 0.4.5 (git+https://github.com/ethcore/rust-rocksdb)" = "" "checksum rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)" = "" +"checksum rotor 0.6.3 (git+https://github.com/ethcore/rotor)" = "" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "bff9fc1c79f2dec76b253273d07682e94a978bd8f132ded071188122b2af9818" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" @@ -1121,6 +1276,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum siphasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "833011ca526bd88f16778d32c699d325a9ad302fa06381cd66f7be63351d3f6d" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410" +"checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf" "checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" "checksum syntex 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84f37b94d7ee762bcac58741f73a95465cf87188c3b93f10df9245aff821b2b4" "checksum syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0d95d2141ae79f312a01c6934d9984f9d7f5cfaf0c74aae5fbbc234a6dcb77a" @@ -1132,12 +1288,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" "checksum tokio-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "06f40e15561569e24dab3dcf270c0bb950195b84dbed591dfb6591e28c9b9cff" +"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" +"checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f" +"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172" "checksum unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b905d0fc2a1f0befd86b0e72e31d1787944efef9d38b9358a9e92a69757f7e3b" "checksum unicode-width 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6722facc10989f63ee0e20a83cd4e1714a9ae11529403ac7e0afd069abc39e" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" +"checksum url 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "48ccf7bd87a81b769cf84ad556e034541fb90e1cd6d4bc375c822ed9500cd9d7" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum variance 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3abfc2be1fb59663871379ea884fd81de80c496f2274e021c01d6fe56cd77b05" "checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f" +"checksum vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0795a11576d29ae80525a3fda315bf7b534f8feb9d34101e5fe63fb95bb2fd24" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/pbtc/cli.yml b/pbtc/cli.yml index f3b4876c..2c24665f 100644 --- a/pbtc/cli.yml +++ b/pbtc/cli.yml @@ -43,6 +43,34 @@ args: value_name: NET help: Only connect to nodes in network (ipv4 or ipv6) takes_value: true + - no-jsonrpc: + long: no-jsonrpc + help: Disable the JSON-RPC API server + - jsonrpc-port: + long: jsonrpc-port + help: The port portion of the JSONRPC API server + takes_value: true + value_name: PORT + - jsonrpc-interface: + long: jsonrpc-interface + help: The hostname portion of the JSONRPC API server + takes_value: true + value_name: INTERFACE + - jsonrpc-cors: + long: jsonrpc-cors + help: Specify CORS header for JSON-RPC API responses + takes_value: true + value_name: URL + - jsonrpc-apis: + long: jsonrpc-apis + help: Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API name. + takes_value: true + value_name: APIS + - jsonrpc-hosts: + long: jsonrpc-hosts + help: List of allowed Host header values + takes_value: true + value_name: HOSTS subcommands: - import: about: Import blocks from bitcoin core database diff --git a/pbtc/commands/start.rs b/pbtc/commands/start.rs index 43a5c034..38a137c1 100644 --- a/pbtc/commands/start.rs +++ b/pbtc/commands/start.rs @@ -3,6 +3,7 @@ use sync::create_sync_connection_factory; use message::Services; use util::{open_db, init_db, node_table_path}; use {config, p2p, PROTOCOL_VERSION, PROTOCOL_MINIMUM}; +use super::super::rpc; pub fn start(cfg: config::Config) -> Result<(), String> { let mut el = p2p::event_loop(); @@ -35,6 +36,8 @@ pub fn start(cfg: config::Config) -> Result<(), String> { let sync_handle = el.handle(); let sync_connection_factory = create_sync_connection_factory(&sync_handle, cfg.magic, db); + let _http_server = try!(rpc::new_http(cfg.rpc_config)); + let p2p = try!(p2p::P2P::new(p2p_cfg, sync_connection_factory, el.handle()).map_err(|x| x.to_string())); try!(p2p.run().map_err(|_| "Failed to start p2p module")); el.run(p2p::forever()).unwrap(); diff --git a/pbtc/config.rs b/pbtc/config.rs index 863835c9..f0d78aad 100644 --- a/pbtc/config.rs +++ b/pbtc/config.rs @@ -4,6 +4,7 @@ use network::Magic; use p2p::InternetProtocol; use seednodes::{mainnet_seednodes, testnet_seednodes}; use {USER_AGENT, REGTEST_USER_AGENT}; +use rpc::HttpConfiguration as RpcHttpConfig; pub struct Config { pub magic: Magic, @@ -18,6 +19,7 @@ pub struct Config { pub data_dir: Option, pub user_agent: String, pub internet_protocol: InternetProtocol, + pub rpc_config: RpcHttpConfig, } pub const DEFAULT_DB_CACHE: usize = 512; @@ -86,6 +88,8 @@ pub fn parse(matches: &clap::ArgMatches) -> Result { None => InternetProtocol::default(), }; + let rpc_config = try!(parse_rpc_config(magic, matches)); + let config = Config { print_to_console: print_to_console, magic: magic, @@ -99,7 +103,26 @@ pub fn parse(matches: &clap::ArgMatches) -> Result { data_dir: data_dir, user_agent: user_agent.to_string(), internet_protocol: only_net, + rpc_config: rpc_config, }; Ok(config) } + +fn parse_rpc_config(magic: Magic, matches: &clap::ArgMatches) -> Result { + let mut config = RpcHttpConfig::with_port(magic.rpc_port()); + config.enabled = !matches.is_present("no-jsonrpc"); + if !config.enabled { + return Ok(config); + } + + if let Some(port) = matches.value_of("jsonrpc-port") { + config.port = try!(port.parse().map_err(|_| "Invalid JSON RPC port".to_owned())); + } + if let Some(interface) = matches.value_of("jsonrpc-interface") { + config.interface = interface.to_owned(); + } + // TODO: support other options + + Ok(config) +} diff --git a/pbtc/main.rs b/pbtc/main.rs index 8a07f87e..b52a17be 100644 --- a/pbtc/main.rs +++ b/pbtc/main.rs @@ -17,11 +17,14 @@ extern crate network; extern crate p2p; extern crate sync; extern crate import; +extern crate rpc as ethcore_rpc; mod commands; mod config; mod seednodes; mod util; +mod rpc; +mod rpc_apis; use app_dirs::AppInfo; diff --git a/pbtc/rpc.rs b/pbtc/rpc.rs new file mode 100644 index 00000000..30aae30e --- /dev/null +++ b/pbtc/rpc.rs @@ -0,0 +1,61 @@ +use std::net::SocketAddr; +use rpc_apis::{self, ApiSet}; +use ethcore_rpc::{Server, RpcServer, RpcServerError}; +use std::io; + +#[derive(Debug, PartialEq)] +pub struct HttpConfiguration { + pub enabled: bool, + pub interface: String, + pub port: u16, + pub apis: ApiSet, + pub cors: Option>, + pub hosts: Option>, +} + +impl HttpConfiguration { + pub fn with_port(port: u16) -> Self { + HttpConfiguration { + enabled: true, + interface: "127.0.0.1".into(), + port: port, + apis: ApiSet::default(), + cors: None, + hosts: Some(Vec::new()), + } + } +} + +pub fn new_http(conf: HttpConfiguration) -> Result, String> { + if !conf.enabled { + return Ok(None); + } + + let url = format!("{}:{}", conf.interface, conf.port); + let addr = try!(url.parse().map_err(|_| format!("Invalid JSONRPC listen host/port given: {}", url))); + Ok(Some(try!(setup_http_rpc_server(&addr, conf.cors, conf.hosts, conf.apis)))) +} + +pub fn setup_http_rpc_server( + url: &SocketAddr, + cors_domains: Option>, + allowed_hosts: Option>, + apis: ApiSet +) -> Result { + let server = try!(setup_rpc_server(apis)); + // TODO: PanicsHandler + let start_result = server.start_http(url, cors_domains, allowed_hosts); + 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)), + _ => Err(format!("RPC io error: {}", err)), + }, + Err(e) => Err(format!("RPC error: {:?}", e)), + Ok(server) => Ok(server), + } +} + +fn setup_rpc_server(apis: ApiSet) -> Result { + let server = RpcServer::new(); + Ok(rpc_apis::setup_rpc(server, apis)) +} diff --git a/pbtc/rpc_apis.rs b/pbtc/rpc_apis.rs new file mode 100644 index 00000000..a191497d --- /dev/null +++ b/pbtc/rpc_apis.rs @@ -0,0 +1,50 @@ +use std::str::FromStr; +use std::collections::HashSet; +use ethcore_rpc::Extendable; + +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +pub enum Api { + /// Raw + Raw, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum ApiSet { + List(HashSet), +} + +impl Default for ApiSet { + fn default() -> Self { + ApiSet::List(vec![Api::Raw].into_iter().collect()) + } +} + +impl FromStr for Api { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "raw" => Ok(Api::Raw), + api => Err(format!("Unknown api: {}", api)), + } + } +} + +impl ApiSet { + pub fn list_apis(&self) -> HashSet { + match *self { + ApiSet::List(ref apis) => apis.clone(), + } + } +} + +pub fn setup_rpc(server: T, apis: ApiSet) -> T { + use ethcore_rpc::v1::*; + + for api in apis.list_apis() { + match api { + Api::Raw => server.add_delegate(RawClient::new().to_delegate()), + } + } + server +} diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 37b7743f..78fa2e5a 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -13,6 +13,7 @@ serde_json = "0.8" rustc-serialize = "0.3" serde_macros = { version = "0.8.0", optional = true } jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" } [build-dependencies] serde_codegen = { version = "0.8.0", optional = true } diff --git a/rpc/build.rs b/rpc/build.rs index 31dc032d..4de3e062 100644 --- a/rpc/build.rs +++ b/rpc/build.rs @@ -1,19 +1,3 @@ -// Copyright 2015, 2016 Ethcore (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - #[cfg(not(feature = "serde_macros"))] mod inner { extern crate serde_codegen; diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index d0975afe..2ece41fc 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -6,5 +6,10 @@ extern crate rustc_serialize; extern crate serde; extern crate serde_json; extern crate jsonrpc_core; +extern crate jsonrpc_http_server; pub mod v1; +pub mod rpc_server; + +pub use jsonrpc_http_server::{Server, RpcServerError}; +pub use self::rpc_server::{RpcServer, Extendable}; diff --git a/rpc/src/rpc_server.rs b/rpc/src/rpc_server.rs new file mode 100644 index 00000000..95ce83ae --- /dev/null +++ b/rpc/src/rpc_server.rs @@ -0,0 +1,56 @@ +// TODO: panic handler +use std::sync::Arc; +use std::net::SocketAddr; +use jsonrpc_core::{IoHandler, IoDelegate}; +use jsonrpc_http_server::{self, ServerBuilder, Server, RpcServerError}; + +/// An object that can be extended with `IoDelegates` +pub trait Extendable { + /// Add `Delegate` to this object. + fn add_delegate(&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>, + ) -> 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()) + .start_http(addr) + } +} diff --git a/rpc/src/v1/impls/raw.rs b/rpc/src/v1/impls/raw.rs index e8a884a9..0c67dc4f 100644 --- a/rpc/src/v1/impls/raw.rs +++ b/rpc/src/v1/impls/raw.rs @@ -4,8 +4,14 @@ use jsonrpc_core::Error; pub struct RawClient; +impl RawClient { + pub fn new() -> Self { + RawClient { } + } +} + impl Raw for RawClient { - fn send_raw_transaction(&self, _tx: RawTransaction) -> Result { + fn send_raw_transaction(&self, _tx: RawTransaction) -> Result<(), Error> { rpc_unimplemented!() } } diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index c3c7a216..fc31be83 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -3,3 +3,6 @@ pub mod helpers; pub mod impls; pub mod traits; pub mod types; + +pub use self::traits::Raw; +pub use self::impls::RawClient; diff --git a/rpc/src/v1/traits/raw.rs b/rpc/src/v1/traits/raw.rs index 516553d0..e4c208dd 100644 --- a/rpc/src/v1/traits/raw.rs +++ b/rpc/src/v1/traits/raw.rs @@ -4,10 +4,10 @@ use v1::helpers::auto_args::Wrap; use v1::types::RawTransaction; build_rpc_trait! { - /// Eth rpc interface. + /// Partiy-bitcoin raw data interface. pub trait Raw { - /// Returns protocol version encoded as a string (quotes are necessary). + /// Adds transaction to the memory pool && relays it to the peers. #[rpc(name = "sendrawtransaction")] - fn send_raw_transaction(&self, RawTransaction) -> Result; + fn send_raw_transaction(&self, RawTransaction) -> Result<(), Error>; } } diff --git a/rpc/src/v1/types/bytes.rs b/rpc/src/v1/types/bytes.rs index 348029e8..3f7fbb75 100644 --- a/rpc/src/v1/types/bytes.rs +++ b/rpc/src/v1/types/bytes.rs @@ -34,7 +34,7 @@ impl Into> for Bytes { impl Serialize for Bytes { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - let mut serialized = "0x".to_owned(); + let mut serialized = String::new(); serialized.push_str(self.0.to_hex().as_ref()); serializer.serialize_str(serialized.as_ref()) } @@ -53,8 +53,8 @@ impl Visitor for BytesVisitor { type Value = Bytes; fn visit_str(&mut self, value: &str) -> Result where E: Error { - if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { - Ok(Bytes::new(try!(FromHex::from_hex(&value[2..]).map_err(|_| Error::custom("invalid hex"))))) + if value.len() > 0 && value.len() & 1 == 0 { + Ok(Bytes::new(try!(FromHex::from_hex(&value).map_err(|_| Error::custom("invalid hex"))))) } else { Err(Error::custom("invalid format")) } @@ -75,18 +75,18 @@ mod tests { fn test_bytes_serialize() { let bytes = Bytes("0123456789abcdef".from_hex().unwrap()); let serialized = serde_json::to_string(&bytes).unwrap(); - assert_eq!(serialized, r#""0x0123456789abcdef""#); + assert_eq!(serialized, r#""0123456789abcdef""#); } #[test] fn test_bytes_deserialize() { let bytes1: Result = serde_json::from_str(r#""""#); - let bytes2: Result = serde_json::from_str(r#""0x123""#); - let bytes3: Result = serde_json::from_str(r#""0xgg""#); + let bytes2: Result = serde_json::from_str(r#""123""#); + let bytes3: Result = serde_json::from_str(r#""gg""#); - let bytes4: Bytes = serde_json::from_str(r#""0x""#).unwrap(); - let bytes5: Bytes = serde_json::from_str(r#""0x12""#).unwrap(); - let bytes6: Bytes = serde_json::from_str(r#""0x0123""#).unwrap(); + let bytes4: Bytes = serde_json::from_str(r#""""#).unwrap(); + let bytes5: Bytes = serde_json::from_str(r#""12""#).unwrap(); + let bytes6: Bytes = serde_json::from_str(r#""0123""#).unwrap(); assert!(bytes1.is_err()); assert!(bytes2.is_err()); diff --git a/rpc/src/v1/types/raw_transaction.rs b/rpc/src/v1/types/raw_transaction.rs index e86b0a18..2c36e782 100644 --- a/rpc/src/v1/types/raw_transaction.rs +++ b/rpc/src/v1/types/raw_transaction.rs @@ -1,9 +1,3 @@ -//use serde::{Serialize, Deserialize}; use super::bytes::Bytes; -/// Raw (serialized) transaction -#[derive(Debug, Serialize, Deserialize)] -pub struct RawTransaction { - /// Serialized transaction data bytes - pub data: Bytes, -} +pub type RawTransaction = Bytes; From 7598747b2c30aaaab710caccc4b82b21bfd7fed0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 7 Dec 2016 16:24:54 +0300 Subject: [PATCH 3/4] added missing JSON RPC options handling --- pbtc/config.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pbtc/config.rs b/pbtc/config.rs index f0d78aad..50c52856 100644 --- a/pbtc/config.rs +++ b/pbtc/config.rs @@ -3,6 +3,7 @@ use clap; use network::Magic; use p2p::InternetProtocol; use seednodes::{mainnet_seednodes, testnet_seednodes}; +use rpc_apis::ApiSet; use {USER_AGENT, REGTEST_USER_AGENT}; use rpc::HttpConfiguration as RpcHttpConfig; @@ -116,13 +117,21 @@ fn parse_rpc_config(magic: Magic, matches: &clap::ArgMatches) -> Result Date: Wed, 7 Dec 2016 16:31:23 +0300 Subject: [PATCH 4/4] fixed tests --- rpc/src/v1/types/bytes.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/rpc/src/v1/types/bytes.rs b/rpc/src/v1/types/bytes.rs index 3f7fbb75..2cb845ed 100644 --- a/rpc/src/v1/types/bytes.rs +++ b/rpc/src/v1/types/bytes.rs @@ -84,15 +84,13 @@ mod tests { let bytes2: Result = serde_json::from_str(r#""123""#); let bytes3: Result = serde_json::from_str(r#""gg""#); - let bytes4: Bytes = serde_json::from_str(r#""""#).unwrap(); - let bytes5: Bytes = serde_json::from_str(r#""12""#).unwrap(); - let bytes6: Bytes = serde_json::from_str(r#""0123""#).unwrap(); + let bytes4: Bytes = serde_json::from_str(r#""12""#).unwrap(); + let bytes5: Bytes = serde_json::from_str(r#""0123""#).unwrap(); assert!(bytes1.is_err()); assert!(bytes2.is_err()); assert!(bytes3.is_err()); - assert_eq!(bytes4, Bytes(vec![])); - assert_eq!(bytes5, Bytes(vec![0x12])); - assert_eq!(bytes6, Bytes(vec![0x1, 0x23])); + assert_eq!(bytes4, Bytes(vec![0x12])); + assert_eq!(bytes5, Bytes(vec![0x1, 0x23])); } }