Fixing secretstore TODOs - part 1 (#5386)

* ECDKG protocol prototype

* added test for enc/dec math

* get rid of decryption_session

* added licenses

* fix after merge

* get rid of unused serde dependency

* doc

* decryption session [without commutative enc]

* failed_dec_session

* fixed tests

* added commen

* added more decryption session tests

* helper to localize an issue

* more computations to localize error

* decryption_session::SessionParams

* added tests for EC math to localize problem

* secretstore network transport

* encryption_session_works_over_network

* network errors processing

* connecting to KeyServer

* licenses

* get rid of debug println-s

* fixed secretstore args

* encryption results are stored in KS database

* decryption protocol works over network

* enc/dec Session traits

* fixing warnings

* fix after merge

* on-chain ACL checker proto

* fixed compilation

* fixed compilation

* finally fixed <odd>-of-N-scheme

* temporary commented test

* 1-of-N works in math

* scheme 1-of-N works

* updated AclStorage with real contract ABI

* remove unnecessary unsafety

* fixed grumbles

* wakeup on access denied

* encrypt secretstore messages

* 'shadow' decryption

* fix grumbles

* lost files

* secretstore cli-options

* decryption seccion when ACL check failed on master

* disallow regenerating key for existing document

* removed obsolete TODO

* fix after merge

* switched to tokio_io

* fix after merge

* fix after merge

* fix after merge

* fix after merge

* fix after merge

* fixed test

* fix after merge
This commit is contained in:
Svyatoslav Nikolsky 2017-04-08 12:26:16 +03:00 committed by Gav Wood
parent d0e057cabd
commit 93a6047912
33 changed files with 1095 additions and 668 deletions

168
Cargo.lock generated
View File

@ -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)" = "<none>"
"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)" = "<none>"
"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)" = "<none>"
"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)" = "<none>"
"checksum nanomsg-sys 0.5.0 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "<none>"
"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)" = "<none>"
"checksum tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)" = "<none>"

View File

@ -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<T>(private_key: H256, chain_code: H256, index: Derivation<T>) -> (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<T>(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<T>(public_key: H512, chain_code: H256, derivation: Derivation<T>) -> 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)

View File

@ -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,

View File

@ -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<key::PublicKey, Error> {
let public_data = {
let mut temp = [4u8; 65];

View File

@ -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()?;

View File

@ -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]

View File

@ -38,7 +38,8 @@ user = "username"
pass = "password"
[secretstore]
port = 8082
http_port = 8082
port = 8083
[ipfs]
enable = false

View File

@ -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<String> = 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<bool>,
port: Option<u16>,
self_secret: Option<String>,
nodes: Option<Vec<String>>,
interface: Option<String>,
port: Option<u16>,
http_interface: Option<String>,
http_port: Option<u16>,
path: Option<String>,
}
@ -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 {

View File

@ -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:<IP> (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:<IP> (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.

View File

@ -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<SecretStoreConfiguration, String> {
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<Option<Secret>, 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<BTreeMap<Public, (String, u16)>, 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 {

View File

@ -651,7 +651,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> 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())?;

View File

@ -14,9 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
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<Secret>,
/// Other nodes IDs + addresses.
pub nodes: BTreeMap<Public, (String, u16)>,
/// 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<Self, String> {
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::<String>::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"),
}
}

View File

@ -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"

View File

@ -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<T: KeyServer + 'static> {
@ -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<T> KeyServer for KeyServerHttpListener<T> where T: KeyServer + 'static {
fn document_key(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKey, Error> {
self.handler.key_server.document_key(signature, document)
}
fn document_key_shadow(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKeyShadow, Error> {
self.handler.key_server.document_key_shadow(signature, document)
}
}
impl<T> HttpHandler for KeyServerHttpHandler<T> where T: KeyServer + 'static {
@ -111,6 +119,34 @@ impl<T> HttpHandler for KeyServerHttpHandler<T> 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<String> = 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,
}
}

View File

@ -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<futures::Complete<()>>,
handle: Option<thread::JoinHandle<()>>,
cluster: Option<Arc<ClusterClient>>,
cluster: Arc<ClusterClient>,
}
impl KeyServerImpl {
@ -53,7 +53,6 @@ impl KeyServerImpl {
/// Get cluster client reference.
pub fn cluster(&self) -> Arc<ClusterClient> {
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<DocumentEncryptedKeyShadow, Error> {
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);
}
}

View File

@ -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<Arc<EncryptionSession>, Error>;
/// Start new decryption session.
fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature) -> Result<Arc<DecryptionSession>, Error>;
fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature, is_shadow_decryption: bool) -> Result<Arc<DecryptionSession>, 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<time::Instant>,
}
@ -649,9 +649,14 @@ impl ClusterSessions {
pub fn new_encryption_session(&self, _master: NodeId, session_id: SessionId, cluster: Arc<Cluster>) -> Result<Arc<EncryptionSessionImpl>, 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<Arc<DecryptionSession>, Error> {
fn new_decryption_session(&self, session_id: SessionId, requestor_signature: Signature, is_shadow_decryption: bool) -> Result<Arc<DecryptionSession>, 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)
}
}

