diff --git a/Cargo.lock b/Cargo.lock index 77652d907..56bad5f2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,7 +30,7 @@ dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps 1.7.0", @@ -350,7 +350,7 @@ name = "env_logger" version = "0.4.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)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -382,7 +382,7 @@ dependencies = [ name = "ethash" version = "1.7.0" dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.1.0", @@ -420,7 +420,7 @@ dependencies = [ "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "native-contracts 0.1.0", "num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -465,7 +465,7 @@ name = "ethcore-io" version = "1.7.0" dependencies = [ "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.1 (git+https://github.com/paritytech/mio)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -499,7 +499,7 @@ dependencies = [ "ethcore-ipc 1.7.0", "ethcore-ipc-codegen 1.7.0", "ethcore-ipc-nano 1.7.0", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -511,7 +511,7 @@ version = "1.7.0" dependencies = [ "ethcore-ipc 1.7.0", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", ] @@ -524,7 +524,7 @@ dependencies = [ "ethcore-ipc-codegen 1.7.0", "ethcore-ipc-nano 1.7.0", "ethcore-util 1.7.0", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -542,7 +542,7 @@ dependencies = [ "ethcore-util 1.7.0", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "smallvec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -559,7 +559,7 @@ dependencies = [ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 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)", @@ -579,7 +579,7 @@ dependencies = [ "ethkey 0.2.0", "igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.1 (git+https://github.com/paritytech/mio)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "path 0.1.0", @@ -617,7 +617,7 @@ dependencies = [ "jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", "parity-updater 1.7.0", @@ -649,14 +649,15 @@ dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "native-contracts 0.1.0", "parking_lot 0.4.0 (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.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -674,7 +675,7 @@ dependencies = [ "ethcore-util 1.7.0", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-ui 1.7.0", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -698,9 +699,9 @@ dependencies = [ "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-tcp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -719,7 +720,7 @@ dependencies = [ "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -786,7 +787,7 @@ dependencies = [ "ethkey 0.2.0", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wordlist 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -817,7 +818,7 @@ dependencies = [ "ethcore-util 1.7.0", "ethkey 0.2.0", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", @@ -857,7 +858,7 @@ version = "0.1.0" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -922,7 +923,7 @@ dependencies = [ "ethkey 0.2.0", "hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)", "libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -964,7 +965,7 @@ dependencies = [ "cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rotor 0.6.3 (git+https://github.com/paritytech/rotor)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -982,7 +983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1079,7 +1080,7 @@ version = "7.0.0" source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1093,7 +1094,7 @@ dependencies = [ "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1105,7 +1106,7 @@ source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c0 dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-tokio-ipc 0.1.0 (git+https://github.com/nikvolf/parity-tokio-ipc)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1127,7 +1128,7 @@ source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c0 dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)", "tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)", @@ -1140,7 +1141,7 @@ version = "7.0.0" source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1150,8 +1151,8 @@ version = "7.0.0" source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1162,7 +1163,7 @@ source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c0 dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1233,7 +1234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1262,7 +1263,7 @@ name = "mime" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1293,9 +1294,9 @@ 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.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (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)", @@ -1303,16 +1304,16 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.2" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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.21 (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.5 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (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)", ] @@ -1324,8 +1325,8 @@ source = "git+https://github.com/alexcrichton/mio-named-pipes#903dc2f7eac6700c62 dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1336,7 +1337,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1345,7 +1346,7 @@ version = "0.1.5" 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)", - "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "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)", ] @@ -1356,7 +1357,7 @@ version = "0.2.1" 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)", - "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "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)", ] @@ -1439,7 +1440,7 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.23" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1620,7 +1621,7 @@ dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1660,7 +1661,7 @@ dependencies = [ "ethcore-util 1.7.0", "fetch 0.1.0", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", @@ -1689,7 +1690,7 @@ dependencies = [ "ethcore-io 1.7.0", "ethcore-util 1.7.0", "ethkey 0.2.0", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1701,7 +1702,7 @@ name = "parity-reactor" version = "0.1.0" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1713,7 +1714,7 @@ dependencies = [ "ethcore-util 1.7.0", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1728,11 +1729,11 @@ version = "0.1.0" source = "git+https://github.com/nikvolf/parity-tokio-ipc#3d4234de6bdc78688ef803935111003080fd5375" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-line 0.1.0 (git+https://github.com/tokio-rs/tokio-line)", "tokio-named-pipes 0.1.0 (git+https://github.com/alexcrichton/tokio-named-pipes)", "tokio-uds 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1773,7 +1774,7 @@ dependencies = [ "ethcore-util 1.7.0", "ethsync 1.7.0", "ipc-common-types 1.7.0", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-hash-fetch 1.7.0", "parity-reactor 0.1.0", "path 0.1.0", @@ -1992,7 +1993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-native-tls 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)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2043,7 +2044,7 @@ name = "rotor" version = "0.6.3" source = "git+https://github.com/paritytech/rotor#2a3764a830174aa94405593be550e8fc7ecea25a" dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.1 (git+https://github.com/paritytech/mio)", "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2309,7 +2310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "stats" version = "0.1.0" dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2361,7 +2362,7 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (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.58.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2442,14 +2443,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "tokio-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2459,7 +2463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2468,7 +2472,7 @@ version = "0.1.0" source = "git+https://github.com/tokio-rs/tokio-line#482614ae0c82daf584727ae65a80d854fe861f81" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2480,10 +2484,10 @@ source = "git+https://github.com/tomusdrw/tokio-minihttp#8acbafae3e77e7f7eb516b4 dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2495,7 +2499,7 @@ source = "git+https://github.com/alexcrichton/tokio-named-pipes#3a22f8fc9a441b54 dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2504,13 +2508,13 @@ version = "0.1.0" source = "git+https://github.com/tomusdrw/tokio-proto#f6ee08cb594fa2fc1b4178eaaca0855d66e68fd3" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2520,13 +2524,13 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2544,10 +2548,10 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2695,7 +2699,7 @@ source = "git+https://github.com/paritytech/ws-rs.git?branch=parity-1.7#30415c17 dependencies = [ "bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.1 (git+https://github.com/paritytech/mio)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2827,7 +2831,7 @@ dependencies = [ "checksum libusb-sys 0.2.3 (git+https://github.com/paritytech/libusb-sys)" = "" "checksum linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bda158e0dabeb97ee8a401f4d17e479d6b891a14de0bba79d5cc2d4d325b5e48" "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 log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" "checksum lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656fa4dfcb02bcf1063c592ba3ff6a5303ee1f2afe98c8a889e8b1a77c6dfdb7" "checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" @@ -2835,7 +2839,7 @@ dependencies = [ "checksum mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e50bf542f81754ef69e5cea856946a3819f7c09ea97b4903c8bc8a89f74e7b6" "checksum miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d1f4d337a01c32e1f2122510fed46393d53ca35a7f429cb0450abaedfa3ed54" "checksum mio 0.6.1 (git+https://github.com/paritytech/mio)" = "" -"checksum mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5b493dc9fd96bd2077f2117f178172b0765db4dfda3ea4d8000401e6d65d3e80" +"checksum mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f27d38f824a0d267d55b29b171e9e99269a53812e385fa75c1fe700ae254a6a4" "checksum mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)" = "" "checksum mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78437f00d9615c366932cbfe79790b5c2945706ba67cf78378ffacc0069ed9de" "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" @@ -2846,7 +2850,7 @@ dependencies = [ "checksum nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "" "checksum nanomsg-sys 0.5.0 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "" "checksum native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4e52995154bb6f0b41e4379a279482c9387c1632e3798ba4e511ef8c54ee09" -"checksum net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a816012ca11cb47009693c1e0c6130e26d39e4d97ee2a13c50e868ec83e3204" +"checksum net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "18b9642ad6222faf5ce46f6966f59b71b9775ad5758c9e09fcf0a6c8061972b4" "checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b" "checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" "checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e" @@ -2944,7 +2948,7 @@ dependencies = [ "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" "checksum tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aef43048292ca0bae4ab32180e85f6202cf2816c2a210c396a84b99dab9270" -"checksum tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3d1be481b55126f02ef88ff86748086473cb537a949fc4a8f4be403a530ae54b" +"checksum tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "99e958104a67877907c1454386d5482fe8e965a55d60be834a15a44328e7dc76" "checksum tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a278fde45f1be68e44995227d426aaa4841e0980bb0a21b981092f28c3c8473" "checksum tokio-line 0.1.0 (git+https://github.com/tokio-rs/tokio-line)" = "" "checksum tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)" = "" diff --git a/ethkey/src/extended.rs b/ethkey/src/extended.rs index 490014db9..77b35f774 100644 --- a/ethkey/src/extended.rs +++ b/ethkey/src/extended.rs @@ -214,10 +214,10 @@ mod derivation { use rcrypto::sha2::Sha512; use bigint::hash::{H512, H256}; use bigint::prelude::{U256, U512, Uint}; - use secp256k1; use secp256k1::key::{SecretKey, PublicKey}; use SECP256K1; use keccak; + use math::curve_order; use super::{Label, Derivation}; #[derive(Debug)] @@ -233,7 +233,7 @@ mod derivation { // For hardened derivation, pass u32 index at least 2^31 or custom Derivation::Hard(T) enum // // Can panic if passed `private_key` is not a valid secp256k1 private key - // (outside of (0..curve_n()]) field + // (outside of (0..curve_order()]) field pub fn private(private_key: H256, chain_code: H256, index: Derivation) -> (H256, H256) where T: Label { match index { Derivation::Soft(index) => private_soft(private_key, chain_code, index), @@ -260,7 +260,7 @@ mod derivation { } // Can panic if passed `private_key` is not a valid secp256k1 private key - // (outside of (0..curve_n()]) field + // (outside of (0..curve_order()]) field fn private_soft(private_key: H256, chain_code: H256, index: T) -> (H256, H256) where T: Label { let mut data = vec![0u8; 33 + T::len()]; @@ -295,7 +295,7 @@ mod derivation { fn private_add(k1: U256, k2: U256) -> U256 { let sum = U512::from(k1) + U512::from(k2); - modulo(sum, curve_n()) + modulo(sum, curve_order()) } // todo: surely can be optimized @@ -305,12 +305,6 @@ mod derivation { md.into() } - // returns n (for mod(n)) for the secp256k1 elliptic curve - // todo: maybe lazy static - fn curve_n() -> U256 { - H256::from_slice(&secp256k1::constants::CURVE_ORDER).into() - } - pub fn public(public_key: H512, chain_code: H256, derivation: Derivation) -> Result<(H512, H256), Error> where T: Label { let index = match derivation { Derivation::Soft(index) => index, @@ -339,7 +333,7 @@ mod derivation { let new_chain_code = H256::from(&i_512[32..64]); // Generated private key can (extremely rarely) be out of secp256k1 key field - if curve_n() <= new_private.clone().into() { return Err(Error::MissingIndex); } + if curve_order() <= new_private.clone().into() { return Err(Error::MissingIndex); } let new_private_sec = SecretKey::from_slice(&SECP256K1, &*new_private) .expect("Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed"); let mut new_public = PublicKey::from_secret_key(&SECP256K1, &new_private_sec) diff --git a/ethkey/src/keypair.rs b/ethkey/src/keypair.rs index f883c4738..58747e172 100644 --- a/ethkey/src/keypair.rs +++ b/ethkey/src/keypair.rs @@ -27,7 +27,7 @@ pub fn public_to_address(public: &Public) -> Address { result } -#[derive(Clone)] +#[derive(Debug, Clone, PartialEq)] /// secp256k1 key pair pub struct KeyPair { secret: Secret, diff --git a/ethkey/src/math.rs b/ethkey/src/math.rs index 536f4ee7d..cf7012132 100644 --- a/ethkey/src/math.rs +++ b/ethkey/src/math.rs @@ -16,7 +16,9 @@ use super::{SECP256K1, Public, Secret, Error}; use secp256k1::key; -use secp256k1::constants::{GENERATOR_X, GENERATOR_Y}; +use secp256k1::constants::{GENERATOR_X, GENERATOR_Y, CURVE_ORDER}; +use bigint::prelude::U256; +use bigint::hash::H256; /// Inplace multiply public key by secret key (EC point * scalar) pub fn public_mul_secret(public: &mut Public, secret: &Secret) -> Result<(), Error> { @@ -47,6 +49,14 @@ pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> { Ok(()) } +/// Replace public key with its negation (EC point = - EC point) +pub fn public_negate(public: &mut Public) -> Result<(), Error> { + let mut key_public = to_secp256k1_public(public)?; + key_public.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; + set_public(public, &key_public); + Ok(()) +} + /// Return base point of secp256k1 pub fn generation_point() -> Public { let mut public_sec_raw = [0u8; 65]; @@ -61,6 +71,11 @@ pub fn generation_point() -> Public { public } +/// Return secp256k1 elliptic curve order +pub fn curve_order() -> U256 { + H256::from_slice(&CURVE_ORDER).into() +} + fn to_secp256k1_public(public: &Public) -> Result { let public_data = { let mut temp = [4u8; 65]; diff --git a/ethkey/src/secret.rs b/ethkey/src/secret.rs index 9c9fd05ad..e1c5bd2fa 100644 --- a/ethkey/src/secret.rs +++ b/ethkey/src/secret.rs @@ -67,6 +67,15 @@ impl Secret { Ok(()) } + /// Inplace decrease secret key (scalar - 1) + pub fn dec(&mut self) -> Result<(), Error> { + let mut key_secret = self.to_secp256k1_secret()?; + key_secret.add_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; + + *self = key_secret.into(); + Ok(()) + } + /// Inplace multiply one secret key to another (scalar * scalar) pub fn mul(&mut self, other: &Secret) -> Result<(), Error> { let mut key_secret = self.to_secp256k1_secret()?; diff --git a/parity/cli/config.full.toml b/parity/cli/config.full.toml index 56cb60fc5..7301afa50 100644 --- a/parity/cli/config.full.toml +++ b/parity/cli/config.full.toml @@ -69,8 +69,11 @@ pass = "test_pass" [secretstore] disable = false -port = 8082 +nodes = [] +http_interface = "local" +http_port = 8082 interface = "local" +port = 8083 path = "$HOME/.parity/secretstore" [ipfs] diff --git a/parity/cli/config.toml b/parity/cli/config.toml index 5c721c715..b7f2936a1 100644 --- a/parity/cli/config.toml +++ b/parity/cli/config.toml @@ -38,7 +38,8 @@ user = "username" pass = "password" [secretstore] -port = 8082 +http_port = 8082 +port = 8083 [ipfs] enable = false diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 02f0838cc..002ce6efb 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -187,10 +187,18 @@ usage! { // Secret Store flag_no_secretstore: bool = false, or |c: &Config| otry!(c.secretstore).disable.clone(), - flag_secretstore_port: u16 = 8082u16, - or |c: &Config| otry!(c.secretstore).port.clone(), + flag_secretstore_secret: Option = None, + or |c: &Config| otry!(c.secretstore).self_secret.clone().map(Some), + flag_secretstore_nodes: String = "", + or |c: &Config| otry!(c.secretstore).nodes.as_ref().map(|vec| vec.join(",")), flag_secretstore_interface: String = "local", or |c: &Config| otry!(c.secretstore).interface.clone(), + flag_secretstore_port: u16 = 8083u16, + or |c: &Config| otry!(c.secretstore).port.clone(), + flag_secretstore_http_interface: String = "local", + or |c: &Config| otry!(c.secretstore).http_interface.clone(), + flag_secretstore_http_port: u16 = 8082u16, + or |c: &Config| otry!(c.secretstore).http_port.clone(), flag_secretstore_path: String = "$BASE/secretstore", or |c: &Config| otry!(c.secretstore).path.clone(), @@ -454,8 +462,12 @@ struct Dapps { #[derive(Default, Debug, PartialEq, RustcDecodable)] struct SecretStore { disable: Option, - port: Option, + self_secret: Option, + nodes: Option>, interface: Option, + port: Option, + http_interface: Option, + http_port: Option, path: Option, } @@ -697,8 +709,12 @@ mod tests { flag_no_dapps: false, flag_no_secretstore: false, - flag_secretstore_port: 8082u16, + flag_secretstore_secret: None, + flag_secretstore_nodes: "".into(), flag_secretstore_interface: "local".into(), + flag_secretstore_port: 8083u16, + flag_secretstore_http_interface: "local".into(), + flag_secretstore_http_port: 8082u16, flag_secretstore_path: "$HOME/.parity/secretstore".into(), // IPFS @@ -909,8 +925,12 @@ mod tests { }), secretstore: Some(SecretStore { disable: None, - port: Some(8082), + self_secret: None, + nodes: None, interface: None, + port: Some(8083), + http_interface: None, + http_port: Some(8082), path: None, }), ipfs: Some(Ipfs { diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index 7ee2860b1..16f04e55e 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -22,399 +22,408 @@ Usage: parity db kill [options] Operating Options: - --mode MODE Set the operating mode. MODE can be one of: - last - Uses the last-used mode, active if none. - active - Parity continuously syncs the chain. - passive - Parity syncs initially, then sleeps and - wakes regularly to resync. - dark - Parity syncs only when the RPC is active. - offline - Parity doesn't sync. (default: {flag_mode}). - --mode-timeout SECS Specify the number of seconds before inactivity - timeout occurs when mode is dark or passive - (default: {flag_mode_timeout}). - --mode-alarm SECS Specify the number of seconds before auto sleep - reawake timeout occurs when mode is passive - (default: {flag_mode_alarm}). - --auto-update SET Set a releases set to automatically update and - install. - all - All updates in the our release track. - critical - Only consensus/security updates. - none - No updates will be auto-installed. - (default: {flag_auto_update}). - --release-track TRACK Set which release track we should use for updates. - stable - Stable releases. - beta - Beta releases. - nightly - Nightly releases (unstable). - testing - Testing releases (do not use). - current - Whatever track this executable was - released on (default: {flag_release_track}). - --public-node Start Parity as a public web server. Account storage - and transaction signing will be delegated to the UI. - (default: {flag_public_node}). - --no-download Normally new releases will be downloaded ready for - updating. This disables it. Not recommended. - (default: {flag_no_download}). - --no-consensus Force the binary to run even if there are known - issues regarding consensus. Not recommended. - (default: {flag_no_consensus}). - --force-direct Run the originally installed version of Parity, - ignoring any updates that have since been installed. - --chain CHAIN Specify the blockchain type. CHAIN may be either a - JSON chain specification file or olympic, frontier, - homestead, mainnet, morden, ropsten, classic, expanse, - testnet, kovan or dev (default: {flag_chain}). - -d --base-path PATH Specify the base data storage path. - (default: {flag_base_path}). - --db-path PATH Specify the database directory path - (default: {flag_db_path}). - --keys-path PATH Specify the path for JSON key files to be found - (default: {flag_keys_path}). - --identity NAME Specify your node's name. (default: {flag_identity}) - --light Experimental: run in light client mode. Light clients - synchronize a bare minimum of data and fetch necessary - data on-demand from the network. Much lower in storage, - potentially higher in bandwidth. Has no effect with - subcommands (default: {flag_light}). + --mode MODE Set the operating mode. MODE can be one of: + last - Uses the last-used mode, active if none. + active - Parity continuously syncs the chain. + passive - Parity syncs initially, then sleeps and + wakes regularly to resync. + dark - Parity syncs only when the RPC is active. + offline - Parity doesn't sync. (default: {flag_mode}). + --mode-timeout SECS Specify the number of seconds before inactivity + timeout occurs when mode is dark or passive + (default: {flag_mode_timeout}). + --mode-alarm SECS Specify the number of seconds before auto sleep + reawake timeout occurs when mode is passive + (default: {flag_mode_alarm}). + --auto-update SET Set a releases set to automatically update and + install. + all - All updates in the our release track. + critical - Only consensus/security updates. + none - No updates will be auto-installed. + (default: {flag_auto_update}). + --release-track TRACK Set which release track we should use for updates. + stable - Stable releases. + beta - Beta releases. + nightly - Nightly releases (unstable). + testing - Testing releases (do not use). + current - Whatever track this executable was + released on (default: {flag_release_track}). + --public-node Start Parity as a public web server. Account storage + and transaction signing will be delegated to the UI. + (default: {flag_public_node}). + --no-download Normally new releases will be downloaded ready for + updating. This disables it. Not recommended. + (default: {flag_no_download}). + --no-consensus Force the binary to run even if there are known + issues regarding consensus. Not recommended. + (default: {flag_no_consensus}). + --force-direct Run the originally installed version of Parity, + ignoring any updates that have since been installed. + --chain CHAIN Specify the blockchain type. CHAIN may be either a + JSON chain specification file or olympic, frontier, + homestead, mainnet, morden, ropsten, classic, expanse, + testnet, kovan or dev (default: {flag_chain}). + -d --base-path PATH Specify the base data storage path. + (default: {flag_base_path}). + --db-path PATH Specify the database directory path + (default: {flag_db_path}). + --keys-path PATH Specify the path for JSON key files to be found + (default: {flag_keys_path}). + --identity NAME Specify your node's name. (default: {flag_identity}) + --light Experimental: run in light client mode. Light clients + synchronize a bare minimum of data and fetch necessary + data on-demand from the network. Much lower in storage, + potentially higher in bandwidth. Has no effect with + subcommands (default: {flag_light}). Account Options: - --unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution. - ACCOUNTS is a comma-delimited list of addresses. - Implies --no-ui. (default: {flag_unlock:?}) - --password FILE Provide a file containing a password for unlocking - an account. Leading and trailing whitespace is trimmed. - (default: {flag_password:?}) - --keys-iterations NUM Specify the number of iterations to use when - deriving key from the password (bigger is more - secure) (default: {flag_keys_iterations}). - --no-hardware-wallets Disables hardware wallet support. (default: {flag_no_hardware_wallets}) + --unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution. + ACCOUNTS is a comma-delimited list of addresses. + Implies --no-ui. (default: {flag_unlock:?}) + --password FILE Provide a file containing a password for unlocking + an account. Leading and trailing whitespace is trimmed. + (default: {flag_password:?}) + --keys-iterations NUM Specify the number of iterations to use when + deriving key from the password (bigger is more + secure) (default: {flag_keys_iterations}). + --no-hardware-wallets Disables hardware wallet support. (default: {flag_no_hardware_wallets}) UI Options: - --force-ui Enable Trusted UI WebSocket endpoint, - even when --unlock is in use. (default: ${flag_force_ui}) - --no-ui Disable Trusted UI WebSocket endpoint. - (default: ${flag_no_ui}) - --ui-port PORT Specify the port of Trusted UI server - (default: {flag_ui_port}). - --ui-interface IP Specify the hostname portion of the Trusted UI - server, IP should be an interface's IP address, - or local (default: {flag_ui_interface}). - --ui-path PATH Specify directory where Trusted UIs tokens should - be stored. (default: {flag_ui_path}) - --ui-no-validation Disable Origin and Host headers validation for - Trusted UI. WARNING: INSECURE. Used only for - development. (default: {flag_ui_no_validation}) + --force-ui Enable Trusted UI WebSocket endpoint, + even when --unlock is in use. (default: ${flag_force_ui}) + --no-ui Disable Trusted UI WebSocket endpoint. + (default: ${flag_no_ui}) + --ui-port PORT Specify the port of Trusted UI server + (default: {flag_ui_port}). + --ui-interface IP Specify the hostname portion of the Trusted UI + server, IP should be an interface's IP address, + or local (default: {flag_ui_interface}). + --ui-path PATH Specify directory where Trusted UIs tokens should + be stored. (default: {flag_ui_path}) + --ui-no-validation Disable Origin and Host headers validation for + Trusted UI. WARNING: INSECURE. Used only for + development. (default: {flag_ui_no_validation}) Networking Options: - --no-warp Disable syncing from the snapshot over the network. (default: {flag_no_warp}) - --port PORT Override the port on which the node should listen - (default: {flag_port}). - --min-peers NUM Try to maintain at least NUM peers (default: {flag_min_peers}). - --max-peers NUM Allow up to NUM peers (default: {flag_max_peers}). - --snapshot-peers NUM Allow additional NUM peers for a snapshot sync - (default: {flag_snapshot_peers}). - --nat METHOD Specify method to use for determining public - address. Must be one of: any, none, upnp, - extip: (default: {flag_nat}). - --network-id INDEX Override the network identifier from the chain we - are on. (default: {flag_network_id:?}) - --bootnodes NODES Override the bootnodes from our chain. NODES should - be comma-delimited enodes. (default: {flag_bootnodes:?}) - --no-discovery Disable new peer discovery. (default: {flag_no_discovery}) - --node-key KEY Specify node secret key, either as 64-character hex - string or input to SHA3 operation. (default: {flag_node_key:?}) - --reserved-peers FILE Provide a file containing enodes, one per line. - These nodes will always have a reserved slot on top - of the normal maximum peers. (default: {flag_reserved_peers:?}) - --reserved-only Connect only to reserved nodes. (default: {flag_reserved_only}) - --allow-ips FILTER Filter outbound connections. Must be one of: - private - connect to private network IP addresses only; - public - connect to public network IP addresses only; - all - connect to any IP address. - (default: {flag_allow_ips}) - --max-pending-peers NUM Allow up to NUM pending connections. (default: {flag_max_pending_peers}) - --no-ancient-blocks Disable downloading old blocks after snapshot restoration - or warp sync. (default: {flag_no_ancient_blocks}) - --no-serve-light Disable serving of light peers. (default: {flag_no_serve_light}) + --no-warp Disable syncing from the snapshot over the network. (default: {flag_no_warp}) + --port PORT Override the port on which the node should listen + (default: {flag_port}). + --min-peers NUM Try to maintain at least NUM peers (default: {flag_min_peers}). + --max-peers NUM Allow up to NUM peers (default: {flag_max_peers}). + --snapshot-peers NUM Allow additional NUM peers for a snapshot sync + (default: {flag_snapshot_peers}). + --nat METHOD Specify method to use for determining public + address. Must be one of: any, none, upnp, + extip: (default: {flag_nat}). + --network-id INDEX Override the network identifier from the chain we + are on. (default: {flag_network_id:?}) + --bootnodes NODES Override the bootnodes from our chain. NODES should + be comma-delimited enodes. (default: {flag_bootnodes:?}) + --no-discovery Disable new peer discovery. (default: {flag_no_discovery}) + --node-key KEY Specify node secret key, either as 64-character hex + string or input to SHA3 operation. (default: {flag_node_key:?}) + --reserved-peers FILE Provide a file containing enodes, one per line. + These nodes will always have a reserved slot on top + of the normal maximum peers. (default: {flag_reserved_peers:?}) + --reserved-only Connect only to reserved nodes. (default: {flag_reserved_only}) + --allow-ips FILTER Filter outbound connections. Must be one of: + private - connect to private network IP addresses only; + public - connect to public network IP addresses only; + all - connect to any IP address. + (default: {flag_allow_ips}) + --max-pending-peers NUM Allow up to NUM pending connections. (default: {flag_max_pending_peers}) + --no-ancient-blocks Disable downloading old blocks after snapshot restoration + or warp sync. (default: {flag_no_ancient_blocks}) + --no-serve-light Disable serving of light peers. (default: {flag_no_serve_light}) API and Console Options: - --no-jsonrpc Disable the JSON-RPC API server. (default: {flag_no_jsonrpc}) - --jsonrpc-port PORT Specify the port portion of the JSONRPC API server - (default: {flag_jsonrpc_port}). - --jsonrpc-interface IP Specify the hostname portion of the JSONRPC API - server, IP should be an interface's IP address, or - all (all interfaces) or local (default: {flag_jsonrpc_interface}). - --jsonrpc-cors URL Specify CORS header for JSON-RPC API responses. - (default: {flag_jsonrpc_cors:?}) - --jsonrpc-apis APIS Specify the APIs available through the JSONRPC - interface. APIS is a comma-delimited list of API - name. Possible name are all, safe, web3, eth, net, personal, - parity, parity_set, traces, rpc, parity_accounts. - You can also disable a specific API by putting '-' in the front: all,-personal - (default: {flag_jsonrpc_apis}). - --jsonrpc-hosts HOSTS List of allowed Host header values. This option will - validate the Host header sent by the browser, it - is additional security against some attack - vectors. Special options: "all", "none", - (default: {flag_jsonrpc_hosts}). - --jsonrpc-threads THREADS Enables experimental faster implementation of JSON-RPC server. - Requires Dapps server to be disabled using --no-dapps. (default: {flag_jsonrpc_threads:?}) + --no-jsonrpc Disable the JSON-RPC API server. (default: {flag_no_jsonrpc}) + --jsonrpc-port PORT Specify the port portion of the JSONRPC API server + (default: {flag_jsonrpc_port}). + --jsonrpc-interface IP Specify the hostname portion of the JSONRPC API + server, IP should be an interface's IP address, or + all (all interfaces) or local (default: {flag_jsonrpc_interface}). + --jsonrpc-cors URL Specify CORS header for JSON-RPC API responses. + (default: {flag_jsonrpc_cors:?}) + --jsonrpc-apis APIS Specify the APIs available through the JSONRPC + interface. APIS is a comma-delimited list of API + name. Possible name are all, safe, web3, eth, net, personal, + parity, parity_set, traces, rpc, parity_accounts. + You can also disable a specific API by putting '-' in the front: all,-personal + (default: {flag_jsonrpc_apis}). + --jsonrpc-hosts HOSTS List of allowed Host header values. This option will + validate the Host header sent by the browser, it + is additional security against some attack + vectors. Special options: "all", "none", + (default: {flag_jsonrpc_hosts}). + --jsonrpc-threads THREADS Enables experimental faster implementation of JSON-RPC server. + Requires Dapps server to be disabled using --no-dapps. (default: {flag_jsonrpc_threads:?}) - --no-ipc Disable JSON-RPC over IPC service. (default: {flag_no_ipc}) - --ipc-path PATH Specify custom path for JSON-RPC over IPC service - (default: {flag_ipc_path}). - --ipc-apis APIS Specify custom API set available via JSON-RPC over - IPC (default: {flag_ipc_apis}). - - --no-dapps Disable the Dapps server (e.g. status page). (default: {flag_no_dapps}) - --dapps-path PATH Specify directory where dapps should be installed. - (default: {flag_dapps_path}) - --ipfs-api Enable IPFS-compatible HTTP API. (default: {flag_ipfs_api}) - --ipfs-api-port PORT Configure on which port the IPFS HTTP API should listen. - (default: {flag_ipfs_api_port}) - --ipfs-api-interface IP Specify the hostname portion of the IPFS API server, - IP should be an interface's IP address or local. - (default: {flag_ipfs_api_interface}) - --ipfs-api-cors URL Specify CORS header for IPFS API responses. - (default: {flag_ipfs_api_cors:?}) - --ipfs-api-hosts HOSTS List of allowed Host header values. This option will - validate the Host header sent by the browser, it - is additional security against some attack - vectors. Special options: "all", "none" - (default: {flag_ipfs_api_hosts}). + --no-ipc Disable JSON-RPC over IPC service. (default: {flag_no_ipc}) + --ipc-path PATH Specify custom path for JSON-RPC over IPC service + (default: {flag_ipc_path}). + --ipc-apis APIS Specify custom API set available via JSON-RPC over + IPC (default: {flag_ipc_apis}). + --no-dapps Disable the Dapps server (e.g. status page). (default: {flag_no_dapps}) + --dapps-path PATH Specify directory where dapps should be installed. + (default: {flag_dapps_path}) + --ipfs-api Enable IPFS-compatible HTTP API. (default: {flag_ipfs_api}) + --ipfs-api-port PORT Configure on which port the IPFS HTTP API should listen. + (default: {flag_ipfs_api_port}) + --ipfs-api-interface IP Specify the hostname portion of the IPFS API server, + IP should be an interface's IP address or local. + (default: {flag_ipfs_api_interface}) + --ipfs-api-cors URL Specify CORS header for IPFS API responses. + (default: {flag_ipfs_api_cors:?}) + --ipfs-api-hosts HOSTS List of allowed Host header values. This option will + validate the Host header sent by the browser, it + is additional security against some attack + vectors. Special options: "all", "none" + (default: {flag_ipfs_api_hosts}). Secret Store Options: - --no-secretstore Disable Secret Store functionality. (default: {flag_no_secretstore}) - --secretstore-port PORT Specify the port portion for Secret Store Key Server - (default: {flag_secretstore_port}). - --secretstore-interface IP Specify the hostname portion for Secret Store Key Server, IP - should be an interface's IP address, or local - (default: {flag_secretstore_interface}). - --secretstore-path PATH Specify directory where Secret Store should save its data. - (default: {flag_secretstore_path}) + --no-secretstore Disable Secret Store functionality. (default: {flag_no_secretstore}) + --secretstore-secret SECRET Hex-encoded secret key of this node. + (required, default: {flag_secretstore_secret:?}). + --secretstore-nodes NODES Comma-separated list of other secret store cluster nodes in form + NODE_PUBLIC_KEY_IN_HEX@NODE_IP_ADDR:NODE_PORT. + (required, default: {flag_secretstore_nodes}). + --secretstore-interface IP Specify the hostname portion for listening to Secret Store Key Server + internal requests, IP should be an interface's IP address, or local + (default: {flag_secretstore_interface}). + --secretstore-port PORT Specify the port portion for listening to Secret Store Key Server + internal requests (default: {flag_secretstore_port}). + --secretstore-http-interface IP Specify the hostname portion for listening to Secret Store Key Server + HTTP requests, IP should be an interface's IP address, or local + (default: {flag_secretstore_http_interface}). + --secretstore-http-port PORT Specify the port portion for listening to Secret Store Key Server + HTTP requests (default: {flag_secretstore_http_port}). + --secretstore-path PATH Specify directory where Secret Store should save its data. + (default: {flag_secretstore_path}). Sealing/Mining Options: - --author ADDRESS Specify the block author (aka "coinbase") address - for sending block rewards from sealed blocks. - NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION. - (default: {flag_author:?}) - --engine-signer ADDRESS Specify the address which should be used to - sign consensus messages and issue blocks. - Relevant only to non-PoW chains. - (default: {flag_engine_signer:?}) - --force-sealing Force the node to author new blocks as if it were - always sealing/mining. - (default: {flag_force_sealing}) - --reseal-on-txs SET Specify which transactions should force the node - to reseal a block. SET is one of: - none - never reseal on new transactions; - own - reseal only on a new local transaction; - ext - reseal only on a new external transaction; - all - reseal on all new transactions - (default: {flag_reseal_on_txs}). - --reseal-min-period MS Specify the minimum time between reseals from - incoming transactions. MS is time measured in - milliseconds (default: {flag_reseal_min_period}). - --reseal-max-period MS Specify the maximum time since last block to enable - force-sealing. MS is time measured in - milliseconds (default: {flag_reseal_max_period}). - --work-queue-size ITEMS Specify the number of historical work packages - which are kept cached lest a solution is found for - them later. High values take more memory but result - in fewer unusable solutions (default: {flag_work_queue_size}). - --tx-gas-limit GAS Apply a limit of GAS as the maximum amount of gas - a single transaction may have for it to be mined. - (default: {flag_tx_gas_limit:?}) - --tx-time-limit MS Maximal time for processing single transaction. - If enabled senders/recipients/code of transactions - offending the limit will be banned from being included - in transaction queue for 180 seconds. - (default: {flag_tx_time_limit:?}) - --relay-set SET Set of transactions to relay. SET may be: - cheap - Relay any transaction in the queue (this - may include invalid transactions); - strict - Relay only executed transactions (this - guarantees we don't relay invalid transactions, but - means we relay nothing if not mining); - lenient - Same as strict when mining, and cheap - when not (default: {flag_relay_set}). - --usd-per-tx USD Amount of USD to be paid for a basic transaction - (default: {flag_usd_per_tx}). The minimum gas price is set - accordingly. - --usd-per-eth SOURCE USD value of a single ETH. SOURCE may be either an - amount in USD, a web service or 'auto' to use each - web service in turn and fallback on the last known - good value (default: {flag_usd_per_eth}). - --price-update-period T T will be allowed to pass between each gas price - update. T may be daily, hourly, a number of seconds, - or a time string of the form "2 days", "30 minutes" - etc. (default: {flag_price_update_period}). - --gas-floor-target GAS Amount of gas per block to target when sealing a new - block (default: {flag_gas_floor_target}). - --gas-cap GAS A cap on how large we will raise the gas limit per - block due to transaction volume (default: {flag_gas_cap}). - --extra-data STRING Specify a custom extra-data for authored blocks, no - more than 32 characters. (default: {flag_extra_data:?}) - --tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting - to be included in next block) (default: {flag_tx_queue_size}). - --tx-queue-gas LIMIT Maximum amount of total gas for external transactions in - the queue. LIMIT can be either an amount of gas or - 'auto' or 'off'. 'auto' sets the limit to be 20x - the current block gas limit. (default: {flag_tx_queue_gas}). - --tx-queue-strategy S Prioritization strategy used to order transactions - in the queue. S may be: - gas - Prioritize txs with low gas limit; - gas_price - Prioritize txs with high gas price; - gas_factor - Prioritize txs using gas price - and gas limit ratio (default: {flag_tx_queue_strategy}). - --tx-queue-ban-count C Number of times maximal time for execution (--tx-time-limit) - can be exceeded before banning sender/recipient/code. - (default: {flag_tx_queue_ban_count}) - --tx-queue-ban-time SEC Banning time (in seconds) for offenders of specified - execution time limit. Also number of offending actions - have to reach the threshold within that time. - (default: {flag_tx_queue_ban_time} seconds) - --remove-solved Move solved blocks from the work package queue - instead of cloning them. This gives a slightly - faster import speed, but means that extra solutions - submitted for the same work package will go unused. - (default: {flag_remove_solved}) - --notify-work URLS URLs to which work package notifications are pushed. - URLS should be a comma-delimited list of HTTP URLs. - (default: {flag_notify_work:?}) - --refuse-service-transactions Always refuse service transactions. - (default: {flag_refuse_service_transactions}). - --stratum Run Stratum server for miner push notification. (default: {flag_stratum}) - --stratum-interface IP Interface address for Stratum server. (default: {flag_stratum_interface}) - --stratum-port PORT Port for Stratum server to listen on. (default: {flag_stratum_port}) - --stratum-secret STRING Secret for authorizing Stratum server for peers. - (default: {flag_stratum_secret:?}) + --author ADDRESS Specify the block author (aka "coinbase") address + for sending block rewards from sealed blocks. + NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION. + (default: {flag_author:?}) + --engine-signer ADDRESS Specify the address which should be used to + sign consensus messages and issue blocks. + Relevant only to non-PoW chains. + (default: {flag_engine_signer:?}) + --force-sealing Force the node to author new blocks as if it were + always sealing/mining. + (default: {flag_force_sealing}) + --reseal-on-txs SET Specify which transactions should force the node + to reseal a block. SET is one of: + none - never reseal on new transactions; + own - reseal only on a new local transaction; + ext - reseal only on a new external transaction; + all - reseal on all new transactions + (default: {flag_reseal_on_txs}). + --reseal-min-period MS Specify the minimum time between reseals from + incoming transactions. MS is time measured in + milliseconds (default: {flag_reseal_min_period}). + --reseal-max-period MS Specify the maximum time since last block to enable + force-sealing. MS is time measured in + milliseconds (default: {flag_reseal_max_period}). + --work-queue-size ITEMS Specify the number of historical work packages + which are kept cached lest a solution is found for + them later. High values take more memory but result + in fewer unusable solutions (default: {flag_work_queue_size}). + --tx-gas-limit GAS Apply a limit of GAS as the maximum amount of gas + a single transaction may have for it to be mined. + (default: {flag_tx_gas_limit:?}) + --tx-time-limit MS Maximal time for processing single transaction. + If enabled senders/recipients/code of transactions + offending the limit will be banned from being included + in transaction queue for 180 seconds. + (default: {flag_tx_time_limit:?}) + --relay-set SET Set of transactions to relay. SET may be: + cheap - Relay any transaction in the queue (this + may include invalid transactions); + strict - Relay only executed transactions (this + guarantees we don't relay invalid transactions, but + means we relay nothing if not mining); + lenient - Same as strict when mining, and cheap + when not (default: {flag_relay_set}). + --usd-per-tx USD Amount of USD to be paid for a basic transaction + (default: {flag_usd_per_tx}). The minimum gas price is set + accordingly. + --usd-per-eth SOURCE USD value of a single ETH. SOURCE may be either an + amount in USD, a web service or 'auto' to use each + web service in turn and fallback on the last known + good value (default: {flag_usd_per_eth}). + --price-update-period T T will be allowed to pass between each gas price + update. T may be daily, hourly, a number of seconds, + or a time string of the form "2 days", "30 minutes" + etc. (default: {flag_price_update_period}). + --gas-floor-target GAS Amount of gas per block to target when sealing a new + block (default: {flag_gas_floor_target}). + --gas-cap GAS A cap on how large we will raise the gas limit per + block due to transaction volume (default: {flag_gas_cap}). + --extra-data STRING Specify a custom extra-data for authored blocks, no + more than 32 characters. (default: {flag_extra_data:?}) + --tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting + to be included in next block) (default: {flag_tx_queue_size}). + --tx-queue-gas LIMIT Maximum amount of total gas for external transactions in + the queue. LIMIT can be either an amount of gas or + 'auto' or 'off'. 'auto' sets the limit to be 20x + the current block gas limit. (default: {flag_tx_queue_gas}). + --tx-queue-strategy S Prioritization strategy used to order transactions + in the queue. S may be: + gas - Prioritize txs with low gas limit; + gas_price - Prioritize txs with high gas price; + gas_factor - Prioritize txs using gas price + and gas limit ratio (default: {flag_tx_queue_strategy}). + --tx-queue-ban-count C Number of times maximal time for execution (--tx-time-limit) + can be exceeded before banning sender/recipient/code. + (default: {flag_tx_queue_ban_count}) + --tx-queue-ban-time SEC Banning time (in seconds) for offenders of specified + execution time limit. Also number of offending actions + have to reach the threshold within that time. + (default: {flag_tx_queue_ban_time} seconds) + --remove-solved Move solved blocks from the work package queue + instead of cloning them. This gives a slightly + faster import speed, but means that extra solutions + submitted for the same work package will go unused. + (default: {flag_remove_solved}) + --notify-work URLS URLs to which work package notifications are pushed. + URLS should be a comma-delimited list of HTTP URLs. + (default: {flag_notify_work:?}) + --refuse-service-transactions Always refuse service transactions. + (default: {flag_refuse_service_transactions}). + --stratum Run Stratum server for miner push notification. (default: {flag_stratum}) + --stratum-interface IP Interface address for Stratum server. (default: {flag_stratum_interface}) + --stratum-port PORT Port for Stratum server to listen on. (default: {flag_stratum_port}) + --stratum-secret STRING Secret for authorizing Stratum server for peers. + (default: {flag_stratum_secret:?}) Footprint Options: - --tracing BOOL Indicates if full transaction tracing should be - enabled. Works only if client had been fully synced - with tracing enabled. BOOL may be one of auto, on, - off. auto uses last used value of this option (off - if it does not exist) (default: {flag_tracing}). - --pruning METHOD Configure pruning of the state/storage trie. METHOD - may be one of auto, archive, fast: - archive - keep all state trie data. No pruning. - fast - maintain journal overlay. Fast but 50MB used. - auto - use the method most recently synced or - default to fast if none synced (default: {flag_pruning}). - --pruning-history NUM Set a minimum number of recent states to keep when pruning - is active. (default: {flag_pruning_history}). - --pruning-memory MB The ideal amount of memory in megabytes to use to store - recent states. As many states as possible will be kept - within this limit, and at least --pruning-history states - will always be kept. (default: {flag_pruning_memory}) - --cache-size-db MB Override database cache size (default: {flag_cache_size_db}). - --cache-size-blocks MB Specify the prefered size of the blockchain cache in - megabytes (default: {flag_cache_size_blocks}). - --cache-size-queue MB Specify the maximum size of memory to use for block - queue (default: {flag_cache_size_queue}). - --cache-size-state MB Specify the maximum size of memory to use for - the state cache (default: {flag_cache_size_state}). - --cache-size MB Set total amount of discretionary memory to use for - the entire system, overrides other cache and queue - options. (default: {flag_cache_size:?}) - --fast-and-loose Disables DB WAL, which gives a significant speed up - but means an unclean exit is unrecoverable. (default: {flag_fast_and_loose}) - --db-compaction TYPE Database compaction type. TYPE may be one of: - ssd - suitable for SSDs and fast HDDs; - hdd - suitable for slow HDDs; - auto - determine automatically (default: {flag_db_compaction}). - --fat-db BOOL Build appropriate information to allow enumeration - of all accounts and storage keys. Doubles the size - of the state database. BOOL may be one of on, off - or auto. (default: {flag_fat_db}) - --scale-verifiers Automatically scale amount of verifier threads based on - workload. Not guaranteed to be faster. - (default: {flag_scale_verifiers}) - --num-verifiers INT Amount of verifier threads to use or to begin with, if verifier - auto-scaling is enabled. (default: {flag_num_verifiers:?}) + --tracing BOOL Indicates if full transaction tracing should be + enabled. Works only if client had been fully synced + with tracing enabled. BOOL may be one of auto, on, + off. auto uses last used value of this option (off + if it does not exist) (default: {flag_tracing}). + --pruning METHOD Configure pruning of the state/storage trie. METHOD + may be one of auto, archive, fast: + archive - keep all state trie data. No pruning. + fast - maintain journal overlay. Fast but 50MB used. + auto - use the method most recently synced or + default to fast if none synced (default: {flag_pruning}). + --pruning-history NUM Set a minimum number of recent states to keep when pruning + is active. (default: {flag_pruning_history}). + --pruning-memory MB The ideal amount of memory in megabytes to use to store + recent states. As many states as possible will be kept + within this limit, and at least --pruning-history states + will always be kept. (default: {flag_pruning_memory}) + --cache-size-db MB Override database cache size (default: {flag_cache_size_db}). + --cache-size-blocks MB Specify the prefered size of the blockchain cache in + megabytes (default: {flag_cache_size_blocks}). + --cache-size-queue MB Specify the maximum size of memory to use for block + queue (default: {flag_cache_size_queue}). + --cache-size-state MB Specify the maximum size of memory to use for + the state cache (default: {flag_cache_size_state}). + --cache-size MB Set total amount of discretionary memory to use for + the entire system, overrides other cache and queue + options. (default: {flag_cache_size:?}) + --fast-and-loose Disables DB WAL, which gives a significant speed up + but means an unclean exit is unrecoverable. (default: {flag_fast_and_loose}) + --db-compaction TYPE Database compaction type. TYPE may be one of: + ssd - suitable for SSDs and fast HDDs; + hdd - suitable for slow HDDs; + auto - determine automatically (default: {flag_db_compaction}). + --fat-db BOOL Build appropriate information to allow enumeration + of all accounts and storage keys. Doubles the size + of the state database. BOOL may be one of on, off + or auto. (default: {flag_fat_db}) + --scale-verifiers Automatically scale amount of verifier threads based on + workload. Not guaranteed to be faster. + (default: {flag_scale_verifiers}) + --num-verifiers INT Amount of verifier threads to use or to begin with, if verifier + auto-scaling is enabled. (default: {flag_num_verifiers:?}) Import/Export Options: - --from BLOCK Export from block BLOCK, which may be an index or - hash (default: {flag_from}). - --to BLOCK Export to (including) block BLOCK, which may be an - index, hash or 'latest' (default: {flag_to}). - --format FORMAT For import/export in given format. FORMAT must be - one of 'hex' and 'binary'. - (default: {flag_format:?} = Import: auto, Export: binary) - --no-seal-check Skip block seal check. (default: {flag_no_seal_check}) - --at BLOCK Export state at the given block, which may be an - index, hash, or 'latest'. (default: {flag_at}) - --no-storage Don't export account storage. (default: {flag_no_storage}) - --no-code Don't export account code. (default: {flag_no_code}) - --min-balance WEI Don't export accounts with balance less than specified. - (default: {flag_min_balance:?}) - --max-balance WEI Don't export accounts with balance greater than specified. - (default: {flag_max_balance:?}) + --from BLOCK Export from block BLOCK, which may be an index or + hash (default: {flag_from}). + --to BLOCK Export to (including) block BLOCK, which may be an + index, hash or 'latest' (default: {flag_to}). + --format FORMAT For import/export in given format. FORMAT must be + one of 'hex' and 'binary'. + (default: {flag_format:?} = Import: auto, Export: binary) + --no-seal-check Skip block seal check. (default: {flag_no_seal_check}) + --at BLOCK Export state at the given block, which may be an + index, hash, or 'latest'. (default: {flag_at}) + --no-storage Don't export account storage. (default: {flag_no_storage}) + --no-code Don't export account code. (default: {flag_no_code}) + --min-balance WEI Don't export accounts with balance less than specified. + (default: {flag_min_balance:?}) + --max-balance WEI Don't export accounts with balance greater than specified. + (default: {flag_max_balance:?}) Snapshot Options: - --at BLOCK Take a snapshot at the given block, which may be an - index, hash, or 'latest'. Note that taking snapshots at - non-recent blocks will only work with --pruning archive - (default: {flag_at}) - --no-periodic-snapshot Disable automated snapshots which usually occur once - every 10000 blocks. (default: {flag_no_periodic_snapshot}) + --at BLOCK Take a snapshot at the given block, which may be an + index, hash, or 'latest'. Note that taking snapshots at + non-recent blocks will only work with --pruning archive + (default: {flag_at}) + --no-periodic-snapshot Disable automated snapshots which usually occur once + every 10000 blocks. (default: {flag_no_periodic_snapshot}) Virtual Machine Options: - --jitvm Enable the JIT VM. (default: {flag_jitvm}) + --jitvm Enable the JIT VM. (default: {flag_jitvm}) Legacy Options: - --geth Run in Geth-compatibility mode. Sets the IPC path - to be the same as Geth's. Overrides the --ipc-path - and --ipcpath options. Alters RPCs to reflect Geth - bugs. Includes the personal_ RPC by default. - --testnet Testnet mode. Equivalent to --chain testnet. - Overrides the --keys-path option. - --import-geth-keys Attempt to import keys from Geth client. - --datadir PATH Equivalent to --base-path PATH. - --networkid INDEX Equivalent to --network-id INDEX. - --peers NUM Equivalent to --min-peers NUM. - --nodekey KEY Equivalent to --node-key KEY. - --nodiscover Equivalent to --no-discovery. - -j --jsonrpc Does nothing; JSON-RPC is on by default now. - --jsonrpc-off Equivalent to --no-jsonrpc. - -w --webapp Does nothing; dapps server is on by default now. - --dapps-off Equivalent to --no-dapps. - --dapps-user USERNAME Dapps server authentication has been removed. (default: {flag_dapps_user:?}) - --dapps-pass PASSWORD Dapps server authentication has been removed. (default: {flag_dapps_pass:?}) - --dapps-apis-all Dapps server is merged with RPC server. Use --jsonrpc-apis. (default: {flag_dapps_apis_all:?}) - --dapps-cors URL Dapps server is merged with RPC server. Use --jsonrpc-cors. (default: {flag_dapps_cors:?}) - --dapps-hosts HOSTS Dapps server is merged with RPC server. Use --jsonrpc-hosts. (default: {flag_dapps_hosts:?}) - --dapps-interface IP Dapps server is merged with RPC server. Use --jsonrpc-interface. (default: {flag_dapps_interface:?}) - --dapps-port PORT Dapps server is merged with RPC server. Use --jsonrpc-port. (default: {flag_dapps_port:?}) - --rpc Does nothing; JSON-RPC is on by default now. - --warp Does nothing; Warp sync is on by default. (default: {flag_warp}) - --rpcaddr IP Equivalent to --jsonrpc-interface IP. - --rpcport PORT Equivalent to --jsonrpc-port PORT. - --rpcapi APIS Equivalent to --jsonrpc-apis APIS. - --rpccorsdomain URL Equivalent to --jsonrpc-cors URL. - --ipcdisable Equivalent to --no-ipc. - --ipc-off Equivalent to --no-ipc. - --ipcapi APIS Equivalent to --ipc-apis APIS. - --ipcpath PATH Equivalent to --ipc-path PATH. - --gasprice WEI Minimum amount of Wei per GAS to be paid for a - transaction to be accepted for mining. Overrides - --basic-tx-usd. - --etherbase ADDRESS Equivalent to --author ADDRESS. - --extradata STRING Equivalent to --extra-data STRING. - --cache MB Equivalent to --cache-size MB. + --geth Run in Geth-compatibility mode. Sets the IPC path + to be the same as Geth's. Overrides the --ipc-path + and --ipcpath options. Alters RPCs to reflect Geth + bugs. Includes the personal_ RPC by default. + --testnet Testnet mode. Equivalent to --chain testnet. + Overrides the --keys-path option. + --import-geth-keys Attempt to import keys from Geth client. + --datadir PATH Equivalent to --base-path PATH. + --networkid INDEX Equivalent to --network-id INDEX. + --peers NUM Equivalent to --min-peers NUM. + --nodekey KEY Equivalent to --node-key KEY. + --nodiscover Equivalent to --no-discovery. + -j --jsonrpc Does nothing; JSON-RPC is on by default now. + --jsonrpc-off Equivalent to --no-jsonrpc. + -w --webapp Does nothing; dapps server is on by default now. + --dapps-off Equivalent to --no-dapps. + --dapps-user USERNAME Dapps server authentication has been removed. (default: {flag_dapps_user:?}) + --dapps-pass PASSWORD Dapps server authentication has been removed. (default: {flag_dapps_pass:?}) + --dapps-apis-all Dapps server is merged with RPC server. Use --jsonrpc-apis. (default: {flag_dapps_apis_all:?}) + --dapps-cors URL Dapps server is merged with RPC server. Use --jsonrpc-cors. (default: {flag_dapps_cors:?}) + --dapps-hosts HOSTS Dapps server is merged with RPC server. Use --jsonrpc-hosts. (default: {flag_dapps_hosts:?}) + --dapps-interface IP Dapps server is merged with RPC server. Use --jsonrpc-interface. (default: {flag_dapps_interface:?}) + --dapps-port PORT Dapps server is merged with RPC server. Use --jsonrpc-port. (default: {flag_dapps_port:?}) + --rpc Does nothing; JSON-RPC is on by default now. + --warp Does nothing; Warp sync is on by default. (default: {flag_warp}) + --rpcaddr IP Equivalent to --jsonrpc-interface IP. + --rpcport PORT Equivalent to --jsonrpc-port PORT. + --rpcapi APIS Equivalent to --jsonrpc-apis APIS. + --rpccorsdomain URL Equivalent to --jsonrpc-cors URL. + --ipcdisable Equivalent to --no-ipc. + --ipc-off Equivalent to --no-ipc. + --ipcapi APIS Equivalent to --ipc-apis APIS. + --ipcpath PATH Equivalent to --ipc-path PATH. + --gasprice WEI Minimum amount of Wei per GAS to be paid for a + transaction to be accepted for mining. Overrides + --basic-tx-usd. + --etherbase ADDRESS Equivalent to --author ADDRESS. + --extradata STRING Equivalent to --extra-data STRING. + --cache MB Equivalent to --cache-size MB. Internal Options: - --can-restart Executable will auto-restart if exiting with 69. + --can-restart Executable will auto-restart if exiting with 69. Miscellaneous Options: - -c --config CONFIG Specify a filename containing a configuration file. - (default: {flag_config}) - -l --logging LOGGING Specify the logging level. Must conform to the same - format as RUST_LOG. (default: {flag_logging:?}) - --log-file FILENAME Specify a filename into which logging should be - appended. (default: {flag_log_file:?}) - --no-config Don't load a configuration file. - --no-color Don't use terminal color codes in output. (default: {flag_no_color}) - -v --version Show information about version. - -h --help Show this screen. + -c --config CONFIG Specify a filename containing a configuration file. + (default: {flag_config}) + -l --logging LOGGING Specify the logging level. Must conform to the same + format as RUST_LOG. (default: {flag_logging:?}) + --log-file FILENAME Specify a filename into which logging should be + appended. (default: {flag_log_file:?}) + --no-config Don't load a configuration file. + --no-color Don't use terminal color codes in output. (default: {flag_no_color}) + -v --version Show information about version. + -h --help Show this screen. diff --git a/parity/configuration.rs b/parity/configuration.rs index 7061610bb..fe26613d3 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -18,13 +18,14 @@ use std::time::Duration; use std::io::{Read, Write, stderr}; use std::net::SocketAddr; use std::path::{Path, PathBuf}; +use std::collections::BTreeMap; use std::cmp::max; use cli::{Args, ArgsError}; use util::{Hashable, H256, U256, Uint, Bytes, version_data, Address}; use util::journaldb::Algorithm; use util::Colour; use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP}; -use ethcore::ethstore::ethkey::Secret; +use ethcore::ethstore::ethkey::{Secret, Public}; use ethcore::client::{VMType}; use ethcore::miner::{MinerOptions, Banning, StratumOptions}; use ethcore::verification::queue::VerifierSettings; @@ -136,7 +137,7 @@ impl Configuration { let mut dapps_conf = self.dapps_config(); let ipfs_conf = self.ipfs_config(); let signer_conf = self.signer_config(); - let secretstore_conf = self.secretstore_config(); + let secretstore_conf = self.secretstore_config()?; let format = self.format()?; if self.args.flag_jsonrpc_threads.is_some() && dapps_conf.enabled { @@ -571,13 +572,17 @@ impl Configuration { } } - fn secretstore_config(&self) -> SecretStoreConfiguration { - SecretStoreConfiguration { + fn secretstore_config(&self) -> Result { + Ok(SecretStoreConfiguration { enabled: self.secretstore_enabled(), + self_secret: self.secretstore_self_secret()?, + nodes: self.secretstore_nodes()?, interface: self.secretstore_interface(), port: self.args.flag_secretstore_port, + http_interface: self.secretstore_http_interface(), + http_port: self.args.flag_secretstore_http_port, data_path: self.directories().secretstore, - } + }) } fn ipfs_config(&self) -> IpfsConfiguration { @@ -913,10 +918,43 @@ impl Configuration { } fn secretstore_interface(&self) -> String { - match self.args.flag_secretstore_interface.as_str() { - "local" => "127.0.0.1", - x => x, - }.into() + Self::interface(&self.args.flag_secretstore_interface) + } + + fn secretstore_http_interface(&self) -> String { + Self::interface(&self.args.flag_secretstore_http_interface) + } + + fn secretstore_self_secret(&self) -> Result, String> { + match self.args.flag_secretstore_secret { + Some(ref s) => Ok(Some(s.parse() + .map_err(|e| format!("Invalid secret store secret: {}. Error: {:?}", s, e))?)), + None => Ok(None), + } + } + + fn secretstore_nodes(&self) -> Result, String> { + let mut nodes = BTreeMap::new(); + for node in self.args.flag_secretstore_nodes.split(',').filter(|n| n != &"") { + let public_and_addr: Vec<_> = node.split('@').collect(); + if public_and_addr.len() != 2 { + return Err(format!("Invalid secret store node: {}", node)); + } + + let ip_and_port: Vec<_> = public_and_addr[1].split(':').collect(); + if ip_and_port.len() != 2 { + return Err(format!("Invalid secret store node: {}", node)); + } + + let public = public_and_addr[0].parse() + .map_err(|e| format!("Invalid public key in secret store node: {}. Error: {:?}", public_and_addr[0], e))?; + let port = ip_and_port[1].parse() + .map_err(|e| format!("Invalid port in secret store node: {}. Error: {:?}", ip_and_port[1], e))?; + + nodes.insert(public, (ip_and_port[0].into(), port)); + } + + Ok(nodes) } fn stratum_interface(&self) -> String { diff --git a/parity/run.rs b/parity/run.rs index 1ad124dbe..b674c93ca 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -651,7 +651,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> R let secretstore_deps = secretstore::Dependencies { client: client.clone(), }; - let secretstore_key_server = secretstore::start(cmd.secretstore_conf.clone(), secretstore_deps); + let secretstore_key_server = secretstore::start(cmd.secretstore_conf.clone(), secretstore_deps)?; // the ipfs server let ipfs_server = ipfs::start_server(cmd.ipfs_conf.clone(), client.clone())?; diff --git a/parity/secretstore.rs b/parity/secretstore.rs index d31614193..5a787b224 100644 --- a/parity/secretstore.rs +++ b/parity/secretstore.rs @@ -14,9 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::collections::BTreeMap; use std::sync::Arc; use dir::default_data_path; use ethcore::client::Client; +use ethkey::{Secret, Public}; use helpers::replace_home; #[derive(Debug, PartialEq, Clone)] @@ -24,10 +26,18 @@ use helpers::replace_home; pub struct Configuration { /// Is secret store functionality enabled? pub enabled: bool, + /// This node secret. + pub self_secret: Option, + /// Other nodes IDs + addresses. + pub nodes: BTreeMap, /// Interface to listen to pub interface: String, /// Port to listen to pub port: u16, + /// Interface to listen to + pub http_interface: String, + /// Port to listen to + pub http_port: u16, /// Data directory path for secret store pub data_path: String, } @@ -55,8 +65,8 @@ mod server { #[cfg(feature="secretstore")] mod server { - use ethkey; use ethcore_secretstore; + use ethkey::KeyPair; use super::{Configuration, Dependencies}; /// Key server @@ -67,37 +77,35 @@ mod server { impl KeyServer { /// Create new key server pub fn new(conf: Configuration, deps: Dependencies) -> Result { - let key_pairs = vec![ - ethkey::KeyPair::from_secret("6c26a76e9b31048d170873a791401c7e799a11f0cefc0171cc31a49800967509".parse().unwrap()).unwrap(), - ethkey::KeyPair::from_secret("7e94018b3731afdb3b4e6f4c3e179475640166da12e1d1b0c7d80729b1a5b452".parse().unwrap()).unwrap(), - ethkey::KeyPair::from_secret("5ab6ed2a52c33142380032c39a03a86b12eacb3fa4b53bc16d84f51318156f8c".parse().unwrap()).unwrap(), - ]; - let conf = ethcore_secretstore::ServiceConfiguration { + let self_secret = conf.self_secret.ok_or("self secret is required when using secretstore")?; + let mut conf = ethcore_secretstore::ServiceConfiguration { listener_address: ethcore_secretstore::NodeAddress { - address: conf.interface.clone(), - port: conf.port, + address: conf.http_interface.clone(), + port: conf.http_port, }, data_path: conf.data_path.clone(), - // TODO: this is test configuration. how it will be configured in production? cluster_config: ethcore_secretstore::ClusterConfiguration { threads: 4, - self_private: (***key_pairs[(conf.port - 8082) as usize].secret()).into(), + self_private: (**self_secret).into(), listener_address: ethcore_secretstore::NodeAddress { address: conf.interface.clone(), - port: conf.port + 10, + port: conf.port, }, - nodes: key_pairs.iter().enumerate().map(|(i, kp)| (kp.public().clone(), - ethcore_secretstore::NodeAddress { - address: conf.interface.clone(), - port: 8082 + 10 + (i as u16), - })).collect(), + nodes: conf.nodes.into_iter().map(|(p, (ip, port))| (p, ethcore_secretstore::NodeAddress { + address: ip, + port: port, + })).collect(), allow_connecting_to_higher_nodes: true, encryption_config: ethcore_secretstore::EncryptionConfiguration { key_check_timeout_ms: 1000, }, - } + }, }; + let self_key_pair = KeyPair::from_secret(self_secret.clone()) + .map_err(|e| format!("valid secret is required when using secretstore. Error: {}", e))?; + conf.cluster_config.nodes.insert(self_key_pair.public().clone(), conf.cluster_config.listener_address.clone()); + let key_server = ethcore_secretstore::start(deps.client, conf) .map_err(Into::::into)?; @@ -115,8 +123,12 @@ impl Default for Configuration { let data_dir = default_data_path(); Configuration { enabled: true, + self_secret: None, + nodes: BTreeMap::new(), interface: "127.0.0.1".to_owned(), - port: 8082, + port: 8083, + http_interface: "127.0.0.1".to_owned(), + http_port: 8082, data_path: replace_home(&data_dir, "$BASE/secretstore"), } } diff --git a/secret_store/Cargo.toml b/secret_store/Cargo.toml index 539f15f1f..062195737 100644 --- a/secret_store/Cargo.toml +++ b/secret_store/Cargo.toml @@ -20,7 +20,8 @@ serde_derive = "0.9" futures = "0.1" futures-cpupool = "0.1" rustc-serialize = "0.3" -tokio-core = "0.1" +tokio-core = "0.1.6" +tokio-io = "0.1.0" tokio-service = "0.1" tokio-proto = "0.1" url = "1.0" diff --git a/secret_store/src/http_listener.rs b/secret_store/src/http_listener.rs index 79fe71330..e7737f160 100644 --- a/secret_store/src/http_listener.rs +++ b/secret_store/src/http_listener.rs @@ -21,11 +21,13 @@ use hyper::method::Method as HttpMethod; use hyper::status::StatusCode as HttpStatusCode; use hyper::server::{Server as HttpServer, Request as HttpRequest, Response as HttpResponse, Handler as HttpHandler, Listening as HttpListening}; +use serde_json; use url::percent_encoding::percent_decode; use util::ToPretty; use traits::KeyServer; -use types::all::{Error, ServiceConfiguration, RequestSignature, DocumentAddress, DocumentEncryptedKey}; +use serialization::SerializableDocumentEncryptedKeyShadow; +use types::all::{Error, ServiceConfiguration, RequestSignature, DocumentAddress, DocumentEncryptedKey, DocumentEncryptedKeyShadow}; /// Key server http-requests listener pub struct KeyServerHttpListener { @@ -42,6 +44,8 @@ enum Request { GenerateDocumentKey(DocumentAddress, RequestSignature, usize), /// Request encryption key of given document for given requestor. GetDocumentKey(DocumentAddress, RequestSignature), + /// Request shadow of encryption key of given document for given requestor. + GetDocumentKeyShadow(DocumentAddress, RequestSignature), } /// Cloneable http handler @@ -83,6 +87,10 @@ impl KeyServer for KeyServerHttpListener where T: KeyServer + 'static { fn document_key(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result { self.handler.key_server.document_key(signature, document) } + + fn document_key_shadow(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result { + self.handler.key_server.document_key_shadow(signature, document) + } } impl HttpHandler for KeyServerHttpHandler where T: KeyServer + 'static { @@ -111,6 +119,34 @@ impl HttpHandler for KeyServerHttpHandler where T: KeyServer + 'static { err })); }, + Request::GetDocumentKeyShadow(document, signature) => { + match self.handler.key_server.document_key_shadow(&signature, &document) + .map_err(|err| { + warn!(target: "secretstore", "GetDocumentKeyShadow request {} has failed with: {}", req_uri, err); + err + }) { + Ok(document_key_shadow) => { + let document_key_shadow = SerializableDocumentEncryptedKeyShadow { + decrypted_secret: document_key_shadow.decrypted_secret.into(), + common_point: document_key_shadow.common_point.expect("always filled when requesting document_key_shadow; qed").into(), + decrypt_shadows: document_key_shadow.decrypt_shadows.expect("always filled when requesting document_key_shadow; qed").into_iter().map(Into::into).collect(), + }; + match serde_json::to_vec(&document_key_shadow) { + Ok(document_key) => { + res.headers_mut().set(header::ContentType::json()); + if let Err(err) = res.send(&document_key) { + // nothing to do, but to log an error + warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err); + } + }, + Err(err) => { + warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err); + } + } + }, + Err(err) => return_error(res, err), + } + }, Request::Invalid => { warn!(target: "secretstore", "Ignoring invalid {}-request {}", req_method, req_uri); *res.status_mut() = HttpStatusCode::BadRequest; @@ -134,11 +170,17 @@ fn return_document_key(req: HttpRequest, mut res: HttpResponse, document_key: Re warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err); } }, - Err(Error::BadSignature) => *res.status_mut() = HttpStatusCode::BadRequest, - Err(Error::AccessDenied) => *res.status_mut() = HttpStatusCode::Forbidden, - Err(Error::DocumentNotFound) => *res.status_mut() = HttpStatusCode::NotFound, - Err(Error::Database(_)) => *res.status_mut() = HttpStatusCode::InternalServerError, - Err(Error::Internal(_)) => *res.status_mut() = HttpStatusCode::InternalServerError, + Err(err) => return_error(res, err), + } +} + +fn return_error(mut res: HttpResponse, err: Error) { + match err { + Error::BadSignature => *res.status_mut() = HttpStatusCode::BadRequest, + Error::AccessDenied => *res.status_mut() = HttpStatusCode::Forbidden, + Error::DocumentNotFound => *res.status_mut() = HttpStatusCode::NotFound, + Error::Database(_) => *res.status_mut() = HttpStatusCode::InternalServerError, + Error::Internal(_) => *res.status_mut() = HttpStatusCode::InternalServerError, } } @@ -149,17 +191,27 @@ fn parse_request(method: &HttpMethod, uri_path: &str) -> Request { }; let path: Vec = uri_path.trim_left_matches('/').split('/').map(Into::into).collect(); - if path.len() < 2 || path[0].is_empty() || path[1].is_empty() { + if path.len() == 0 { + return Request::Invalid; + } + let (args_prefix, args_offset) = if &path[0] == "shadow" { + ("shadow", 1) + } else { + ("", 0) + }; + + if path.len() < 2 + args_offset || path[args_offset].is_empty() || path[args_offset + 1].is_empty() { return Request::Invalid; } let args_len = path.len(); - let document = path[0].parse(); - let signature = path[1].parse(); - let threshold = (if args_len > 2 { &path[2] } else { "" }).parse(); - match (args_len, method, document, signature, threshold) { - (3, &HttpMethod::Post, Ok(document), Ok(signature), Ok(threshold)) => Request::GenerateDocumentKey(document, signature, threshold), - (2, &HttpMethod::Get, Ok(document), Ok(signature), _) => Request::GetDocumentKey(document, signature), + let document = path[args_offset].parse(); + let signature = path[args_offset + 1].parse(); + let threshold = (if args_len > args_offset + 2 { &path[args_offset + 2] } else { "" }).parse(); + match (args_prefix, args_len, method, document, signature, threshold) { + ("", 3, &HttpMethod::Post, Ok(document), Ok(signature), Ok(threshold)) => Request::GenerateDocumentKey(document, signature, threshold), + ("", 2, &HttpMethod::Get, Ok(document), Ok(signature), _) => Request::GetDocumentKey(document, signature), + ("shadow", 3, &HttpMethod::Get, Ok(document), Ok(signature), _) => Request::GetDocumentKeyShadow(document, signature), _ => Request::Invalid, } } diff --git a/secret_store/src/key_server.rs b/secret_store/src/key_server.rs index 598f06338..64dc47a50 100644 --- a/secret_store/src/key_server.rs +++ b/secret_store/src/key_server.rs @@ -26,7 +26,7 @@ use super::acl_storage::AclStorage; use super::key_storage::KeyStorage; use key_server_cluster::ClusterCore; use traits::KeyServer; -use types::all::{Error, RequestSignature, DocumentAddress, DocumentEncryptedKey, ClusterConfiguration}; +use types::all::{Error, RequestSignature, DocumentAddress, DocumentEncryptedKey, DocumentEncryptedKeyShadow, ClusterConfiguration}; use key_server_cluster::{ClusterClient, ClusterConfiguration as NetClusterConfiguration}; /// Secret store key server implementation @@ -38,7 +38,7 @@ pub struct KeyServerImpl { pub struct KeyServerCore { close: Option>, handle: Option>, - cluster: Option>, + cluster: Arc, } impl KeyServerImpl { @@ -53,7 +53,6 @@ impl KeyServerImpl { /// Get cluster client reference. pub fn cluster(&self) -> Arc { self.data.lock().cluster.clone() - .expect("cluster can be None in test cfg only; test cfg is for correct tests; qed") } } @@ -64,9 +63,7 @@ impl KeyServer for KeyServerImpl { .map_err(|_| Error::BadSignature)?; // generate document key - let data = self.data.lock(); - let encryption_session = data.cluster.as_ref().expect("cluster can be None in test cfg only; test cfg is for correct tests; qed") - .new_encryption_session(document.clone(), threshold)?; + let encryption_session = self.data.lock().cluster.new_encryption_session(document.clone(), threshold)?; let document_key = encryption_session.wait()?; // encrypt document key with requestor public key @@ -80,17 +77,21 @@ impl KeyServer for KeyServerImpl { let public = ethkey::recover(signature, document) .map_err(|_| Error::BadSignature)?; + // decrypt document key - let data = self.data.lock(); - let decryption_session = data.cluster.as_ref().expect("cluster can be None in test cfg only; test cfg is for correct tests; qed") - .new_decryption_session(document.clone(), signature.clone())?; - let document_key = decryption_session.wait()?; + let decryption_session = self.data.lock().cluster.new_decryption_session(document.clone(), signature.clone(), false)?; + let document_key = decryption_session.wait()?.decrypted_secret; // encrypt document key with requestor public key let document_key = ethcrypto::ecies::encrypt_single_message(&public, &document_key) .map_err(|err| Error::Internal(format!("Error encrypting document key: {}", err)))?; Ok(document_key) } + + fn document_key_shadow(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result { + let decryption_session = self.data.lock().cluster.new_decryption_session(document.clone(), signature.clone(), false)?; + decryption_session.wait().map_err(Into::into) + } } impl KeyServerCore { @@ -129,7 +130,7 @@ impl KeyServerCore { Ok(KeyServerCore { close: Some(stop), handle: Some(handle), - cluster: Some(cluster), + cluster: cluster, }) } } @@ -149,24 +150,9 @@ mod tests { use ethkey::{self, Random, Generator}; use acl_storage::tests::DummyAclStorage; use key_storage::tests::DummyKeyStorage; - use types::all::{ClusterConfiguration, NodeAddress, EncryptionConfiguration, DocumentEncryptedKey, DocumentKey}; - use super::super::{RequestSignature, DocumentAddress}; + use types::all::{ClusterConfiguration, NodeAddress, EncryptionConfiguration}; use super::{KeyServer, KeyServerImpl}; - const DOCUMENT1: &'static str = "0000000000000000000000000000000000000000000000000000000000000001"; - const PRIVATE1: &'static str = "03055e18a8434dcc9061cc1b81c4ef84dc7cf4574d755e52cdcf0c8898b25b11"; - - fn make_signature(secret: &str, document: &'static str) -> RequestSignature { - let secret = secret.parse().unwrap(); - let document: DocumentAddress = document.into(); - ethkey::sign(&secret, &document).unwrap() - } - - fn decrypt_document_key(secret: &str, document_key: DocumentEncryptedKey) -> DocumentKey { - let secret = secret.parse().unwrap(); - ethcrypto::ecies::decrypt_single_message(&secret, &document_key).unwrap() - } - #[test] fn document_key_generation_and_retrievement_works_over_network() { //::util::log::init_log(); @@ -208,15 +194,16 @@ mod tests { let test_cases = [0, 1, 2]; for threshold in &test_cases { // generate document key - // TODO: it is an error that we can regenerate key for the same DOCUMENT - let signature = make_signature(PRIVATE1, DOCUMENT1); - let generated_key = key_servers[0].generate_document_key(&signature, &DOCUMENT1.into(), *threshold).unwrap(); - let generated_key = decrypt_document_key(PRIVATE1, generated_key); + let document = Random.generate().unwrap().secret().clone(); + let secret = Random.generate().unwrap().secret().clone(); + let signature = ethkey::sign(&secret, &document).unwrap(); + let generated_key = key_servers[0].generate_document_key(&signature, &document, *threshold).unwrap(); + let generated_key = ethcrypto::ecies::decrypt_single_message(&secret, &generated_key).unwrap(); // now let's try to retrieve key back for key_server in key_servers.iter() { - let retrieved_key = key_server.document_key(&signature, &DOCUMENT1.into()).unwrap(); - let retrieved_key = decrypt_document_key(PRIVATE1, retrieved_key); + let retrieved_key = key_server.document_key(&signature, &document).unwrap(); + let retrieved_key = ethcrypto::ecies::decrypt_single_message(&secret, &retrieved_key).unwrap(); assert_eq!(retrieved_key, generated_key); } } diff --git a/secret_store/src/key_server_cluster/cluster.rs b/secret_store/src/key_server_cluster/cluster.rs index 388a79aef..55b302757 100644 --- a/secret_store/src/key_server_cluster/cluster.rs +++ b/secret_store/src/key_server_cluster/cluster.rs @@ -23,7 +23,7 @@ use std::net::{SocketAddr, IpAddr}; use futures::{finished, failed, Future, Stream, BoxFuture}; use futures_cpupool::CpuPool; use parking_lot::{RwLock, Mutex}; -use tokio_core::io::IoFuture; +use tokio_io::IoFuture; use tokio_core::reactor::{Handle, Remote, Timeout, Interval}; use tokio_core::net::{TcpListener, TcpStream}; use ethkey::{Secret, KeyPair, Signature, Random, Generator}; @@ -45,7 +45,7 @@ pub trait ClusterClient: Send + Sync { /// Start new encryption session. fn new_encryption_session(&self, session_id: SessionId, threshold: usize) -> Result, Error>; /// Start new decryption session. - fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature) -> Result, Error>; + fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature, is_shadow_decryption: bool) -> Result, Error>; } /// Cluster access for single encryption/decryption participant. @@ -181,7 +181,7 @@ pub struct Connection { /// Tcp stream. stream: SharedTcpStream, /// Connection key. - key: Secret, + key: KeyPair, /// Last message time. last_message_time: Mutex, } @@ -649,9 +649,14 @@ impl ClusterSessions { pub fn new_encryption_session(&self, _master: NodeId, session_id: SessionId, cluster: Arc) -> Result, Error> { let mut encryption_sessions = self.encryption_sessions.write(); + // check that there's no active encryption session with the same id if encryption_sessions.contains_key(&session_id) { return Err(Error::DuplicateSessionId); } + // check that there's no finished encryption session with the same id + if self.key_storage.contains(&session_id) { + return Err(Error::DuplicateSessionId); + } let session = Arc::new(EncryptionSessionImpl::new(EncryptionSessionParams { id: session_id.clone(), @@ -865,14 +870,14 @@ impl ClusterClient for ClusterClientImpl { Ok(session) } - fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature) -> Result, Error> { + fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature, is_shadow_decryption: bool) -> Result, Error> { let mut connected_nodes = self.data.connections.connected_nodes(); connected_nodes.insert(self.data.self_key_pair.public().clone()); let access_key = Random.generate()?.secret().clone(); let cluster = Arc::new(ClusterView::new(self.data.clone(), connected_nodes.clone())); let session = self.data.sessions.new_decryption_session(self.data.self_key_pair.public().clone(), session_id, access_key, cluster)?; - session.initialize(requestor_signature)?; + session.initialize(requestor_signature, is_shadow_decryption)?; Ok(session) } } diff --git a/secret_store/src/key_server_cluster/decryption_session.rs b/secret_store/src/key_server_cluster/decryption_session.rs index 652ed5c5a..5a8c136c6 100644 --- a/secret_store/src/key_server_cluster/decryption_session.rs +++ b/secret_store/src/key_server_cluster/decryption_session.rs @@ -18,8 +18,9 @@ use std::cmp::{Ord, PartialOrd, Ordering}; use std::collections::{BTreeSet, BTreeMap}; use std::sync::Arc; use parking_lot::{Mutex, Condvar}; +use ethcrypto::ecies::encrypt_single_message; use ethkey::{self, Secret, Public, Signature}; -use key_server_cluster::{Error, AclStorage, DocumentKeyShare, NodeId, SessionId}; +use key_server_cluster::{Error, AclStorage, DocumentKeyShare, NodeId, SessionId, DocumentEncryptedKeyShadow}; use key_server_cluster::cluster::Cluster; use key_server_cluster::math; use key_server_cluster::message::{Message, DecryptionMessage, InitializeDecryptionSession, ConfirmDecryptionInitialization, @@ -28,7 +29,7 @@ use key_server_cluster::message::{Message, DecryptionMessage, InitializeDecrypti /// Decryption session API. pub trait Session: Send + Sync + 'static { /// Wait until session is completed. Returns distributely restored secret key. - fn wait(&self) -> Result; + fn wait(&self) -> Result; } /// Distributed decryption session. @@ -83,6 +84,15 @@ pub struct SessionParams { pub cluster: Arc, } +#[derive(Debug)] +/// Partial decryption result. +struct PartialDecryptionResult { + /// Shadow point. + pub shadow_point: Public, + /// Decryption shadow coefficient, if requested. + pub decrypt_shadow: Option>, +} + #[derive(Debug)] /// Mutable data of encryption (distributed key generation) session. struct SessionData { @@ -94,6 +104,8 @@ struct SessionData { master: Option, /// Public key of requestor. requestor: Option, + /// Is shadow decryption requested? + is_shadow_decryption: Option, // === Values, filled during session initialization === /// Nodes, which have been requested for decryption initialization. @@ -105,11 +117,11 @@ struct SessionData { // === Values, filled during partial decryption === /// Shadow points, received from nodes as a response to partial decryption request. - shadow_points: BTreeMap, + shadow_points: BTreeMap, /// === Values, filled during final decryption === /// Decrypted secret - decrypted_secret: Option>, + decrypted_secret: Option>, } #[derive(Debug, Clone, PartialEq)] @@ -146,6 +158,7 @@ impl SessionImpl { state: SessionState::WaitingForInitialization, master: None, requestor: None, + is_shadow_decryption: None, requested_nodes: BTreeSet::new(), rejected_nodes: BTreeSet::new(), confirmed_nodes: BTreeSet::new(), @@ -174,12 +187,12 @@ impl SessionImpl { #[cfg(test)] /// Get decrypted secret - pub fn decrypted_secret(&self) -> Option { + pub fn decrypted_secret(&self) -> Option { self.data.lock().decrypted_secret.clone().and_then(|r| r.ok()) } /// Initialize decryption session. - pub fn initialize(&self, requestor_signature: Signature) -> Result<(), Error> { + pub fn initialize(&self, requestor_signature: Signature, is_shadow_decryption: bool) -> Result<(), Error> { let mut data = self.data.lock(); // check state @@ -194,6 +207,7 @@ impl SessionImpl { data.master = Some(self.node().clone()); data.state = SessionState::WaitingForInitializationConfirm; data.requestor = Some(requestor_public.clone()); + data.is_shadow_decryption = Some(is_shadow_decryption); data.requested_nodes.extend(self.encrypted_data.id_numbers.keys().cloned()); // ..and finally check access on our's own @@ -209,6 +223,7 @@ impl SessionImpl { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), requestor_signature: requestor_signature.clone().into(), + is_shadow_decryption: is_shadow_decryption, })))?; } }, @@ -249,6 +264,7 @@ impl SessionImpl { data.state = if is_requestor_allowed_to_read { SessionState::WaitingForPartialDecryptionRequest } else { SessionState::Failed }; data.requestor = Some(requestor_public); + data.is_shadow_decryption = Some(message.is_shadow_decryption); // respond to master node data.master = Some(sender.clone()); @@ -316,14 +332,17 @@ impl SessionImpl { } // calculate shadow point - let shadow_point = { + let decryption_result = { let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryptionRequest follows initialization; qed"); - do_partial_decryption(self.node(), &requestor, &message.nodes.iter().cloned().map(Into::into).collect(), &self.access_key, &self.encrypted_data)? + let is_shadow_decryption = data.is_shadow_decryption.expect("is_shadow_decryption is filled during initialization; WaitingForPartialDecryptionRequest follows initialization; qed"); + let nodes = message.nodes.iter().cloned().map(Into::into).collect(); + do_partial_decryption(self.node(), &requestor, is_shadow_decryption, &nodes, &self.access_key, &self.encrypted_data)? }; self.cluster.send(&sender, Message::Decryption(DecryptionMessage::PartialDecryption(PartialDecryption { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), - shadow_point: shadow_point.into(), + shadow_point: decryption_result.shadow_point.into(), + decrypt_shadow: decryption_result.decrypt_shadow, })))?; // update sate @@ -348,7 +367,10 @@ impl SessionImpl { if !data.confirmed_nodes.remove(&sender) { return Err(Error::InvalidStateForRequest); } - data.shadow_points.insert(sender, message.shadow_point.clone().into()); + data.shadow_points.insert(sender, PartialDecryptionResult { + shadow_point: message.shadow_point.clone().into(), + decrypt_shadow: message.decrypt_shadow.clone(), + }); // check if we have enough shadow points to decrypt the secret if data.shadow_points.len() != self.encrypted_data.threshold + 1 { @@ -390,22 +412,38 @@ impl SessionImpl { })))?; } - assert!(data.confirmed_nodes.remove(&self_node_id)); - - let shadow_point = { - let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryption follows initialization; qed"); - do_partial_decryption(&self_node_id, &requestor, &data.confirmed_nodes, &access_key, &encrypted_data)? - }; - data.shadow_points.insert(self_node_id.clone(), shadow_point); + if data.confirmed_nodes.remove(&self_node_id) { + let decryption_result = { + let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryption follows initialization; qed"); + let is_shadow_decryption = data.is_shadow_decryption.expect("is_shadow_decryption is filled during initialization; WaitingForPartialDecryption follows initialization; qed"); + do_partial_decryption(&self_node_id, &requestor, is_shadow_decryption, &data.confirmed_nodes, &access_key, &encrypted_data)? + }; + data.shadow_points.insert(self_node_id.clone(), decryption_result); + } Ok(()) } fn do_decryption(access_key: Secret, encrypted_data: &DocumentKeyShare, data: &mut SessionData) -> Result<(), Error> { // decrypt the secret using shadow points - let joint_shadow_point = math::compute_joint_shadow_point(data.shadow_points.values())?; + let joint_shadow_point = math::compute_joint_shadow_point(data.shadow_points.values().map(|s| &s.shadow_point))?; let decrypted_secret = math::decrypt_with_joint_shadow(encrypted_data.threshold, &access_key, &encrypted_data.encrypted_point, &joint_shadow_point)?; - data.decrypted_secret = Some(Ok(decrypted_secret)); + let is_shadow_decryption = data.is_shadow_decryption.expect("is_shadow_decryption is filled during initialization; decryption follows initialization; qed"); + let (common_point, decrypt_shadows) = if is_shadow_decryption { + ( + Some(math::make_common_shadow_point(encrypted_data.threshold, encrypted_data.common_point.clone())?), + Some(data.shadow_points.values() + .map(|s| s.decrypt_shadow.as_ref().expect("decrypt_shadow is filled during partial decryption; decryption follows partial decryption; qed").clone()) + .collect()) + ) + } else { + (None, None) + }; + data.decrypted_secret = Some(Ok(DocumentEncryptedKeyShadow { + decrypted_secret: decrypted_secret, + common_point: common_point, + decrypt_shadows: decrypt_shadows, + })); // switch to completed state data.state = SessionState::Finished; @@ -415,7 +453,7 @@ impl SessionImpl { } impl Session for SessionImpl { - fn wait(&self) -> Result { + fn wait(&self) -> Result { let mut data = self.data.lock(); if !data.decrypted_secret.is_some() { self.completed.wait(&mut data); @@ -492,15 +530,22 @@ fn process_initialization_response(encrypted_data: &DocumentKeyShare, data: &mut Ok(()) } -fn do_partial_decryption(node: &NodeId, _requestor_public: &Public, participants: &BTreeSet, access_key: &Secret, encrypted_data: &DocumentKeyShare) -> Result { +fn do_partial_decryption(node: &NodeId, requestor_public: &Public, is_shadow_decryption: bool, participants: &BTreeSet, access_key: &Secret, encrypted_data: &DocumentKeyShare) -> Result { let node_id_number = &encrypted_data.id_numbers[node]; let node_secret_share = &encrypted_data.secret_share; let other_id_numbers = participants.iter() .filter(|id| *id != node) .map(|id| &encrypted_data.id_numbers[id]); - // TODO: commutative encryption using _requestor_public let node_shadow = math::compute_node_shadow(node_id_number, node_secret_share, other_id_numbers)?; - math::compute_node_shadow_point(access_key, &encrypted_data.common_point, &node_shadow) + let decrypt_shadow = if is_shadow_decryption { Some(math::generate_random_scalar()?) } else { None }; + let (shadow_point, decrypt_shadow) = math::compute_node_shadow_point(access_key, &encrypted_data.common_point, &node_shadow, decrypt_shadow)?; + Ok(PartialDecryptionResult { + shadow_point: shadow_point, + decrypt_shadow: match decrypt_shadow { + None => None, + Some(decrypt_shadow) => Some(encrypt_single_message(requestor_public, &**decrypt_shadow)?), + }, + }) } #[cfg(test)] @@ -509,10 +554,11 @@ mod tests { use std::collections::BTreeMap; use super::super::super::acl_storage::tests::DummyAclStorage; use ethkey::{self, Random, Generator, Public, Secret}; - use key_server_cluster::{NodeId, DocumentKeyShare, SessionId, Error}; + use key_server_cluster::{NodeId, DocumentKeyShare, SessionId, Error, DocumentEncryptedKeyShadow}; use key_server_cluster::cluster::tests::DummyCluster; use key_server_cluster::decryption_session::{SessionImpl, SessionParams, SessionState}; use key_server_cluster::message::{self, Message, DecryptionMessage}; + use key_server_cluster::math; const SECRET_PLAIN: &'static str = "d2b57ae7619e070af0af6bc8c703c0cd27814c54d5d6a999cacac0da34ede279ca0d9216e85991029e54e2f0c92ee0bd30237725fa765cbdbfc4529489864c5f"; @@ -660,18 +706,19 @@ mod tests { #[test] fn fails_to_initialize_when_already_initialized() { let (_, _, sessions) = prepare_decryption_sessions(); - assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(), ()); - assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap_err(), Error::InvalidStateForRequest); + assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), false).unwrap(), ()); + assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), false).unwrap_err(), Error::InvalidStateForRequest); } #[test] fn fails_to_accept_initialization_when_already_initialized() { let (_, _, sessions) = prepare_decryption_sessions(); - assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(), ()); + assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), false).unwrap(), ()); assert_eq!(sessions[0].on_initialize_session(sessions[1].node().clone(), &message::InitializeDecryptionSession { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), + is_shadow_decryption: false, }).unwrap_err(), Error::InvalidStateForRequest); } @@ -682,6 +729,7 @@ mod tests { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), + is_shadow_decryption: false, }).unwrap(), ()); assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), &message::RequestPartialDecryption { session: SessionId::default().into(), @@ -702,6 +750,7 @@ mod tests { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), + is_shadow_decryption: false, }).unwrap(), ()); assert_eq!(sessions[1].on_partial_decryption_requested(sessions[2].node().clone(), &message::RequestPartialDecryption { session: SessionId::default().into(), @@ -717,6 +766,7 @@ mod tests { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), + is_shadow_decryption: false, }).unwrap(), ()); assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), &message::RequestPartialDecryption { session: SessionId::default().into(), @@ -732,13 +782,14 @@ mod tests { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), shadow_point: Random.generate().unwrap().public().clone().into(), + decrypt_shadow: None, }).unwrap_err(), Error::InvalidStateForRequest); } #[test] fn fails_to_accept_partial_decrypt_twice() { let (clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(); + sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), false).unwrap(); let mut pd_from = None; let mut pd_msg = None; @@ -762,7 +813,7 @@ mod tests { // now let's try to do a decryption let key_pair = Random.generate().unwrap(); let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap(); - sessions[0].initialize(signature).unwrap(); + sessions[0].initialize(signature, false).unwrap(); do_messages_exchange(&clusters, &sessions); @@ -773,7 +824,45 @@ mod tests { assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::WaitingForPartialDecryptionRequest).count(), 1); // 3) 1 session has decrypted key value assert!(sessions.iter().skip(1).all(|s| s.decrypted_secret().is_none())); - assert_eq!(sessions[0].decrypted_secret(), Some(SECRET_PLAIN.into())); + assert_eq!(sessions[0].decrypted_secret(), Some(DocumentEncryptedKeyShadow { + decrypted_secret: SECRET_PLAIN.into(), + common_point: None, + decrypt_shadows: None, + })); + } + + #[test] + fn complete_shadow_dec_session() { + let (clusters, _, sessions) = prepare_decryption_sessions(); + + // now let's try to do a decryption + let key_pair = Random.generate().unwrap(); + let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap(); + sessions[0].initialize(signature, true).unwrap(); + + do_messages_exchange(&clusters, &sessions); + + // now check that: + // 1) 4 of 5 sessions are in Finished state + assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::Finished).count(), 4); + // 2) 1 session is in WaitingForPartialDecryptionRequest state + assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::WaitingForPartialDecryptionRequest).count(), 1); + // 3) 1 session has decrypted key value + assert!(sessions.iter().skip(1).all(|s| s.decrypted_secret().is_none())); + + let decrypted_secret = sessions[0].decrypted_secret().unwrap(); + // check that decrypted_secret != SECRET_PLAIN + assert!(decrypted_secret.decrypted_secret != SECRET_PLAIN.into()); + // check that common point && shadow coefficients are returned + assert!(decrypted_secret.common_point.is_some()); + assert!(decrypted_secret.decrypt_shadows.is_some()); + // check that KS client is able to restore original secret + use ethcrypto::ecies::decrypt_single_message; + let decrypt_shadows: Vec<_> = decrypted_secret.decrypt_shadows.unwrap().into_iter() + .map(|c| Secret::from_slice(&decrypt_single_message(key_pair.secret(), &c).unwrap()).unwrap()) + .collect(); + let decrypted_secret = math::decrypt_with_shadow_coefficients(decrypted_secret.decrypted_secret, decrypted_secret.common_point.unwrap(), decrypt_shadows).unwrap(); + assert_eq!(decrypted_secret, SECRET_PLAIN.into()); } #[test] @@ -783,7 +872,7 @@ mod tests { // now let's try to do a decryption let key_pair = Random.generate().unwrap(); let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap(); - sessions[0].initialize(signature).unwrap(); + sessions[0].initialize(signature, false).unwrap(); // we need 4 out of 5 nodes to agree to do a decryption // let's say that 2 of these nodes are disagree @@ -801,6 +890,33 @@ mod tests { assert!(sessions.iter().all(|s| s.decrypted_secret().is_none())); } + #[test] + fn complete_dec_session_with_acl_check_failed_on_master() { + let (clusters, acl_storages, sessions) = prepare_decryption_sessions(); + + // we need 4 out of 5 nodes to agree to do a decryption + // let's say that 1 of these nodes (master) is disagree + let key_pair = Random.generate().unwrap(); + acl_storages[0].prohibit(key_pair.public().clone(), SessionId::default()); + + // now let's try to do a decryption + let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap(); + sessions[0].initialize(signature, false).unwrap(); + + do_messages_exchange(&clusters, &sessions); + + // now check that: + // 1) 4 of 5 sessions are in Finished state + assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::Finished).count(), 5); + // 2) 1 session has decrypted key value + assert!(sessions.iter().skip(1).all(|s| s.decrypted_secret().is_none())); + assert_eq!(sessions[0].decrypted_secret(), Some(DocumentEncryptedKeyShadow { + decrypted_secret: SECRET_PLAIN.into(), + common_point: None, + decrypt_shadows: None, + })); + } + #[test] fn decryption_session_works_over_network() { // TODO diff --git a/secret_store/src/key_server_cluster/io/handshake.rs b/secret_store/src/key_server_cluster/io/handshake.rs index 0d71d25aa..38d8a6ac1 100644 --- a/secret_store/src/key_server_cluster/io/handshake.rs +++ b/secret_store/src/key_server_cluster/io/handshake.rs @@ -17,21 +17,22 @@ use std::io; use std::collections::BTreeSet; use futures::{Future, Poll, Async}; +use tokio_io::{AsyncRead, AsyncWrite}; use ethkey::{Random, Generator, KeyPair, Secret, sign, verify_public}; use util::H256; use key_server_cluster::{NodeId, Error}; use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature}; use key_server_cluster::io::{write_message, write_encrypted_message, WriteMessage, ReadMessage, - read_message, compute_shared_key}; + read_message, read_encrypted_message, compute_shared_key}; /// Start handshake procedure with another node from the cluster. -pub fn handshake(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet) -> Handshake where A: io::Write + io::Read { +pub fn handshake(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into); handshake_with_plain_confirmation(a, self_confirmation_plain, self_key_pair, trusted_nodes) } /// Start handshake procedure with another node from the cluster and given plain confirmation. -pub fn handshake_with_plain_confirmation(a: A, self_confirmation_plain: Result, self_key_pair: KeyPair, trusted_nodes: BTreeSet) -> Handshake where A: io::Write + io::Read { +pub fn handshake_with_plain_confirmation(a: A, self_confirmation_plain: Result, self_key_pair: KeyPair, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { let (error, state) = match self_confirmation_plain.clone() .and_then(|c| Handshake::::make_public_key_message(self_key_pair.public().clone(), c)) { Ok(message) => (None, HandshakeState::SendPublicKey(write_message(a, message))), @@ -52,7 +53,7 @@ pub fn handshake_with_plain_confirmation(a: A, self_confirmation_plain: Resul } /// Wait for handshake procedure to be started by another node from the cluster. -pub fn accept_handshake(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet) -> Handshake where A: io::Write + io::Read { +pub fn accept_handshake(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into); let (error, state) = match self_confirmation_plain.clone() { Ok(_) => (None, HandshakeState::ReceivePublicKey(read_message(a))), @@ -78,7 +79,7 @@ pub struct HandshakeResult { /// Node id. pub node_id: NodeId, /// Shared key. - pub shared_key: Secret, + pub shared_key: KeyPair, } /// Future handshake procedure. @@ -91,7 +92,7 @@ pub struct Handshake { trusted_nodes: BTreeSet, other_node_id: Option, other_confirmation_plain: Option, - shared_key: Option, + shared_key: Option, } /// Active handshake state. @@ -103,7 +104,7 @@ enum HandshakeState { Finished, } -impl Handshake where A: io::Read + io::Write { +impl Handshake where A: AsyncRead + AsyncWrite { #[cfg(test)] pub fn set_self_confirmation_plain(&mut self, self_confirmation_plain: H256) { self.self_confirmation_plain = self_confirmation_plain; @@ -123,7 +124,7 @@ impl Handshake where A: io::Read + io::Write { } } -impl Future for Handshake where A: io::Read + io::Write { +impl Future for Handshake where A: AsyncRead + AsyncWrite { type Item = (A, Result); type Error = io::Error; @@ -207,7 +208,9 @@ impl Future for Handshake where A: io::Read + io::Write { let (stream, _) = try_ready!(future.poll()); (HandshakeState::ReceivePrivateKeySignature( - read_message(stream) + read_encrypted_message(stream, + self.shared_key.as_ref().expect("shared_key is filled in Send/ReceivePublicKey; SendPrivateKeySignature follows Send/ReceivePublicKey; qed").clone() + ) ), Async::NotReady) }, HandshakeState::ReceivePrivateKeySignature(ref mut future) => { @@ -247,9 +250,9 @@ impl Future for Handshake where A: io::Read + io::Write { mod tests { use std::collections::BTreeSet; use futures::Future; - use ethcrypto::ecdh::agree; use ethkey::{Random, Generator, sign}; use util::H256; + use key_server_cluster::io::message::compute_shared_key; use key_server_cluster::io::message::tests::TestIo; use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature}; use super::{handshake_with_plain_confirmation, accept_handshake, HandshakeResult}; @@ -263,24 +266,15 @@ mod tests { let peer_confirmation_plain = *Random.generate().unwrap().secret().clone(); let self_confirmation_signed = sign(peer_key_pair.secret(), &self_confirmation_plain).unwrap(); - let peer_confirmation_signed = sign(self_key_pair.secret(), &peer_confirmation_plain).unwrap(); io.add_input_message(Message::Cluster(ClusterMessage::NodePublicKey(NodePublicKey { node_id: peer_key_pair.public().clone().into(), confirmation_plain: peer_confirmation_plain.into(), }))); - io.add_input_message(Message::Cluster(ClusterMessage::NodePrivateKeySignature(NodePrivateKeySignature { + io.add_encrypted_input_message(Message::Cluster(ClusterMessage::NodePrivateKeySignature(NodePrivateKeySignature { confirmation_signed: self_confirmation_signed.into(), }))); - io.add_output_message(Message::Cluster(ClusterMessage::NodePublicKey(NodePublicKey { - node_id: self_key_pair.public().clone().into(), - confirmation_plain: self_confirmation_plain.clone().into(), - }))); - io.add_output_message(Message::Cluster(ClusterMessage::NodePrivateKeySignature(NodePrivateKeySignature { - confirmation_signed: peer_confirmation_signed.into(), - }))); - (self_confirmation_plain, io) } @@ -289,7 +283,7 @@ mod tests { let (self_confirmation_plain, io) = prepare_test_io(); let self_key_pair = io.self_key_pair().clone(); let trusted_nodes: BTreeSet<_> = vec![io.peer_public().clone()].into_iter().collect(); - let shared_key = agree(self_key_pair.secret(), trusted_nodes.iter().nth(0).unwrap()).unwrap(); + let shared_key = compute_shared_key(self_key_pair.secret(), trusted_nodes.iter().nth(0).unwrap()).unwrap(); let handshake = handshake_with_plain_confirmation(io, Ok(self_confirmation_plain), self_key_pair, trusted_nodes); let handshake_result = handshake.wait().unwrap(); @@ -297,7 +291,6 @@ mod tests { node_id: handshake_result.0.peer_public().clone(), shared_key: shared_key, })); - handshake_result.0.assert_output(); } #[test] @@ -305,7 +298,7 @@ mod tests { let (self_confirmation_plain, io) = prepare_test_io(); let self_key_pair = io.self_key_pair().clone(); let trusted_nodes: BTreeSet<_> = vec![io.peer_public().clone()].into_iter().collect(); - let shared_key = agree(self_key_pair.secret(), io.peer_public()).unwrap(); + let shared_key = compute_shared_key(self_key_pair.secret(), trusted_nodes.iter().nth(0).unwrap()).unwrap(); let mut handshake = accept_handshake(io, self_key_pair, trusted_nodes); handshake.set_self_confirmation_plain(self_confirmation_plain); @@ -315,6 +308,5 @@ mod tests { node_id: handshake_result.0.peer_public().clone(), shared_key: shared_key, })); - handshake_result.0.assert_output(); } } diff --git a/secret_store/src/key_server_cluster/io/message.rs b/secret_store/src/key_server_cluster/io/message.rs index bcabebf76..fcc605a8e 100644 --- a/secret_store/src/key_server_cluster/io/message.rs +++ b/secret_store/src/key_server_cluster/io/message.rs @@ -20,7 +20,10 @@ use std::ops::Deref; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use serde_json; use ethcrypto::ecdh::agree; -use ethkey::{Public, Secret}; +use ethcrypto::ecies::{encrypt_single_message, decrypt_single_message}; +use ethkey::{Public, Secret, KeyPair}; +use ethkey::math::curve_order; +use util::{H256, U256}; use key_server_cluster::Error; use key_server_cluster::message::{Message, ClusterMessage, EncryptionMessage, DecryptionMessage}; @@ -82,20 +85,11 @@ pub fn serialize_message(message: Message) -> Result { }; let payload = payload.map_err(|err| Error::Serde(err.to_string()))?; - let payload_len = payload.len(); - if payload_len > u16::MAX as usize { - return Err(Error::InvalidMessage); - } - - let header = MessageHeader { + build_serialized_message(MessageHeader { kind: message_kind, version: 1, - size: payload_len as u16, - }; - - let mut serialized_message = serialize_header(&header)?; - serialized_message.extend(payload); - Ok(SerializedMessage(serialized_message)) + size: 0, + }, payload) } /// Deserialize message. @@ -127,18 +121,30 @@ pub fn deserialize_message(header: &MessageHeader, payload: Vec) -> Result Result { - Ok(message) // TODO: implement me +pub fn encrypt_message(key: &KeyPair, message: SerializedMessage) -> Result { + let mut header: Vec<_> = message.into(); + let payload = header.split_off(MESSAGE_HEADER_SIZE); + let encrypted_payload = encrypt_single_message(key.public(), &payload)?; + + let header = deserialize_header(&header)?; + build_serialized_message(header, encrypted_payload) } /// Decrypt serialized message. -pub fn decrypt_message(_key: &Secret, payload: Vec) -> Result, Error> { - Ok(payload) // TODO: implement me +pub fn decrypt_message(key: &KeyPair, payload: Vec) -> Result, Error> { + Ok(decrypt_single_message(key.secret(), &payload)?) } /// Compute shared encryption key. -pub fn compute_shared_key(self_secret: &Secret, other_public: &Public) -> Result { - Ok(agree(self_secret, other_public)?) +pub fn compute_shared_key(self_secret: &Secret, other_public: &Public) -> Result { + // secret key created in agree function is invalid, as it is not calculated mod EC.field.n + // => let's do it manually + let shared_secret = agree(self_secret, other_public)?; + let shared_secret: H256 = (*shared_secret).into(); + let shared_secret: U256 = shared_secret.into(); + let shared_secret: H256 = (shared_secret % curve_order()).into(); + let shared_key_pair = KeyPair::from_secret_slice(&*shared_secret)?; + Ok(shared_key_pair) } /// Serialize message header. @@ -160,29 +166,44 @@ pub fn deserialize_header(data: &[u8]) -> Result { }) } +/// Build serialized message from header && payload +fn build_serialized_message(mut header: MessageHeader, payload: Vec) -> Result { + let payload_len = payload.len(); + if payload_len > u16::MAX as usize { + return Err(Error::InvalidMessage); + } + header.size = payload.len() as u16; + + let mut message = serialize_header(&header)?; + message.extend(payload); + Ok(SerializedMessage(message)) +} + #[cfg(test)] pub mod tests { use std::io; + use futures::Poll; + use tokio_io::{AsyncRead, AsyncWrite}; use ethkey::{KeyPair, Public}; use key_server_cluster::message::Message; - use super::{MESSAGE_HEADER_SIZE, MessageHeader, serialize_message, serialize_header, deserialize_header}; + use super::{MESSAGE_HEADER_SIZE, MessageHeader, compute_shared_key, encrypt_message, serialize_message, + serialize_header, deserialize_header}; pub struct TestIo { self_key_pair: KeyPair, peer_public: Public, + shared_key_pair: KeyPair, input_buffer: io::Cursor>, - output_buffer: Vec, - expected_output_buffer: Vec, } impl TestIo { pub fn new(self_key_pair: KeyPair, peer_public: Public) -> Self { + let shared_key_pair = compute_shared_key(self_key_pair.secret(), &peer_public).unwrap(); TestIo { self_key_pair: self_key_pair, peer_public: peer_public, + shared_key_pair: shared_key_pair, input_buffer: io::Cursor::new(Vec::new()), - output_buffer: Vec::new(), - expected_output_buffer: Vec::new(), } } @@ -203,14 +224,21 @@ pub mod tests { } } - pub fn add_output_message(&mut self, message: Message) { - let serialized_message = serialize_message(message).unwrap(); + pub fn add_encrypted_input_message(&mut self, message: Message) { + let serialized_message = encrypt_message(&self.shared_key_pair, serialize_message(message).unwrap()).unwrap(); let serialized_message: Vec<_> = serialized_message.into(); - self.expected_output_buffer.extend(serialized_message); + let input_buffer = self.input_buffer.get_mut(); + for b in serialized_message { + input_buffer.push(b); + } } + } - pub fn assert_output(&self) { - assert_eq!(self.output_buffer, self.expected_output_buffer); + impl AsyncRead for TestIo {} + + impl AsyncWrite for TestIo { + fn shutdown(&mut self) -> Poll<(), io::Error> { + Ok(().into()) } } @@ -222,11 +250,11 @@ pub mod tests { impl io::Write for TestIo { fn write(&mut self, buf: &[u8]) -> io::Result { - io::Write::write(&mut self.output_buffer, buf) + Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { - io::Write::flush(&mut self.output_buffer) + Ok(()) } } diff --git a/secret_store/src/key_server_cluster/io/read_header.rs b/secret_store/src/key_server_cluster/io/read_header.rs index ab7ce360e..2fd8960e3 100644 --- a/secret_store/src/key_server_cluster/io/read_header.rs +++ b/secret_store/src/key_server_cluster/io/read_header.rs @@ -16,12 +16,13 @@ use std::io; use futures::{Future, Poll, Async}; -use tokio_core::io::{ReadExact, read_exact}; +use tokio_io::AsyncRead; +use tokio_io::io::{ReadExact, read_exact}; use key_server_cluster::Error; use key_server_cluster::io::message::{MESSAGE_HEADER_SIZE, MessageHeader, deserialize_header}; /// Create future for read single message header from the stream. -pub fn read_header(a: A) -> ReadHeader where A: io::Read { +pub fn read_header(a: A) -> ReadHeader where A: AsyncRead { ReadHeader { reader: read_exact(a, [0; MESSAGE_HEADER_SIZE]), } @@ -32,7 +33,7 @@ pub struct ReadHeader { reader: ReadExact, } -impl Future for ReadHeader where A: io::Read { +impl Future for ReadHeader where A: AsyncRead { type Item = (A, Result); type Error = io::Error; diff --git a/secret_store/src/key_server_cluster/io/read_message.rs b/secret_store/src/key_server_cluster/io/read_message.rs index 418e5e31d..1ffb98792 100644 --- a/secret_store/src/key_server_cluster/io/read_message.rs +++ b/secret_store/src/key_server_cluster/io/read_message.rs @@ -16,13 +16,14 @@ use std::io; use futures::{Poll, Future, Async}; -use ethkey::Secret; +use tokio_io::AsyncRead; +use ethkey::KeyPair; use key_server_cluster::Error; use key_server_cluster::message::Message; use key_server_cluster::io::{read_header, ReadHeader, read_payload, read_encrypted_payload, ReadPayload}; /// Create future for read single message from the stream. -pub fn read_message(a: A) -> ReadMessage where A: io::Read { +pub fn read_message(a: A) -> ReadMessage where A: AsyncRead { ReadMessage { key: None, state: ReadMessageState::ReadHeader(read_header(a)), @@ -30,7 +31,7 @@ pub fn read_message(a: A) -> ReadMessage where A: io::Read { } /// Create future for read single encrypted message from the stream. -pub fn read_encrypted_message(a: A, key: Secret) -> ReadMessage where A: io::Read { +pub fn read_encrypted_message(a: A, key: KeyPair) -> ReadMessage where A: AsyncRead { ReadMessage { key: Some(key), state: ReadMessageState::ReadHeader(read_header(a)), @@ -45,11 +46,11 @@ enum ReadMessageState { /// Future for read single message from the stream. pub struct ReadMessage { - key: Option, + key: Option, state: ReadMessageState, } -impl Future for ReadMessage where A: io::Read { +impl Future for ReadMessage where A: AsyncRead { type Item = (A, Result); type Error = io::Error; diff --git a/secret_store/src/key_server_cluster/io/read_payload.rs b/secret_store/src/key_server_cluster/io/read_payload.rs index f6df3155e..1246092e9 100644 --- a/secret_store/src/key_server_cluster/io/read_payload.rs +++ b/secret_store/src/key_server_cluster/io/read_payload.rs @@ -16,14 +16,15 @@ use std::io; use futures::{Poll, Future}; -use tokio_core::io::{read_exact, ReadExact}; -use ethkey::Secret; +use tokio_io::AsyncRead; +use tokio_io::io::{read_exact, ReadExact}; +use ethkey::KeyPair; use key_server_cluster::Error; use key_server_cluster::message::Message; use key_server_cluster::io::message::{MessageHeader, deserialize_message, decrypt_message}; /// Create future for read single message payload from the stream. -pub fn read_payload(a: A, header: MessageHeader) -> ReadPayload where A: io::Read { +pub fn read_payload(a: A, header: MessageHeader) -> ReadPayload where A: AsyncRead { ReadPayload { reader: read_exact(a, vec![0; header.size as usize]), header: header, @@ -32,7 +33,7 @@ pub fn read_payload(a: A, header: MessageHeader) -> ReadPayload where A: i } /// Create future for read single encrypted message payload from the stream. -pub fn read_encrypted_payload(a: A, header: MessageHeader, key: Secret) -> ReadPayload where A: io::Read { +pub fn read_encrypted_payload(a: A, header: MessageHeader, key: KeyPair) -> ReadPayload where A: AsyncRead { ReadPayload { reader: read_exact(a, vec![0; header.size as usize]), header: header, @@ -44,10 +45,10 @@ pub fn read_encrypted_payload(a: A, header: MessageHeader, key: Secret) -> Re pub struct ReadPayload { reader: ReadExact>, header: MessageHeader, - key: Option, + key: Option, } -impl Future for ReadPayload where A: io::Read { +impl Future for ReadPayload where A: AsyncRead { type Item = (A, Result); type Error = io::Error; diff --git a/secret_store/src/key_server_cluster/io/shared_tcp_stream.rs b/secret_store/src/key_server_cluster/io/shared_tcp_stream.rs index 82933c8a2..a847b1428 100644 --- a/secret_store/src/key_server_cluster/io/shared_tcp_stream.rs +++ b/secret_store/src/key_server_cluster/io/shared_tcp_stream.rs @@ -15,7 +15,10 @@ // along with Parity. If not, see . use std::sync::Arc; +use std::net::Shutdown; use std::io::{Read, Write, Error}; +use futures::Poll; +use tokio_io::{AsyncRead, AsyncWrite}; use tokio_core::net::TcpStream; /// Read+Write implementation for Arc. @@ -37,6 +40,14 @@ impl From for SharedTcpStream { } } +impl AsyncRead for SharedTcpStream {} + +impl AsyncWrite for SharedTcpStream { + fn shutdown(&mut self) -> Poll<(), Error> { + self.io.shutdown(Shutdown::Both).map(Into::into) + } +} + impl Read for SharedTcpStream { fn read(&mut self, buf: &mut [u8]) -> Result { Read::read(&mut (&*self.io as &TcpStream), buf) diff --git a/secret_store/src/key_server_cluster/io/write_message.rs b/secret_store/src/key_server_cluster/io/write_message.rs index 457673676..5988634cc 100644 --- a/secret_store/src/key_server_cluster/io/write_message.rs +++ b/secret_store/src/key_server_cluster/io/write_message.rs @@ -16,13 +16,14 @@ use std::io; use futures::{Future, Poll}; -use tokio_core::io::{WriteAll, write_all}; -use ethkey::Secret; +use tokio_io::AsyncWrite; +use tokio_io::io::{WriteAll, write_all}; +use ethkey::KeyPair; use key_server_cluster::message::Message; use key_server_cluster::io::{serialize_message, encrypt_message}; /// Write plain message to the channel. -pub fn write_message(a: A, message: Message) -> WriteMessage where A: io::Write { +pub fn write_message(a: A, message: Message) -> WriteMessage where A: AsyncWrite { let (error, future) = match serialize_message(message) .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) { Ok(message) => (None, write_all(a, message.into())), @@ -35,7 +36,7 @@ pub fn write_message(a: A, message: Message) -> WriteMessage where A: io:: } /// Write encrypted message to the channel. -pub fn write_encrypted_message(a: A, key: &Secret, message: Message) -> WriteMessage where A: io::Write { +pub fn write_encrypted_message(a: A, key: &KeyPair, message: Message) -> WriteMessage where A: AsyncWrite { let (error, future) = match serialize_message(message) .and_then(|message| encrypt_message(key, message)) .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) { @@ -56,7 +57,7 @@ pub struct WriteMessage { future: WriteAll>, } -impl Future for WriteMessage where A: io::Write { +impl Future for WriteMessage where A: AsyncWrite { type Item = (A, Vec); type Error = io::Error; diff --git a/secret_store/src/key_server_cluster/math.rs b/secret_store/src/key_server_cluster/math.rs index fdda08746..c3bef274f 100644 --- a/secret_store/src/key_server_cluster/math.rs +++ b/secret_store/src/key_server_cluster/math.rs @@ -203,12 +203,24 @@ pub fn compute_node_shadow<'a, I>(node_number: &Secret, node_secret_share: &Secr } /// Compute shadow point for the node. -pub fn compute_node_shadow_point(access_key: &Secret, common_point: &Public, node_shadow: &Secret) -> Result { - let mut shadow_key = access_key.clone(); - shadow_key.mul(node_shadow)?; +pub fn compute_node_shadow_point(access_key: &Secret, common_point: &Public, node_shadow: &Secret, decrypt_shadow: Option) -> Result<(Public, Option), Error> { + let mut shadow_key = node_shadow.clone(); + let decrypt_shadow = match decrypt_shadow { + None => None, + Some(mut decrypt_shadow) => { + // update shadow key + shadow_key.mul(&decrypt_shadow)?; + // now udate decrypt shadow itself + decrypt_shadow.dec()?; + decrypt_shadow.mul(node_shadow)?; + Some(decrypt_shadow) + } + }; + shadow_key.mul(access_key)?; + let mut node_shadow_point = common_point.clone(); math::public_mul_secret(&mut node_shadow_point, &shadow_key)?; - Ok(node_shadow_point) + Ok((node_shadow_point, decrypt_shadow)) } /// Compute joint shadow point. @@ -252,6 +264,28 @@ pub fn decrypt_with_joint_shadow(threshold: usize, access_key: &Secret, encrypte Ok(decrypted_point) } +/// Prepare common point for shadow decryption. +pub fn make_common_shadow_point(threshold: usize, mut common_point: Public) -> Result { + if threshold % 2 != 1 { + Ok(common_point) + } else { + math::public_negate(&mut common_point)?; + Ok(common_point) + } +} + +#[cfg(test)] +/// Decrypt shadow-encrypted secret. +pub fn decrypt_with_shadow_coefficients(mut decrypted_shadow: Public, mut common_shadow_point: Public, shadow_coefficients: Vec) -> Result { + let mut shadow_coefficients_sum = shadow_coefficients[0].clone(); + for shadow_coefficient in shadow_coefficients.iter().skip(1) { + shadow_coefficients_sum.add(shadow_coefficient)?; + } + math::public_mul_secret(&mut common_shadow_point, &shadow_coefficients_sum)?; + math::public_add(&mut decrypted_shadow, &common_shadow_point)?; + Ok(decrypted_shadow) +} + #[cfg(test)] /// Decrypt data using joint secret (version for tests). pub fn decrypt_with_joint_secret(encrypted_point: &Public, common_point: &Public, joint_secret: &Secret) -> Result { @@ -287,7 +321,10 @@ pub mod tests { .filter(|&(j, _)| j != i) .take(t) .map(|(_, id_number)| id_number)).unwrap()).collect(); - let nodes_shadow_points: Vec<_> = nodes_shadows.iter().map(|s| compute_node_shadow_point(&access_key, &encrypted_secret.common_point, s).unwrap()).collect(); + let nodes_shadow_points: Vec<_> = nodes_shadows.iter() + .map(|s| compute_node_shadow_point(&access_key, &encrypted_secret.common_point, s, None).unwrap()) + .map(|sp| sp.0) + .collect(); assert_eq!(nodes_shadows.len(), t + 1); assert_eq!(nodes_shadow_points.len(), t + 1); diff --git a/secret_store/src/key_server_cluster/message.rs b/secret_store/src/key_server_cluster/message.rs index 9958884a4..d817c88a4 100644 --- a/secret_store/src/key_server_cluster/message.rs +++ b/secret_store/src/key_server_cluster/message.rs @@ -218,6 +218,9 @@ pub struct InitializeDecryptionSession { pub sub_session: SerializableSecret, /// Requestor signature. pub requestor_signature: SerializableSignature, + /// Is shadow decryption requested? When true, decryption result + /// will be visible to the owner of requestor public key only. + pub is_shadow_decryption: bool, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -251,6 +254,8 @@ pub struct PartialDecryption { pub sub_session: SerializableSecret, /// Partially decrypted secret. pub shadow_point: SerializablePublic, + /// Decrypt shadow coefficient (if requested), encrypted with requestor public. + pub decrypt_shadow: Option>, } #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/secret_store/src/key_server_cluster/mod.rs b/secret_store/src/key_server_cluster/mod.rs index e889ef322..5c7bc0d2f 100644 --- a/secret_store/src/key_server_cluster/mod.rs +++ b/secret_store/src/key_server_cluster/mod.rs @@ -20,7 +20,7 @@ use ethkey; use ethcrypto; use super::types::all::DocumentAddress; -pub use super::types::all::{NodeId, EncryptionConfiguration}; +pub use super::types::all::{NodeId, EncryptionConfiguration, DocumentEncryptedKeyShadow}; pub use super::acl_storage::AclStorage; pub use super::key_storage::{KeyStorage, DocumentKeyShare}; pub use super::serialization::{SerializableSignature, SerializableH256, SerializableSecret, SerializablePublic}; diff --git a/secret_store/src/key_server_cluster/net/connection.rs b/secret_store/src/key_server_cluster/net/connection.rs index 8125b81d3..577f5828f 100644 --- a/secret_store/src/key_server_cluster/net/connection.rs +++ b/secret_store/src/key_server_cluster/net/connection.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::net; -use ethkey::Secret; +use ethkey::KeyPair; use key_server_cluster::NodeId; use key_server_cluster::io::SharedTcpStream; @@ -28,5 +28,5 @@ pub struct Connection { /// Peer node id. pub node_id: NodeId, /// Encryption key. - pub key: Secret, + pub key: KeyPair, } diff --git a/secret_store/src/key_storage.rs b/secret_store/src/key_storage.rs index e3106f221..ac5e3bf8f 100644 --- a/secret_store/src/key_storage.rs +++ b/secret_store/src/key_storage.rs @@ -43,6 +43,8 @@ pub trait KeyStorage: Send + Sync { fn insert(&self, document: DocumentAddress, key: DocumentKeyShare) -> Result<(), Error>; /// Get document encryption key fn get(&self, document: &DocumentAddress) -> Result; + /// Check if storage contains document encryption key + fn contains(&self, document: &DocumentAddress) -> bool; } /// Persistent document encryption keys storage @@ -95,6 +97,12 @@ impl KeyStorage for PersistentKeyStorage { .and_then(|key| serde_json::from_slice::(&key).map_err(|e| Error::Database(e.to_string()))) .map(Into::into) } + + fn contains(&self, document: &DocumentAddress) -> bool { + self.db.get(None, document) + .map(|k| k.is_some()) + .unwrap_or(false) + } } impl From for SerializableDocumentKeyShare { @@ -146,6 +154,10 @@ pub mod tests { fn get(&self, document: &DocumentAddress) -> Result { self.keys.read().get(document).cloned().ok_or(Error::DocumentNotFound) } + + fn contains(&self, document: &DocumentAddress) -> bool { + self.keys.read().contains_key(document) + } } #[test] diff --git a/secret_store/src/lib.rs b/secret_store/src/lib.rs index 7de957991..cd6116848 100644 --- a/secret_store/src/lib.rs +++ b/secret_store/src/lib.rs @@ -27,6 +27,7 @@ extern crate serde; extern crate serde_json; #[macro_use] extern crate serde_derive; +extern crate tokio_io; extern crate tokio_core; extern crate tokio_service; extern crate tokio_proto; diff --git a/secret_store/src/serialization.rs b/secret_store/src/serialization.rs index 0d0e904a7..e918348fb 100644 --- a/secret_store/src/serialization.rs +++ b/secret_store/src/serialization.rs @@ -17,11 +17,62 @@ use std::fmt; use std::cmp::{Ord, PartialOrd, Ordering}; use std::ops::Deref; -use rustc_serialize::hex::ToHex; +use rustc_serialize::hex::{ToHex, FromHex}; use serde::{Serialize, Deserialize, Serializer, Deserializer}; use serde::de::{Visitor, Error as SerdeError}; use ethkey::{Public, Secret, Signature}; -use util::H256; +use util::{H256, Bytes}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +/// Serializable shadow decryption result. +pub struct SerializableDocumentEncryptedKeyShadow { + /// Decrypted secret point. It is partially decrypted if shadow decrpytion was requested. + pub decrypted_secret: SerializablePublic, + /// Shared common point. + pub common_point: SerializablePublic, + /// If shadow decryption was requested: shadow decryption coefficients, encrypted with requestor public. + pub decrypt_shadows: Vec, +} + +#[derive(Clone, Debug)] +/// Serializable Bytes. +pub struct SerializableBytes(Bytes); + +impl From for SerializableBytes where Bytes: From { + fn from(s: T) -> SerializableBytes { + SerializableBytes(s.into()) + } +} + +impl Into for SerializableBytes { + fn into(self) -> Bytes { + self.0 + } +} + +impl Deref for SerializableBytes { + type Target = Bytes; + + fn deref(&self) -> &Bytes { + &self.0 + } +} + +impl Serialize for SerializableBytes { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&(*self.0).to_hex()) + } +} + +impl Deserialize for SerializableBytes { + fn deserialize(deserializer: D) -> Result + where D: Deserializer + { + let s = String::deserialize(deserializer)?; + let data = s.from_hex().map_err(SerdeError::custom)?; + Ok(SerializableBytes(data)) + } +} #[derive(Clone, Debug)] /// Serializable Signature. diff --git a/secret_store/src/traits.rs b/secret_store/src/traits.rs index 1a407e5c7..86d41be87 100644 --- a/secret_store/src/traits.rs +++ b/secret_store/src/traits.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use types::all::{Error, RequestSignature, DocumentAddress, DocumentEncryptedKey}; +use types::all::{Error, RequestSignature, DocumentAddress, DocumentEncryptedKey, DocumentEncryptedKeyShadow}; #[ipc(client_ident="RemoteKeyServer")] /// Secret store key server @@ -23,4 +23,12 @@ pub trait KeyServer: Send + Sync { fn generate_document_key(&self, signature: &RequestSignature, document: &DocumentAddress, threshold: usize) -> Result; /// Request encryption key of given document for given requestor fn document_key(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result; + /// Request encryption key of given document for given requestor. + /// This method does not reveal document_key to any KeyServer, but it requires additional actions on client. + /// To calculate decrypted key on client: + /// 1) use requestor secret key to decrypt secret coefficients from result.decrypt_shadows + /// 2) calculate decrypt_shadows_sum = sum of all secrets from (1) + /// 3) calculate decrypt_shadow_point: decrypt_shadows_sum * result.common_point + /// 4) calculate decrypted_secret: result.decrypted_secret + decrypt_shadow_point + fn document_key_shadow(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result; } diff --git a/secret_store/src/types/all.rs b/secret_store/src/types/all.rs index 23e07e994..746b07c83 100644 --- a/secret_store/src/types/all.rs +++ b/secret_store/src/types/all.rs @@ -50,7 +50,7 @@ pub enum Error { Internal(String), } -#[derive(Debug)] +#[derive(Debug, Clone)] #[binary] /// Secret store configuration pub struct NodeAddress { @@ -99,6 +99,18 @@ pub struct EncryptionConfiguration { pub key_check_timeout_ms: u64, } +#[derive(Clone, Debug, PartialEq)] +#[binary] +/// Shadow decryption result. +pub struct DocumentEncryptedKeyShadow { + /// Decrypted secret point. It is partially decrypted if shadow decrpytion was requested. + pub decrypted_secret: ethkey::Public, + /// Shared common point. + pub common_point: Option, + /// If shadow decryption was requested: shadow decryption coefficients, encrypted with requestor public. + pub decrypt_shadows: Option>>, +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self {