View File

@ -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<Public, Error>;
fn wait(&self) -> Result<DocumentEncryptedKeyShadow, Error>;
}
/// Distributed decryption session.
@ -83,6 +84,15 @@ pub struct SessionParams {
pub cluster: Arc<Cluster>,
}
#[derive(Debug)]
/// Partial decryption result.
struct PartialDecryptionResult {
/// Shadow point.
pub shadow_point: Public,
/// Decryption shadow coefficient, if requested.
pub decrypt_shadow: Option<Vec<u8>>,
}
#[derive(Debug)]
/// Mutable data of encryption (distributed key generation) session.
struct SessionData {
@ -94,6 +104,8 @@ struct SessionData {
master: Option<NodeId>,
/// Public key of requestor.
requestor: Option<Public>,
/// Is shadow decryption requested?
is_shadow_decryption: Option<bool>,
// === 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<NodeId, Public>,
shadow_points: BTreeMap<NodeId, PartialDecryptionResult>,
/// === Values, filled during final decryption ===
/// Decrypted secret
decrypted_secret: Option<Result<Public, Error>>,
decrypted_secret: Option<Result<DocumentEncryptedKeyShadow, Error>>,
}
#[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<Public> {
pub fn decrypted_secret(&self) -> Option<DocumentEncryptedKeyShadow> {
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<Public, Error> {
fn wait(&self) -> Result<DocumentEncryptedKeyShadow, Error> {
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<NodeId>, access_key: &Secret, encrypted_data: &DocumentKeyShare) -> Result<Public, Error> {
fn do_partial_decryption(node: &NodeId, requestor_public: &Public, is_shadow_decryption: bool, participants: &BTreeSet<NodeId>, access_key: &Secret, encrypted_data: &DocumentKeyShare) -> Result<PartialDecryptionResult, Error> {
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

View File

@ -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: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: io::Write + io::Read {
pub fn handshake<A>(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> 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: A, self_confirmation_plain: Result<H256, Error>, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: io::Write + io::Read {
pub fn handshake_with_plain_confirmation<A>(a: A, self_confirmation_plain: Result<H256, Error>, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: AsyncWrite + AsyncRead {
let (error, state) = match self_confirmation_plain.clone()
.and_then(|c| Handshake::<A>::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: A, self_confirmation_plain: Resul
}
/// Wait for handshake procedure to be started by another node from the cluster.
pub fn accept_handshake<A>(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> where A: io::Write + io::Read {
pub fn accept_handshake<A>(a: A, self_key_pair: KeyPair, trusted_nodes: BTreeSet<NodeId>) -> Handshake<A> 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<A> {
trusted_nodes: BTreeSet<NodeId>,
other_node_id: Option<NodeId>,
other_confirmation_plain: Option<H256>,
shared_key: Option<Secret>,
shared_key: Option<KeyPair>,
}
/// Active handshake state.
@ -103,7 +104,7 @@ enum HandshakeState<A> {
Finished,
}
impl<A> Handshake<A> where A: io::Read + io::Write {
impl<A> Handshake<A> 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<A> Handshake<A> where A: io::Read + io::Write {
}
}
impl<A> Future for Handshake<A> where A: io::Read + io::Write {
impl<A> Future for Handshake<A> where A: AsyncRead + AsyncWrite {
type Item = (A, Result<HandshakeResult, Error>);
type Error = io::Error;
@ -207,7 +208,9 @@ impl<A> Future for Handshake<A> 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<A> Future for Handshake<A> 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();
}
}

View File

@ -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<SerializedMessage, Error> {
};
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<u8>) -> Result<M
}
/// Encrypt serialized message.
pub fn encrypt_message(_key: &Secret, message: SerializedMessage) -> Result<SerializedMessage, Error> {
Ok(message) // TODO: implement me
pub fn encrypt_message(key: &KeyPair, message: SerializedMessage) -> Result<SerializedMessage, Error> {
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<u8>) -> Result<Vec<u8>, Error> {
Ok(payload) // TODO: implement me
pub fn decrypt_message(key: &KeyPair, payload: Vec<u8>) -> Result<Vec<u8>, Error> {
Ok(decrypt_single_message(key.secret(), &payload)?)
}
/// Compute shared encryption key.
pub fn compute_shared_key(self_secret: &Secret, other_public: &Public) -> Result<Secret, Error> {
Ok(agree(self_secret, other_public)?)
pub fn compute_shared_key(self_secret: &Secret, other_public: &Public) -> Result<KeyPair, Error> {
// 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<MessageHeader, Error> {
})
}
/// Build serialized message from header && payload
fn build_serialized_message(mut header: MessageHeader, payload: Vec<u8>) -> Result<SerializedMessage, Error> {
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<Vec<u8>>,
output_buffer: Vec<u8>,
expected_output_buffer: Vec<u8>,
}
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<usize> {
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(())
}
}

View File

@ -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: A) -> ReadHeader<A> where A: io::Read {
pub fn read_header<A>(a: A) -> ReadHeader<A> where A: AsyncRead {
ReadHeader {
reader: read_exact(a, [0; MESSAGE_HEADER_SIZE]),
}
@ -32,7 +33,7 @@ pub struct ReadHeader<A> {
reader: ReadExact<A, [u8; MESSAGE_HEADER_SIZE]>,
}
impl<A> Future for ReadHeader<A> where A: io::Read {
impl<A> Future for ReadHeader<A> where A: AsyncRead {
type Item = (A, Result<MessageHeader, Error>);
type Error = io::Error;

View File

@ -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: A) -> ReadMessage<A> where A: io::Read {
pub fn read_message<A>(a: A) -> ReadMessage<A> where A: AsyncRead {
ReadMessage {
key: None,
state: ReadMessageState::ReadHeader(read_header(a)),
@ -30,7 +31,7 @@ pub fn read_message<A>(a: A) -> ReadMessage<A> where A: io::Read {
}
/// Create future for read single encrypted message from the stream.
pub fn read_encrypted_message<A>(a: A, key: Secret) -> ReadMessage<A> where A: io::Read {
pub fn read_encrypted_message<A>(a: A, key: KeyPair) -> ReadMessage<A> where A: AsyncRead {
ReadMessage {
key: Some(key),
state: ReadMessageState::ReadHeader(read_header(a)),
@ -45,11 +46,11 @@ enum ReadMessageState<A> {
/// Future for read single message from the stream.
pub struct ReadMessage<A> {
key: Option<Secret>,
key: Option<KeyPair>,
state: ReadMessageState<A>,
}
impl<A> Future for ReadMessage<A> where A: io::Read {
impl<A> Future for ReadMessage<A> where A: AsyncRead {
type Item = (A, Result<Message, Error>);
type Error = io::Error;

View File

@ -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: A, header: MessageHeader) -> ReadPayload<A> where A: io::Read {
pub fn read_payload<A>(a: A, header: MessageHeader) -> ReadPayload<A> 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: A, header: MessageHeader) -> ReadPayload<A> where A: i
}
/// Create future for read single encrypted message payload from the stream.
pub fn read_encrypted_payload<A>(a: A, header: MessageHeader, key: Secret) -> ReadPayload<A> where A: io::Read {
pub fn read_encrypted_payload<A>(a: A, header: MessageHeader, key: KeyPair) -> ReadPayload<A> 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: A, header: MessageHeader, key: Secret) -> Re
pub struct ReadPayload<A> {
reader: ReadExact<A, Vec<u8>>,
header: MessageHeader,
key: Option<Secret>,
key: Option<KeyPair>,
}
impl<A> Future for ReadPayload<A> where A: io::Read {
impl<A> Future for ReadPayload<A> where A: AsyncRead {
type Item = (A, Result<Message, Error>);
type Error = io::Error;

View File

@ -15,7 +15,10 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
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<TcpStream>.
@ -37,6 +40,14 @@ impl From<TcpStream> 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<usize, Error> {
Read::read(&mut (&*self.io as &TcpStream), buf)

View File

@ -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: A, message: Message) -> WriteMessage<A> where A: io::Write {
pub fn write_message<A>(a: A, message: Message) -> WriteMessage<A> 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: A, message: Message) -> WriteMessage<A> where A: io::
}
/// Write encrypted message to the channel.
pub fn write_encrypted_message<A>(a: A, key: &Secret, message: Message) -> WriteMessage<A> where A: io::Write {
pub fn write_encrypted_message<A>(a: A, key: &KeyPair, message: Message) -> WriteMessage<A> 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<A> {
future: WriteAll<A, Vec<u8>>,
}
impl<A> Future for WriteMessage<A> where A: io::Write {
impl<A> Future for WriteMessage<A> where A: AsyncWrite {
type Item = (A, Vec<u8>);
type Error = io::Error;

View File

@ -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<Public, Error> {
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<Secret>) -> Result<(Public, Option<Secret>), 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<Public, Error> {
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<Secret>) -> Result<Public, Error> {
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<Public, Error> {
@ -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);

View File

@ -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<Vec<u8>>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]

View File

@ -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};

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
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,
}

View File

@ -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<DocumentKeyShare, Error>;
/// 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::<SerializableDocumentKeyShare>(&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<DocumentKeyShare> for SerializableDocumentKeyShare {
@ -146,6 +154,10 @@ pub mod tests {
fn get(&self, document: &DocumentAddress) -> Result<DocumentKeyShare, Error> {
self.keys.read().get(document).cloned().ok_or(Error::DocumentNotFound)
}
fn contains(&self, document: &DocumentAddress) -> bool {
self.keys.read().contains_key(document)
}
}
#[test]

View File

@ -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;

View File

@ -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<SerializableBytes>,
}
#[derive(Clone, Debug)]
/// Serializable Bytes.
pub struct SerializableBytes(Bytes);
impl<T> From<T> for SerializableBytes where Bytes: From<T> {
fn from(s: T) -> SerializableBytes {
SerializableBytes(s.into())
}
}
impl Into<Bytes> 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
serializer.serialize_str(&(*self.0).to_hex())
}
}
impl Deserialize for SerializableBytes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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.

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
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<DocumentEncryptedKey, Error>;
/// Request encryption key of given document for given requestor
fn document_key(&self, signature: &RequestSignature, document: &DocumentAddress) -> Result<DocumentEncryptedKey, Error>;
/// 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<DocumentEncryptedKeyShadow, Error>;
}

View File

@ -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<ethkey::Public>,
/// If shadow decryption was requested: shadow decryption coefficients, encrypted with requestor public.
pub decrypt_shadows: Option<Vec<Vec<u8>>>,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {