Merge branch 'master' into secretstore_kovan

This commit is contained in:
Svyatoslav Nikolsky 2017-12-06 19:56:54 +03:00
commit 5d792324e6
74 changed files with 3733 additions and 1496 deletions

122
Cargo.lock generated
View File

@ -398,6 +398,11 @@ name = "dtoa"
version = "0.4.2" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "edit-distance"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "either" name = "either"
version = "1.1.0" version = "1.1.0"
@ -488,8 +493,8 @@ dependencies = [
"ethcore-stratum 1.9.0", "ethcore-stratum 1.9.0",
"ethcore-util 1.9.0", "ethcore-util 1.9.0",
"ethjson 0.1.0", "ethjson 0.1.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"ethstore 0.1.0", "ethstore 0.2.0",
"evm 0.1.0", "evm 0.1.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"hardware-wallet 1.9.0", "hardware-wallet 1.9.0",
@ -512,7 +517,7 @@ dependencies = [
"migration 0.1.0", "migration 0.1.0",
"native-contracts 0.1.0", "native-contracts 0.1.0",
"num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-machine 0.1.0", "parity-machine 0.1.0",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.1.0", "patricia-trie 0.1.0",
@ -524,7 +529,7 @@ dependencies = [
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semantic_version 0.1.0", "semantic_version 0.1.0",
"snappy 0.1.0", "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)",
"stats 0.1.0", "stats 0.1.0",
"table 0.1.0", "table 0.1.0",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
@ -643,9 +648,8 @@ dependencies = [
"ethcore-devtools 1.9.0", "ethcore-devtools 1.9.0",
"ethcore-io 1.9.0", "ethcore-io 1.9.0",
"ethcore-logger 1.9.0", "ethcore-logger 1.9.0",
"ethcore-util 1.9.0",
"ethcrypto 0.1.0", "ethcrypto 0.1.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0", "keccak-hash 0.1.0",
@ -660,7 +664,7 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"snappy 0.1.0", "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -677,7 +681,7 @@ dependencies = [
"ethcore-logger 1.9.0", "ethcore-logger 1.9.0",
"ethcore-util 1.9.0", "ethcore-util 1.9.0",
"ethcrypto 0.1.0", "ethcrypto 0.1.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"ethsync 1.9.0", "ethsync 1.9.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -742,7 +746,6 @@ dependencies = [
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.1.0", "patricia-trie 0.1.0",
"rlp 0.2.1", "rlp 0.2.1",
"rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -758,7 +761,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)",
"ethcore-bigint 0.2.1", "ethcore-bigint 0.2.1",
"ethkey 0.2.0", "ethkey 0.3.0",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"subtle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -778,12 +781,15 @@ dependencies = [
[[package]] [[package]]
name = "ethkey" name = "ethkey"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)",
"ethcore-bigint 0.2.1", "ethcore-bigint 0.2.1",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -795,24 +801,27 @@ name = "ethkey-cli"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethkey 0.2.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethkey 0.3.0",
"panic_hook 0.1.0", "panic_hook 0.1.0",
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "ethstore" name = "ethstore"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"ethcore-bigint 0.2.1", "ethcore-bigint 0.2.1",
"ethcrypto 0.1.0", "ethcrypto 0.1.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wordlist 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
@ -831,8 +840,10 @@ name = "ethstore-cli"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethstore 0.1.0", "ethstore 0.2.0",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"panic_hook 0.1.0", "panic_hook 0.1.0",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
@ -851,7 +862,7 @@ dependencies = [
"ethcore-light 1.9.0", "ethcore-light 1.9.0",
"ethcore-network 1.9.0", "ethcore-network 1.9.0",
"ethcore-util 1.9.0", "ethcore-util 1.9.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0", "keccak-hash 0.1.0",
@ -971,7 +982,7 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1014,7 +1025,7 @@ name = "hardware-wallet"
version = "1.9.0" version = "1.9.0"
dependencies = [ dependencies = [
"ethcore-bigint 0.2.1", "ethcore-bigint 0.2.1",
"ethkey 0.2.0", "ethkey 0.3.0",
"hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)", "hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)",
"libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)", "libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1096,7 +1107,7 @@ dependencies = [
"language-tags 0.2.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.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1818,7 +1829,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.6.2" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1921,7 +1932,7 @@ dependencies = [
"ethcore-secretstore 1.0.0", "ethcore-secretstore 1.0.0",
"ethcore-stratum 1.9.0", "ethcore-stratum 1.9.0",
"ethcore-util 1.9.0", "ethcore-util 1.9.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"ethsync 1.9.0", "ethsync 1.9.0",
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1937,7 +1948,7 @@ dependencies = [
"migration 0.1.0", "migration 0.1.0",
"node-filter 1.9.0", "node-filter 1.9.0",
"node-health 0.1.0", "node-health 0.1.0",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"panic_hook 0.1.0", "panic_hook 0.1.0",
"parity-dapps 1.9.0", "parity-dapps 1.9.0",
@ -2075,7 +2086,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"ethcore 1.9.0", "ethcore 1.9.0",
"ethcore-io 1.9.0", "ethcore-io 1.9.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"kvdb 0.1.0", "kvdb 0.1.0",
"kvdb-memorydb 0.1.0", "kvdb-memorydb 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2120,8 +2131,8 @@ dependencies = [
"ethcore-util 1.9.0", "ethcore-util 1.9.0",
"ethcrypto 0.1.0", "ethcrypto 0.1.0",
"ethjson 0.1.0", "ethjson 0.1.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"ethstore 0.1.0", "ethstore 0.2.0",
"ethsync 1.9.0", "ethsync 1.9.0",
"fetch 0.1.0", "fetch 0.1.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2223,7 +2234,7 @@ dependencies = [
[[package]] [[package]]
name = "parity-ui-old-precompiled" name = "parity-ui-old-precompiled"
version = "1.9.0" version = "1.9.0"
source = "git+https://github.com/js-dist-paritytech/parity-master-1-9-v1.git#78f0af2479807e209d72e25e9826c8b31285eba1" source = "git+https://github.com/js-dist-paritytech/parity-master-1-9-v1.git#3c4b36c8f9b182242c1355289dc448eac95c19c5"
dependencies = [ dependencies = [
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2231,7 +2242,7 @@ dependencies = [
[[package]] [[package]]
name = "parity-ui-precompiled" name = "parity-ui-precompiled"
version = "1.9.0" version = "1.9.0"
source = "git+https://github.com/js-dist-paritytech/parity-master-1-9-shell.git#8de0d074b982b04adff50d4814c063225fbb2809" source = "git+https://github.com/js-dist-paritytech/parity-master-1-9-shell.git#6dad0d219f9ad72f948f5f4138df3d6cf987b655"
dependencies = [ dependencies = [
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2275,7 +2286,7 @@ dependencies = [
"ethcore-bigint 0.2.1", "ethcore-bigint 0.2.1",
"ethcore-network 1.9.0", "ethcore-network 1.9.0",
"ethcrypto 0.1.0", "ethcrypto 0.1.0",
"ethkey 0.2.0", "ethkey 0.3.0",
"hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)", "jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)", "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.9)",
@ -2297,7 +2308,7 @@ dependencies = [
[[package]] [[package]]
name = "parity-wordlist" name = "parity-wordlist"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2478,6 +2489,22 @@ dependencies = [
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "pwasm-run-test"
version = "0.1.0"
dependencies = [
"clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1",
"ethcore-logger 1.9.0",
"ethjson 0.1.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
"wasm 0.1.0",
]
[[package]] [[package]]
name = "quasi" name = "quasi"
version = "0.32.0" version = "0.32.0"
@ -2555,7 +2582,7 @@ dependencies = [
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2642,7 +2669,7 @@ dependencies = [
[[package]] [[package]]
name = "rocksdb" name = "rocksdb"
version = "0.4.5" version = "0.4.5"
source = "git+https://github.com/paritytech/rust-rocksdb#4364caec4dd5da1a1d78c39276774ee65bf55c7d" source = "git+https://github.com/paritytech/rust-rocksdb#8c4ad5411c141abc63d562d411053f7ebc1aa00c"
dependencies = [ dependencies = [
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2652,10 +2679,11 @@ dependencies = [
[[package]] [[package]]
name = "rocksdb-sys" name = "rocksdb-sys"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/paritytech/rust-rocksdb#4364caec4dd5da1a1d78c39276774ee65bf55c7d" source = "git+https://github.com/paritytech/rust-rocksdb#8c4ad5411c141abc63d562d411053f7ebc1aa00c"
dependencies = [ dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)",
] ]
[[package]] [[package]]
@ -2942,9 +2970,19 @@ dependencies = [
[[package]] [[package]]
name = "snappy" name = "snappy"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/paritytech/rust-snappy#858eac97192ea25d18d3f3626a8cc13ca0b175bb"
dependencies = [ dependencies = [
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)", "snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)",
]
[[package]]
name = "snappy-sys"
version = "0.1.0"
source = "git+https://github.com/paritytech/rust-snappy#858eac97192ea25d18d3f3626a8cc13ca0b175bb"
dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -3096,6 +3134,14 @@ dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "threadpool"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.38" version = "0.1.38"
@ -3556,6 +3602,7 @@ dependencies = [
"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8"
"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a" "checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a34f5204fbc13582de418611cf3a7dcdd07c6d312a5b631597ba72c06b9d9c9"
"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85" "checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85"
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
@ -3641,7 +3688,7 @@ dependencies = [
"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
"checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790" "checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790"
"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" "checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
"checksum number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "59a14be9c211cb9c602bad35ac99f41e9a84b44d71b8cbd3040e3bd02a214902" "checksum number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "59a14be9c211cb9c602bad35ac99f41e9a84b44d71b8cbd3040e3bd02a214902"
"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba"
"checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c"
@ -3655,7 +3702,7 @@ dependencies = [
"checksum parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-9-v1.git)" = "<none>" "checksum parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-9-v1.git)" = "<none>"
"checksum parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-9-shell.git)" = "<none>" "checksum parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-9-shell.git)" = "<none>"
"checksum parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8431a184ad88cfbcd71a792aaca319cc7203a94300c26b8dce2d0df0681ea87d" "checksum parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8431a184ad88cfbcd71a792aaca319cc7203a94300c26b8dce2d0df0681ea87d"
"checksum parity-wordlist 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81451bfab101d186f8fc4a0aa13cb5539b31b02c4ed96425a0842e2a413daba6" "checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693"
"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e"
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595" "checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"
"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
@ -3726,6 +3773,8 @@ dependencies = [
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
"checksum smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fcd03faf178110ab0334d74ca9631d77f94c8c11cc77fcb59538abf0025695d" "checksum smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fcd03faf178110ab0334d74ca9631d77f94c8c11cc77fcb59538abf0025695d"
"checksum snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "<none>"
"checksum snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "<none>"
"checksum spmc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cd1f11d1fb5fd41834e55ce0b85a186efbf2f2afd9fdb09e2c8d72f9bff1ad1a" "checksum spmc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cd1f11d1fb5fd41834e55ce0b85a186efbf2f2afd9fdb09e2c8d72f9bff1ad1a"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
@ -3743,6 +3792,7 @@ dependencies = [
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
"checksum textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8e08afc40ae3459e4838f303e465aa50d823df8d7f83ca88108f6d3afe7edd" "checksum textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8e08afc40ae3459e4838f303e465aa50d823df8d7f83ca88108f6d3afe7edd"
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" "checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
"checksum tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52d12ad79e4063e0cb0ca5efa202ed7244b6ce4d25f4d3abe410b2a66128292" "checksum tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52d12ad79e4063e0cb0ca5efa202ed7244b6ce4d25f4d3abe410b2a66128292"
"checksum tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e85d419699ec4b71bfe35bbc25bb8771e52eff0471a7f75c853ad06e200b4f86" "checksum tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e85d419699ec4b71bfe35bbc25bb8771e52eff0471a7f75c853ad06e200b4f86"

View File

@ -116,4 +116,4 @@ lto = false
panic = "abort" panic = "abort"
[workspace] [workspace]
members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper", "chainspec", "dapps/js-glue"] members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper", "chainspec", "dapps/js-glue", "ethcore/wasm/run"]

View File

@ -54,7 +54,7 @@ kvdb = { path = "../util/kvdb" }
kvdb-rocksdb = { path = "../util/kvdb-rocksdb" } kvdb-rocksdb = { path = "../util/kvdb-rocksdb" }
kvdb-memorydb = { path = "../util/kvdb-memorydb" } kvdb-memorydb = { path = "../util/kvdb-memorydb" }
util-error = { path = "../util/error" } util-error = { path = "../util/error" }
snappy = { path = "../util/snappy" } snappy = { git = "https://github.com/paritytech/rust-snappy" }
migration = { path = "../util/migration" } migration = { path = "../util/migration" }
macros = { path = "../util/macros" } macros = { path = "../util/macros" }
rust-crypto = "0.2.34" rust-crypto = "0.2.34"

@ -1 +1 @@
Subproject commit e5fcae4e9c2a570f293a22baa4d78d9f4b391a0f Subproject commit d6185ea16eaba7ff685c069c2064819f9549c4d7

View File

@ -1231,12 +1231,12 @@ impl BlockChainClient for Client {
} }
fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result<U256, CallError> { fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result<U256, CallError> {
const UPPER_CEILING: u64 = 1_000_000_000_000u64; let (mut upper, max_upper, env_info) = {
let (mut upper, env_info) = {
let mut env_info = self.env_info(block).ok_or(CallError::StatePruned)?; let mut env_info = self.env_info(block).ok_or(CallError::StatePruned)?;
let initial_upper = env_info.gas_limit; let init = env_info.gas_limit;
env_info.gas_limit = UPPER_CEILING.into(); let max = init * U256::from(10);
(initial_upper, env_info) env_info.gas_limit = max;
(init, max, env_info)
}; };
// that's just a copy of the state. // that's just a copy of the state.
@ -1257,9 +1257,7 @@ impl BlockChainClient for Client {
}; };
if !cond(upper)? { if !cond(upper)? {
// impossible at block gas limit - try `UPPER_CEILING` instead. upper = max_upper;
// TODO: consider raising limit by powers of two.
upper = UPPER_CEILING.into();
if !cond(upper)? { if !cond(upper)? {
trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); trace!(target: "estimate_gas", "estimate_gas failed with {}", upper);
let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper)); let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper));

View File

@ -449,9 +449,12 @@ fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u6
} else { } else {
block_number / era_rounds block_number / era_rounds
}; };
let mut divi = U256::from(1);
for _ in 0..eras { for _ in 0..eras {
reward = reward / U256::from(5) * U256::from(4); reward = reward * U256::from(4);
divi = divi * U256::from(5);
} }
reward = reward / divi;
(eras, reward) (eras, reward)
} }
@ -517,6 +520,11 @@ mod tests {
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
assert_eq!(15, eras); assert_eq!(15, eras);
assert_eq!(U256::from_str("271000000000000").unwrap(), reward); assert_eq!(U256::from_str("271000000000000").unwrap(), reward);
let block_number = 250000000;
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
assert_eq!(49, eras);
assert_eq!(U256::from_str("51212FFBAF0A").unwrap(), reward);
} }
#[test] #[test]

View File

@ -0,0 +1,19 @@
[package]
name = "pwasm-run-test"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
serde = "1"
serde_json = "1"
serde_derive = "1"
ethcore-bigint = { path = "../../../util/bigint" }
ethjson = { path = "../../../json" }
vm = { path = "../../vm" }
wasm = { path = "../" }
clap = "2.24"
ethcore-logger = { path = "../../../logger" }
rustc-hex = "1"
[features]
default = ["ethcore-bigint/std"]

View File

@ -0,0 +1,45 @@
[
{
"caption": "Sample test",
"source": "./res/sample1.wasm",
"address": "0x1000000000000000000000000000000000000001",
"sender": "0x1000000000000000000000000000000000000002",
"value": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": 100000,
"payload": "0x",
"asserts": [
{ "Return": "0x01" },
{ "UsedGas": 17 },
{ "HasCall": { "codeAddress": "0x1000000000000000000000000000000000000002" }},
{ "HasStorage":
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000001",
"value": "0x0000000000000000000000000000000000000000000000000000000000000002"
}
}
]
},
{
"caption": "Keccak test",
"source": "./res/sample2.wasm",
"payload": "0x736f6d657468696e67",
"gasLimit": 100000,
"asserts": [
{ "Return": "0x68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87" }
]
},
{
"caption": "Token total supply",
"source": {
"constructor": "./res/sample3.wasm",
"sender": "0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f",
"at": "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"arguments": "0x0000000000000000000000000000000000000000000000000000000010000000"
},
"payload": "0x18160ddd",
"gasLimit": 100000,
"asserts": [
{ "Return": "0x0000000000000000000000000000000000000000000000000000000010000000" }
]
}
]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,70 @@
use std::borrow::Cow;
use ethjson::uint::Uint;
use ethjson::hash::{Address, H256};
use ethjson::bytes::Bytes;
#[derive(Deserialize)]
#[serde(untagged)]
pub enum Source {
Raw(Cow<'static, String>),
Constructor {
#[serde(rename="constructor")]
source: Cow<'static, String>,
arguments: Bytes,
sender: Address,
at: Address,
},
}
impl Source {
pub fn as_ref(&self) -> &str {
match *self {
Source::Raw(ref r) => r.as_ref(),
Source::Constructor { ref source, .. } => source.as_ref(),
}
}
}
#[derive(Deserialize)]
pub struct Fixture {
pub caption: Cow<'static, String>,
pub source: Source,
pub address: Option<Address>,
pub sender: Option<Address>,
pub value: Option<Uint>,
#[serde(rename="gasLimit")]
pub gas_limit: Option<u64>,
pub payload: Option<Bytes>,
pub storage: Option<Vec<StorageEntry>>,
pub asserts: Vec<Assert>,
}
#[derive(Deserialize, Debug)]
pub struct StorageEntry {
pub key: Uint,
pub value: Uint,
}
#[derive(Deserialize, Debug, Clone)]
pub struct CallLocator {
pub sender: Option<Address>,
pub receiver: Option<Address>,
pub value: Option<Uint>,
pub data: Option<Bytes>,
#[serde(rename="codeAddress")]
pub code_address: Option<Address>,
}
#[derive(Deserialize, Debug)]
pub struct StorageAssert {
pub key: H256,
pub value: H256,
}
#[derive(Deserialize, Debug)]
pub enum Assert {
HasCall(CallLocator),
HasStorage(StorageAssert),
UsedGas(u64),
Return(Bytes),
}

View File

@ -0,0 +1,46 @@
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
extern crate ethcore_bigint;
extern crate ethjson;
extern crate wasm;
extern crate vm;
extern crate clap;
extern crate ethcore_logger;
extern crate rustc_hex;
mod fixture;
mod runner;
use fixture::Fixture;
use clap::{App, Arg};
use std::fs;
fn main() {
::ethcore_logger::init_log();
let matches = App::new("pwasm-run-test")
.arg(Arg::with_name("target")
.index(1)
.required(true)
.multiple(true)
.help("JSON fixture"))
.get_matches();
let mut exit_code = 0;
for target in matches.values_of("target").expect("No target parameter") {
let mut f = fs::File::open(target).expect("Failed to open file");
let fixtures: Vec<Fixture> = serde_json::from_reader(&mut f).expect("Failed to deserialize json");
for fixture in fixtures.into_iter() {
let fails = runner::run_fixture(&fixture);
for fail in fails.iter() {
exit_code = 1;
println!("Failed assert in test \"{}\" ('{}'): {}", fixture.caption.as_ref(), target, fail);
}
}
}
std::process::exit(exit_code);
}

View File

@ -0,0 +1,261 @@
use fixture::{Fixture, Assert, CallLocator, Source};
use wasm::WasmInterpreter;
use vm::{self, Vm, GasLeft, ActionParams, ActionValue, ParamsType};
use vm::tests::FakeExt;
use std::io::{self, Read};
use std::{fs, path, fmt};
use std::sync::Arc;
use ethcore_bigint::prelude::{U256, H256, H160};
use rustc_hex::ToHex;
fn load_code<P: AsRef<path::Path>>(p: P) -> io::Result<Vec<u8>> {
let mut result = Vec::new();
let mut f = fs::File::open(p)?;
f.read_to_end(&mut result)?;
Ok(result)
}
fn wasm_interpreter() -> WasmInterpreter {
WasmInterpreter::new().expect("wasm interpreter to create without errors")
}
#[derive(Debug)]
pub enum SpecNonconformity {
Address,
}
#[derive(Debug)]
pub enum Fail {
Return { expected: Vec<u8>, actual: Vec<u8> },
UsedGas { expected: u64, actual: u64 },
Runtime(String),
Load(io::Error),
NoCall(CallLocator),
StorageMismatch { key: H256, expected: H256, actual: Option<H256> },
Nonconformity(SpecNonconformity)
}
impl Fail {
fn runtime(err: vm::Error) -> Vec<Fail> {
vec![Fail::Runtime(format!("{}", err))]
}
fn load(err: io::Error) -> Vec<Fail> {
vec![Fail::Load(err)]
}
fn nononformity(kind: SpecNonconformity) -> Vec<Fail> {
vec![Fail::Nonconformity(kind)]
}
}
impl fmt::Display for Fail {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Fail::*;
match *self {
Return { ref expected, ref actual } =>
write!(
f,
"Expected to return result: 0x{} ({} bytes), but got 0x{} ({} bytes)",
expected.to_hex(),
expected.len(),
actual.to_hex(),
actual.len()
),
UsedGas { expected, actual } =>
write!(f, "Expected to use gas: {}, but got actual gas used: {}", expected, actual),
Runtime(ref s) =>
write!(f, "WASM Runtime error: {}", s),
Load(ref e) =>
write!(f, "Load i/o error: {}", e),
NoCall(ref call) =>
write!(f, "Call not found: {:?}", call),
StorageMismatch { ref key, ref expected, actual: Some(ref actual)} =>
write!(
f,
"Storage key {} value mismatch, expected {}, got: {}",
key.as_ref().to_vec().to_hex(),
expected.as_ref().to_vec().to_hex(),
actual.as_ref().to_vec().to_hex(),
),
StorageMismatch { ref key, ref expected, actual: None} =>
write!(
f,
"No expected storage value for key {} found, expected {}",
key.as_ref().to_vec().to_hex(),
expected.as_ref().to_vec().to_hex(),
),
Nonconformity(SpecNonconformity::Address) =>
write!(f, "Cannot use address when constructor is specified!"),
}
}
}
pub fn construct(
ext: &mut vm::Ext,
source: Vec<u8>,
arguments: Vec<u8>,
sender: H160,
at: H160,
) -> Result<Vec<u8>, vm::Error> {
let mut params = ActionParams::default();
params.sender = sender;
params.address = at;
params.gas = U256::from(100_000_000);
params.data = Some(arguments);
params.code = Some(Arc::new(source));
params.params_type = ParamsType::Separate;
Ok(
match wasm_interpreter().exec(params, ext)? {
GasLeft::Known(_) => Vec::new(),
GasLeft::NeedsReturn { data, .. } => data.to_vec(),
}
)
}
pub fn run_fixture(fixture: &Fixture) -> Vec<Fail> {
let mut params = ActionParams::default();
let source = match load_code(fixture.source.as_ref()) {
Ok(code) => code,
Err(e) => { return Fail::load(e); },
};
let mut ext = FakeExt::new();
params.code = Some(Arc::new(
if let Source::Constructor { ref arguments, ref sender, ref at, .. } = fixture.source {
match construct(&mut ext, source, arguments.clone().into(), sender.clone().into(), at.clone().into()) {
Ok(code) => code,
Err(e) => { return Fail::runtime(e); }
}
} else {
source
}
));
if let Some(ref sender) = fixture.sender {
params.sender = sender.clone().into();
}
if let Some(ref address) = fixture.address {
if let Source::Constructor { .. } = fixture.source {
return Fail::nononformity(SpecNonconformity::Address);
}
params.address = address.clone().into();
} else if let Source::Constructor { ref at, .. } = fixture.source {
params.address = at.clone().into();
}
if let Some(gas_limit) = fixture.gas_limit {
params.gas = U256::from(gas_limit);
}
if let Some(ref data) = fixture.payload {
params.data = Some(data.clone().into())
}
if let Some(value) = fixture.value {
params.value = ActionValue::Transfer(value.clone().into())
}
if let Some(ref storage) = fixture.storage {
for storage_entry in storage.iter() {
let key: U256 = storage_entry.key.into();
let val: U256 = storage_entry.value.into();
ext.store.insert(key.into(), val.into());
}
}
let mut interpreter = wasm_interpreter();
let interpreter_return = match interpreter.exec(params, &mut ext) {
Ok(ret) => ret,
Err(e) => { return Fail::runtime(e); }
};
let (gas_left, result) = match interpreter_return {
GasLeft::Known(gas) => { (gas, Vec::new()) },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
};
let mut fails = Vec::new();
for assert in fixture.asserts.iter() {
match *assert {
Assert::Return(ref data) => {
if &data[..] != &result[..] {
fails.push(Fail::Return { expected: (&data[..]).to_vec(), actual: (&result[..]).to_vec() })
}
},
Assert::UsedGas(gas) => {
let used_gas = fixture.gas_limit.unwrap_or(0) - gas_left.low_u64();
if gas != used_gas {
fails.push(Fail::UsedGas { expected: gas, actual: used_gas });
}
},
Assert::HasCall(ref locator) => {
let mut found = false;
for fake_call in ext.calls.iter() {
let mut match_ = true;
if let Some(ref data) = locator.data {
if data.as_ref() != &fake_call.data[..] { match_ = false; }
}
if let Some(ref code_addr) = locator.code_address {
if fake_call.code_address.unwrap_or(H160::zero()) != code_addr.clone().into() { match_ = false }
}
if let Some(ref sender) = locator.sender {
if fake_call.sender_address.unwrap_or(H160::zero()) != sender.clone().into() { match_ = false }
}
if let Some(ref receiver) = locator.receiver {
if fake_call.receive_address.unwrap_or(H160::zero()) != receiver.clone().into() { match_ = false }
}
if match_ {
found = true;
break;
}
}
if !found {
fails.push(Fail::NoCall(locator.clone()))
}
},
Assert::HasStorage(ref storage_entry) => {
let expected_storage_key: H256 = storage_entry.key.clone().into();
let expected_storage_value: H256 = storage_entry.value.clone().into();
let val = ext.store.get(&expected_storage_key);
if let Some(val) = val {
if val != &expected_storage_value {
fails.push(Fail::StorageMismatch {
key: expected_storage_key,
expected: expected_storage_value,
actual: Some(val.clone())
})
}
} else {
fails.push(Fail::StorageMismatch {
key: expected_storage_key,
expected: expected_storage_value,
actual: None,
})
}
},
}
}
fails
}

View File

@ -115,7 +115,7 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
Static( Static(
"_blockhash", "_blockhash",
&[I64, I32], &[I64, I32],
Some(I32), None,
), ),
Static( Static(
"_coinbase", "_coinbase",

View File

@ -665,7 +665,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
self.memory.set(return_ptr, &*hash)?; self.memory.set(return_ptr, &*hash)?;
Ok(Some(0i32.into())) Ok(None)
} }
fn return_address_ptr(&mut self, ptr: u32, val: Address) -> Result<(), InterpreterError> fn return_address_ptr(&mut self, ptr: u32, val: Address) -> Result<(), InterpreterError>

View File

@ -765,7 +765,7 @@ fn externs() {
"Gas limit requested and returned does not match" "Gas limit requested and returned does not match"
); );
assert_eq!(gas_left, U256::from(94_733)); assert_eq!(gas_left, U256::from(94_858));
} }
#[test] #[test]

View File

@ -1,14 +1,17 @@
[package] [package]
name = "ethkey" name = "ethkey"
version = "0.2.0" version = "0.3.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
rand = "0.3.14"
lazy_static = "0.2"
tiny-keccak = "1.3"
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
rustc-hex = "1.0"
ethcore-bigint = { path = "../util/bigint" }
rust-crypto = "0.2"
byteorder = "1.0" byteorder = "1.0"
edit-distance = "2.0"
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
ethcore-bigint = { path = "../util/bigint" }
lazy_static = "0.2"
log = "0.3"
parity-wordlist = "1.2"
rand = "0.3.14"
rust-crypto = "0.2"
rustc-hex = "1.0"
tiny-keccak = "1.3"

View File

@ -16,13 +16,13 @@ Ethereum keys generator.
Copyright 2016, 2017 Parity Technologies (UK) Ltd Copyright 2016, 2017 Parity Technologies (UK) Ltd
Usage: Usage:
ethkey info <secret> [options] ethkey info <secret-or-phrase> [options]
ethkey generate random [options] ethkey generate random [options]
ethkey generate prefix <prefix> <iterations> [options] ethkey generate prefix <prefix> [options]
ethkey generate brain <seed> [options]
ethkey sign <secret> <message> ethkey sign <secret> <message>
ethkey verify public <public> <signature> <message> ethkey verify public <public> <signature> <message>
ethkey verify address <address> <signature> <message> ethkey verify address <address> <signature> <message>
ethkey recover <address> <known-phrase>
ethkey [-h | --help] ethkey [-h | --help]
Options: Options:
@ -30,15 +30,15 @@ Options:
-s, --secret Display only the secret. -s, --secret Display only the secret.
-p, --public Display only the public. -p, --public Display only the public.
-a, --address Display only the address. -a, --address Display only the address.
-b, --brain Use parity brain wallet algorithm.
Commands: Commands:
info Display public and address of the secret. info Display public and address of the secret.
generate Generates new ethereum key. generate random Generates new random ethereum key.
random Random generation. generate prefix Random generation, but address must start with a prefix.
prefix Random generation, but address must start with a prefix
brain Generate new key from string seed.
sign Sign message using secret. sign Sign message using secret.
verify Verify signer of the signature. verify Verify signer of the signature.
recover Try to find brain phrase matching given address from partial phrase.
``` ```
### Examples ### Examples
@ -60,20 +60,22 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5
-- --
#### `generate brain <seed>`
*Generate new brain-wallet keypair using 16384 iterations.*
- `<seed>` - brain-wallet seed, any string #### `info --brain <phrase>`
*Display info about private key generate from brain wallet recovery phrase.*
- `<phrase>` - Parity recovery phrase, 12 words
``` ```
ethkey generate brain "this is sparta" ethkey info --brain "this is sparta"
``` ```
``` ```
secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 The recover phrase was not generated by Parity: The word 'this' does not come from the dictionary.
public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124
address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5 secret: aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2
public: c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4
address: 006e27b6a72e1f34c626762f3c4761547aff1421
``` ```
-- --
@ -93,14 +95,30 @@ address: a8fa5dd30a87bb9e3288d604eb74949c515ab66e
-- --
#### `generate prefix <prefix> <iterations>` #### `generate random --brain`
*Generate new keypair with recovery phrase randomly.*
```
ethkey generate random --brain
```
```
recovery phrase: thwarting scandal creamer nuzzle asparagus blast crouch trusting anytime elixir frenzied octagon
secret: 001ce488d50d2f7579dc190c4655f32918d505cee3de63bddc7101bc91c0c2f0
public: 4e19a5fdae82596e1485c69b687c9cc52b5078e5b0668ef3ce8543cd90e712cb00df822489bc1f1dcb3623538a54476c7b3def44e1a51dc174e86448b63f42d0
address: 00cf3711cbd3a1512570639280758118ba0b2bcb
```
--
#### `generate prefix <prefix>`
*Generate new keypair randomly with address starting with prefix.* *Generate new keypair randomly with address starting with prefix.*
- `<prefix>` - desired address prefix, 0 - 32 bytes long. - `<prefix>` - desired address prefix, 0 - 32 bytes long.
- `<iterations>` - maximum number of tries before generation is assumed to be a failure.
``` ```
ethkey generate prefix ff 1000 ethkey generate prefix ff
``` ```
``` ```
@ -111,6 +129,24 @@ address: fff7e25dff2aa60f61f9d98130c8646a01f31649
-- --
#### `generate prefix --brain <prefix>`
*Generate new keypair with recovery phrase randomly with address starting with prefix.*
- `<prefix>` - desired address prefix, 0 - 32 bytes long.
```
ethkey generate prefix --brain 00cf
```
```
recovery phrase: thwarting scandal creamer nuzzle asparagus blast crouch trusting anytime elixir frenzied octagon
secret: 001ce488d50d2f7579dc190c4655f32918d505cee3de63bddc7101bc91c0c2f0
public: 4e19a5fdae82596e1485c69b687c9cc52b5078e5b0668ef3ce8543cd90e712cb00df822489bc1f1dcb3623538a54476c7b3def44e1a51dc174e86448b63f42d0
address: 00cf3711cbd3a1512570639280758118ba0b2bcb
```
--
#### `sign <secret> <message>` #### `sign <secret> <message>`
*Sign a message with a secret.* *Sign a message with a secret.*
@ -159,9 +195,32 @@ ethkey verify address 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6
true true
``` ```
--
# Ethcore toolchain #### `recover <address> <known-phrase>`
*this project is a part of the ethcore toolchain* *Try to recover an account given expected address and partial (too short or with invalid words) recovery phrase.*
- `<address>` - ethereum address, 20 bytes long
- `<known-phrase>` - known phrase, can be in a form of `thwarting * creamer`
```
RUST_LOG="info" ethkey recover "00cf3711cbd3a1512570639280758118ba0b2bcb" "thwarting scandal creamer nuzzle asparagus blast crouch trusting anytime elixir frenzied octag"
```
```
INFO:ethkey::brain_recover: Invalid word 'octag', looking for potential substitutions.
INFO:ethkey::brain_recover: Closest words: ["ocean", "octagon", "octane", "outage", "tag", "acting", "acts", "aorta", "cage", "chug"]
INFO:ethkey::brain_recover: Starting to test 7776 possible combinations.
thwarting scandal creamer nuzzle asparagus blast crouch trusting anytime elixir frenzied octagon
secret: 001ce488d50d2f7579dc190c4655f32918d505cee3de63bddc7101bc91c0c2f0
public: 4e19a5fdae82596e1485c69b687c9cc52b5078e5b0668ef3ce8543cd90e712cb00df822489bc1f1dcb3623538a54476c7b3def44e1a51dc174e86448b63f42d0
address: 00cf3711cbd3a1512570639280758118ba0b2bcb
```
# Parity toolchain
*this project is a part of the parity toolchain*
- [**ethkey**](https://github.com/paritytech/ethkey) - Ethereum keys generator and signer. - [**ethkey**](https://github.com/paritytech/ethkey) - Ethereum keys generator and signer.
- [**ethstore**](https://github.com/paritytech/ethstore) - Ethereum key management. - [**ethstore**](https://github.com/paritytech/ethstore) - Ethereum key management.

View File

@ -4,12 +4,15 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
docopt = "0.8"
env_logger = "0.4"
ethkey = { path = "../" } ethkey = { path = "../" }
panic_hook = { path = "../../panic_hook" }
parity-wordlist="1.2"
rustc-hex = "1.0"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
rustc-hex = "1.0" threadpool = "1.7"
docopt = "0.8"
panic_hook = { path = "../../panic_hook" }
[[bin]] [[bin]]
name = "ethkey" name = "ethkey"

View File

@ -15,32 +15,36 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate docopt; extern crate docopt;
extern crate rustc_hex; extern crate env_logger;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate ethkey; extern crate ethkey;
extern crate panic_hook; extern crate panic_hook;
extern crate parity_wordlist;
extern crate rustc_hex;
extern crate serde;
extern crate threadpool;
#[macro_use]
extern crate serde_derive;
use std::{env, fmt, process};
use std::num::ParseIntError; use std::num::ParseIntError;
use std::{env, fmt, process, io, sync};
use docopt::Docopt; use docopt::Docopt;
use ethkey::{KeyPair, Random, Brain, BrainPrefix, Prefix, Error as EthkeyError, Generator, sign, verify_public, verify_address, brain_recover};
use rustc_hex::{ToHex, FromHex, FromHexError}; use rustc_hex::{ToHex, FromHex, FromHexError};
use ethkey::{KeyPair, Random, Brain, Prefix, Error as EthkeyError, Generator, sign, verify_public, verify_address};
use std::io;
pub const USAGE: &'static str = r#" pub const USAGE: &'static str = r#"
Ethereum keys generator. Ethereum keys generator.
Copyright 2016, 2017 Parity Technologies (UK) Ltd Copyright 2016, 2017 Parity Technologies (UK) Ltd
Usage: Usage:
ethkey info <secret> [options] ethkey info <secret-or-phrase> [options]
ethkey generate random [options] ethkey generate random [options]
ethkey generate prefix <prefix> <iterations> [options] ethkey generate prefix <prefix> [options]
ethkey generate brain <seed> [options]
ethkey sign <secret> <message> ethkey sign <secret> <message>
ethkey verify public <public> <signature> <message> ethkey verify public <public> <signature> <message>
ethkey verify address <address> <signature> <message> ethkey verify address <address> <signature> <message>
ethkey recover <address> <known-phrase>
ethkey [-h | --help] ethkey [-h | --help]
Options: Options:
@ -48,15 +52,15 @@ Options:
-s, --secret Display only the secret. -s, --secret Display only the secret.
-p, --public Display only the public. -p, --public Display only the public.
-a, --address Display only the address. -a, --address Display only the address.
-b, --brain Use parity brain wallet algorithm.
Commands: Commands:
info Display public and address of the secret. info Display public and address of the secret.
generate Generates new ethereum key. generate random Generates new random ethereum key.
random Random generation. generate prefix Random generation, but address must start with a prefix.
prefix Random generation, but address must start with a prefix
brain Generate new key from string seed.
sign Sign message using secret. sign Sign message using secret.
verify Verify signer of the signature. verify Verify signer of the signature.
recover Try to find brain phrase matching given address from partial phrase.
"#; "#;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -65,15 +69,15 @@ struct Args {
cmd_generate: bool, cmd_generate: bool,
cmd_random: bool, cmd_random: bool,
cmd_prefix: bool, cmd_prefix: bool,
cmd_brain: bool,
cmd_sign: bool, cmd_sign: bool,
cmd_verify: bool, cmd_verify: bool,
cmd_public: bool, cmd_public: bool,
cmd_address: bool, cmd_address: bool,
cmd_recover: bool,
arg_prefix: String, arg_prefix: String,
arg_iterations: String,
arg_seed: String,
arg_secret: String, arg_secret: String,
arg_secret_or_phrase: String,
arg_known_phrase: String,
arg_message: String, arg_message: String,
arg_public: String, arg_public: String,
arg_address: String, arg_address: String,
@ -81,6 +85,7 @@ struct Args {
flag_secret: bool, flag_secret: bool,
flag_public: bool, flag_public: bool,
flag_address: bool, flag_address: bool,
flag_brain: bool,
} }
#[derive(Debug)] #[derive(Debug)]
@ -157,6 +162,7 @@ impl DisplayMode {
fn main() { fn main() {
panic_hook::set(); panic_hook::set();
env_logger::init().expect("Logger initialized only once.");
match execute(env::args()) { match execute(env::args()) {
Ok(ok) => println!("{}", ok), Ok(ok) => println!("{}", ok),
@ -167,9 +173,13 @@ fn main() {
} }
} }
fn display(keypair: KeyPair, mode: DisplayMode) -> String { fn display(result: (KeyPair, Option<String>), mode: DisplayMode) -> String {
let keypair = result.0;
match mode { match mode {
DisplayMode::KeyPair => format!("{}", keypair), DisplayMode::KeyPair => match result.1 {
Some(extra_data) => format!("{}\n{}", extra_data, keypair),
None => format!("{}", keypair)
},
DisplayMode::Secret => format!("{}", keypair.secret().to_hex()), DisplayMode::Secret => format!("{}", keypair.secret().to_hex()),
DisplayMode::Public => format!("{:?}", keypair.public()), DisplayMode::Public => format!("{:?}", keypair.public()),
DisplayMode::Address => format!("{:?}", keypair.address()), DisplayMode::Address => format!("{:?}", keypair.address()),
@ -182,23 +192,53 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
return if args.cmd_info { return if args.cmd_info {
let display_mode = DisplayMode::new(&args); let display_mode = DisplayMode::new(&args);
let secret = args.arg_secret.parse().map_err(|_| EthkeyError::InvalidSecret)?;
let keypair = KeyPair::from_secret(secret)?; let result = if args.flag_brain {
Ok(display(keypair, display_mode)) let phrase = args.arg_secret_or_phrase;
let phrase_info = validate_phrase(&phrase);
let keypair = Brain::new(phrase).generate().expect("Brain wallet generator is infallible; qed");
(keypair, Some(phrase_info))
} else {
let secret = args.arg_secret_or_phrase.parse().map_err(|_| EthkeyError::InvalidSecret)?;
(KeyPair::from_secret(secret)?, None)
};
Ok(display(result, display_mode))
} else if args.cmd_generate { } else if args.cmd_generate {
let display_mode = DisplayMode::new(&args); let display_mode = DisplayMode::new(&args);
let keypair = if args.cmd_random { let result = if args.cmd_random {
Random.generate()? if args.flag_brain {
let mut brain = BrainPrefix::new(vec![0], usize::max_value(), BRAIN_WORDS);
let keypair = brain.generate()?;
let phrase = format!("recovery phrase: {}", brain.phrase());
(keypair, Some(phrase))
} else {
(Random.generate()?, None)
}
} else if args.cmd_prefix { } else if args.cmd_prefix {
let prefix = args.arg_prefix.from_hex()?; let prefix = args.arg_prefix.from_hex()?;
let iterations = usize::from_str_radix(&args.arg_iterations, 10)?; let brain = args.flag_brain;
Prefix::new(prefix, iterations).generate()? in_threads(move || {
} else if args.cmd_brain { let iterations = 1024;
Brain::new(args.arg_seed).generate().expect("Brain wallet generator is infallible; qed") let prefix = prefix.clone();
move || {
let prefix = prefix.clone();
let res = if brain {
let mut brain = BrainPrefix::new(prefix, iterations, BRAIN_WORDS);
let result = brain.generate();
let phrase = format!("recovery phrase: {}", brain.phrase());
result.map(|keypair| (keypair, Some(phrase)))
} else {
let result = Prefix::new(prefix, iterations).generate();
result.map(|res| (res, None))
};
Ok(res.map(Some).unwrap_or(None))
}
})?
} else { } else {
unreachable!(); return Ok(format!("{}", USAGE))
}; };
Ok(display(keypair, display_mode)) Ok(display(result, display_mode))
} else if args.cmd_sign { } else if args.cmd_sign {
let secret = args.arg_secret.parse().map_err(|_| EthkeyError::InvalidSecret)?; let secret = args.arg_secret.parse().map_err(|_| EthkeyError::InvalidSecret)?;
let message = args.arg_message.parse().map_err(|_| EthkeyError::InvalidMessage)?; let message = args.arg_message.parse().map_err(|_| EthkeyError::InvalidMessage)?;
@ -214,14 +254,89 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
let address = args.arg_address.parse().map_err(|_| EthkeyError::InvalidAddress)?; let address = args.arg_address.parse().map_err(|_| EthkeyError::InvalidAddress)?;
verify_address(&address, &signature, &message)? verify_address(&address, &signature, &message)?
} else { } else {
unreachable!(); return Ok(format!("{}", USAGE))
}; };
Ok(format!("{}", ok)) Ok(format!("{}", ok))
} else if args.cmd_recover {
let display_mode = DisplayMode::new(&args);
let known_phrase = args.arg_known_phrase;
let address = args.arg_address.parse().map_err(|_| EthkeyError::InvalidAddress)?;
let (phrase, keypair) = in_threads(move || {
let mut it = brain_recover::PhrasesIterator::from_known_phrase(&known_phrase, BRAIN_WORDS);
move || {
let mut i = 0;
while let Some(phrase) = it.next() {
i += 1;
let keypair = Brain::new(phrase.clone()).generate().unwrap();
if keypair.address() == address {
return Ok(Some((phrase, keypair)))
}
if i >= 1024 {
return Ok(None)
}
}
Err(EthkeyError::Custom("Couldn't find any results.".into()))
}
})?;
Ok(display((keypair, Some(phrase)), display_mode))
} else { } else {
unreachable!(); Ok(format!("{}", USAGE))
} }
} }
const BRAIN_WORDS: usize = 12;
fn validate_phrase(phrase: &str) -> String {
match Brain::validate_phrase(phrase, BRAIN_WORDS) {
Ok(()) => format!("The recovery phrase looks correct.\n"),
Err(err) => format!("The recover phrase was not generated by Parity: {}", err)
}
}
fn in_threads<F, X, O>(prepare: F) -> Result<O, EthkeyError> where
O: Send + 'static,
X: Send + 'static,
F: Fn() -> X,
X: FnMut() -> Result<Option<O>, EthkeyError>,
{
let pool = threadpool::Builder::new().build();
let (tx, rx) = sync::mpsc::sync_channel(1);
let is_done = sync::Arc::new(sync::atomic::AtomicBool::default());
for _ in 0..pool.max_count() {
let is_done = is_done.clone();
let tx = tx.clone();
let mut task = prepare();
pool.execute(move || {
loop {
if is_done.load(sync::atomic::Ordering::SeqCst) {
return;
}
let res = match task() {
Ok(None) => continue,
Ok(Some(v)) => Ok(v),
Err(err) => Err(err),
};
// We are interested only in the first response.
let _ = tx.send(res);
}
});
}
if let Ok(solution) = rx.recv() {
is_done.store(true, sync::atomic::Ordering::SeqCst);
return solution;
}
Err(EthkeyError::Custom("No results found.".into()))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::execute; use super::execute;
@ -242,13 +357,15 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned();
#[test] #[test]
fn brain() { fn brain() {
let command = vec!["ethkey", "generate", "brain", "this is sparta"] let command = vec!["ethkey", "info", "--brain", "this is sparta"]
.into_iter() .into_iter()
.map(Into::into) .map(Into::into)
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let expected = let expected =
"secret: aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2 "The recover phrase was not generated by Parity: The word 'this' does not come from the dictionary.
secret: aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2
public: c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4 public: c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4
address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned(); address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
assert_eq!(execute(command).unwrap(), expected); assert_eq!(execute(command).unwrap(), expected);
@ -256,7 +373,7 @@ address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
#[test] #[test]
fn secret() { fn secret() {
let command = vec!["ethkey", "generate", "brain", "this is sparta", "--secret"] let command = vec!["ethkey", "info", "--brain", "this is sparta", "--secret"]
.into_iter() .into_iter()
.map(Into::into) .map(Into::into)
.collect::<Vec<String>>(); .collect::<Vec<String>>();
@ -267,7 +384,7 @@ address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
#[test] #[test]
fn public() { fn public() {
let command = vec!["ethkey", "generate", "brain", "this is sparta", "--public"] let command = vec!["ethkey", "info", "--brain", "this is sparta", "--public"]
.into_iter() .into_iter()
.map(Into::into) .map(Into::into)
.collect::<Vec<String>>(); .collect::<Vec<String>>();
@ -278,7 +395,7 @@ address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
#[test] #[test]
fn address() { fn address() {
let command = vec!["ethkey", "generate", "brain", "this is sparta", "--address"] let command = vec!["ethkey", "info", "-b", "this is sparta", "--address"]
.into_iter() .into_iter()
.map(Into::into) .map(Into::into)
.collect::<Vec<String>>(); .collect::<Vec<String>>();

View File

@ -16,6 +16,7 @@
use keccak::Keccak256; use keccak::Keccak256;
use super::{KeyPair, Generator, Secret}; use super::{KeyPair, Generator, Secret};
use parity_wordlist;
/// Simple brainwallet. /// Simple brainwallet.
pub struct Brain(String); pub struct Brain(String);
@ -24,13 +25,17 @@ impl Brain {
pub fn new(s: String) -> Self { pub fn new(s: String) -> Self {
Brain(s) Brain(s)
} }
pub fn validate_phrase(phrase: &str, expected_words: usize) -> Result<(), ::WordlistError> {
parity_wordlist::validate_phrase(phrase, expected_words)
}
} }
impl Generator for Brain { impl Generator for Brain {
type Error = ::Void; type Error = ::Void;
fn generate(self) -> Result<KeyPair, Self::Error> { fn generate(&mut self) -> Result<KeyPair, Self::Error> {
let seed = self.0; let seed = self.0.clone();
let mut secret = seed.into_bytes().keccak256(); let mut secret = seed.into_bytes().keccak256();
let mut i = 0; let mut i = 0;
@ -43,7 +48,10 @@ impl Generator for Brain {
if let Ok(pair) = Secret::from_unsafe_slice(&secret) if let Ok(pair) = Secret::from_unsafe_slice(&secret)
.and_then(KeyPair::from_secret) .and_then(KeyPair::from_secret)
{ {
if pair.address()[0] == 0 { return Ok(pair) } if pair.address()[0] == 0 {
trace!("Testing: {}, got: {:?}", self.0, pair.address());
return Ok(pair)
}
} }
}, },
} }

View File

@ -0,0 +1,70 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use super::{Generator, KeyPair, Error, Brain};
use parity_wordlist as wordlist;
/// Tries to find brain-seed keypair with address starting with given prefix.
pub struct BrainPrefix {
prefix: Vec<u8>,
iterations: usize,
no_of_words: usize,
last_phrase: String,
}
impl BrainPrefix {
pub fn new(prefix: Vec<u8>, iterations: usize, no_of_words: usize) -> Self {
BrainPrefix {
prefix,
iterations,
no_of_words,
last_phrase: String::new(),
}
}
pub fn phrase(&self) -> &str {
&self.last_phrase
}
}
impl Generator for BrainPrefix {
type Error = Error;
fn generate(&mut self) -> Result<KeyPair, Error> {
for _ in 0..self.iterations {
let phrase = wordlist::random_phrase(self.no_of_words);
let keypair = Brain::new(phrase.clone()).generate().unwrap();
if keypair.address().starts_with(&self.prefix) {
self.last_phrase = phrase;
return Ok(keypair)
}
}
Err(Error::Custom("Could not find keypair".into()))
}
}
#[cfg(test)]
mod tests {
use {Generator, BrainPrefix};
#[test]
fn prefix_generator() {
let prefix = vec![0x00u8];
let keypair = BrainPrefix::new(prefix.clone(), usize::max_value(), 12).generate().unwrap();
assert!(keypair.address().starts_with(&prefix));
}
}

175
ethkey/src/brain_recover.rs Normal file
View File

@ -0,0 +1,175 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::HashSet;
use edit_distance::edit_distance;
use parity_wordlist;
use super::{Address, Brain, Generator};
/// Tries to find a phrase for address, given the number
/// of expected words and a partial phrase.
///
/// Returns `None` if phrase couldn't be found.
pub fn brain_recover(
address: &Address,
known_phrase: &str,
expected_words: usize,
) -> Option<String> {
let it = PhrasesIterator::from_known_phrase(known_phrase, expected_words);
for phrase in it {
let keypair = Brain::new(phrase.clone()).generate().expect("Brain wallets are infallible; qed");
trace!("Testing: {}, got: {:?}", phrase, keypair.address());
if &keypair.address() == address {
return Some(phrase);
}
}
None
}
fn generate_substitutions(word: &str) -> Vec<&'static str> {
let mut words = parity_wordlist::WORDS.iter().cloned()
.map(|w| (edit_distance(w, word), w))
.collect::<Vec<_>>();
words.sort_by(|a, b| a.0.cmp(&b.0));
words.into_iter()
.map(|pair| pair.1)
.collect()
}
/// Iterator over possible
pub struct PhrasesIterator {
words: Vec<Vec<&'static str>>,
combinations: u64,
indexes: Vec<usize>,
has_next: bool,
}
impl PhrasesIterator {
pub fn from_known_phrase(known_phrase: &str, expected_words: usize) -> Self {
let known_words = parity_wordlist::WORDS.iter().cloned().collect::<HashSet<_>>();
let mut words = known_phrase.split(' ')
.map(|word| match known_words.get(word) {
None => {
info!("Invalid word '{}', looking for potential substitutions.", word);
let substitutions = generate_substitutions(word);
info!("Closest words: {:?}", &substitutions[..10]);
substitutions
},
Some(word) => vec![*word],
})
.collect::<Vec<_>>();
// add missing words
if words.len() < expected_words {
let to_add = expected_words - words.len();
info!("Number of words is insuficcient adding {} more.", to_add);
for _ in 0..to_add {
words.push(parity_wordlist::WORDS.iter().cloned().collect());
}
}
// start searching
PhrasesIterator::new(words)
}
pub fn new(words: Vec<Vec<&'static str>>) -> Self {
let combinations = words.iter().fold(1u64, |acc, x| acc * x.len() as u64);
let indexes = words.iter().map(|_| 0).collect();
info!("Starting to test {} possible combinations.", combinations);
PhrasesIterator {
words,
combinations,
indexes,
has_next: combinations > 0,
}
}
pub fn combinations(&self) -> u64 {
self.combinations
}
fn current(&self) -> String {
let mut s = self.words[0][self.indexes[0]].to_owned();
for i in 1..self.indexes.len() {
s.push(' ');
s.push_str(self.words[i][self.indexes[i]]);
}
s
}
fn next_index(&mut self) -> bool {
let mut pos = self.indexes.len();
while pos > 0 {
pos -= 1;
self.indexes[pos] += 1;
if self.indexes[pos] >= self.words[pos].len() {
self.indexes[pos] = 0;
} else {
return true;
}
}
false
}
}
impl Iterator for PhrasesIterator {
type Item = String;
fn next(&mut self) -> Option<String> {
if !self.has_next {
return None;
}
let phrase = self.current();
self.has_next = self.next_index();
Some(phrase)
}
}
#[cfg(test)]
mod tests {
use super::PhrasesIterator;
#[test]
fn should_generate_possible_combinations() {
let mut it = PhrasesIterator::new(vec![
vec!["1", "2", "3"],
vec!["test"],
vec!["a", "b", "c"],
]);
assert_eq!(it.combinations(), 9);
assert_eq!(it.next(), Some("1 test a".to_owned()));
assert_eq!(it.next(), Some("1 test b".to_owned()));
assert_eq!(it.next(), Some("1 test c".to_owned()));
assert_eq!(it.next(), Some("2 test a".to_owned()));
assert_eq!(it.next(), Some("2 test b".to_owned()));
assert_eq!(it.next(), Some("2 test c".to_owned()));
assert_eq!(it.next(), Some("3 test a".to_owned()));
assert_eq!(it.next(), Some("3 test b".to_owned()));
assert_eq!(it.next(), Some("3 test c".to_owned()));
assert_eq!(it.next(), None);
}
}

View File

@ -14,18 +14,25 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate rand; // #![warn(missing_docs)]
extern crate tiny_keccak;
extern crate secp256k1;
extern crate rustc_hex;
extern crate ethcore_bigint as bigint;
extern crate crypto as rcrypto;
extern crate byteorder; extern crate byteorder;
extern crate crypto as rcrypto;
extern crate edit_distance;
extern crate ethcore_bigint as bigint;
extern crate parity_wordlist;
extern crate rand;
extern crate rustc_hex;
extern crate secp256k1;
extern crate tiny_keccak;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
#[macro_use]
extern crate log;
mod brain; mod brain;
mod brain_prefix;
mod error; mod error;
mod keypair; mod keypair;
mod keccak; mod keccak;
@ -35,9 +42,12 @@ mod signature;
mod secret; mod secret;
mod extended; mod extended;
pub mod brain_recover;
pub mod math; pub mod math;
pub use self::parity_wordlist::Error as WordlistError;
pub use self::brain::Brain; pub use self::brain::Brain;
pub use self::brain_prefix::BrainPrefix;
pub use self::error::Error; pub use self::error::Error;
pub use self::keypair::{KeyPair, public_to_address}; pub use self::keypair::{KeyPair, public_to_address};
pub use self::math::public_is_valid; pub use self::math::public_is_valid;
@ -62,7 +72,7 @@ pub trait Generator {
type Error; type Error;
/// Should be called to generate new keypair. /// Should be called to generate new keypair.
fn generate(self) -> Result<KeyPair, Self::Error>; fn generate(&mut self) -> Result<KeyPair, Self::Error>;
} }
pub type Address = H160; pub type Address = H160;

View File

@ -34,7 +34,7 @@ impl Prefix {
impl Generator for Prefix { impl Generator for Prefix {
type Error = Error; type Error = Error;
fn generate(self) -> Result<KeyPair, Error> { fn generate(&mut self) -> Result<KeyPair, Error> {
for _ in 0..self.iterations { for _ in 0..self.iterations {
let keypair = Random.generate()?; let keypair = Random.generate()?;
if keypair.address().starts_with(&self.prefix) { if keypair.address().starts_with(&self.prefix) {

View File

@ -23,7 +23,7 @@ pub struct Random;
impl Generator for Random { impl Generator for Random {
type Error = ::std::io::Error; type Error = ::std::io::Error;
fn generate(self) -> Result<KeyPair, Self::Error> { fn generate(&mut self) -> Result<KeyPair, Self::Error> {
let mut rng = OsRng::new()?; let mut rng = OsRng::new()?;
match rng.generate() { match rng.generate() {
Ok(pair) => Ok(pair), Ok(pair) => Ok(pair),
@ -32,10 +32,10 @@ impl Generator for Random {
} }
} }
impl<'a> Generator for &'a mut OsRng { impl Generator for OsRng {
type Error = ::Void; type Error = ::Void;
fn generate(self) -> Result<KeyPair, Self::Error> { fn generate(&mut self) -> Result<KeyPair, Self::Error> {
let (sec, publ) = SECP256K1.generate_keypair(self) let (sec, publ) = SECP256K1.generate_keypair(self)
.expect("context always created with full capabilities; qed"); .expect("context always created with full capabilities; qed");

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ethstore" name = "ethstore"
version = "0.1.0" version = "0.2.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]

View File

@ -21,6 +21,7 @@ Usage:
ethstore list [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore list [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore import [--src DIR] [--dir DIR] ethstore import [--src DIR] [--dir DIR]
ethstore import-wallet <path> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore import-wallet <path> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore find-wallet-pass <path> <password>
ethstore remove <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore remove <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore sign <address> <password> <message> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore sign <address> <password> <message> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore public <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore public <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
@ -50,6 +51,7 @@ Commands:
list List accounts. list List accounts.
import Import accounts from src. import Import accounts from src.
import-wallet Import presale wallet. import-wallet Import presale wallet.
find-wallet-pass Tries to open a wallet with list of passwords given.
remove Remove account. remove Remove account.
sign Sign message. sign Sign message.
public Displays public key for an address. public Displays public key for an address.
@ -164,6 +166,25 @@ ethstore import-wallet ethwallet.json password.txt
e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb
``` ```
--
#### `find-wallet-pass <path> <password>`
Try to open presale wallet given a list of passwords from a file.
The list of passwords can be generated using e.g. [Phildo/brutedist](https://github.com/Phildo/brutedist).
- `<path>` - presale wallet path
- `<password>` - possible passwords, file path
```
ethstore find-wallet-pass ethwallet.json passwords.txt
```
```
Found password: test
```
-- --
#### `remove <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]` #### `remove <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]`
@ -318,8 +339,8 @@ OK
-- --
# Ethcore toolchain # Parity toolchain
*this project is a part of the ethcore toolchain* *this project is a part of the parity toolchain*
- [**ethkey**](https://github.com/paritytech/ethkey) - Ethereum keys generator and signer. - [**ethkey**](https://github.com/paritytech/ethkey) - Ethereum keys generator and signer.
- [**ethstore**](https://github.com/paritytech/ethstore) - Ethereum key management. - [**ethstore**](https://github.com/paritytech/ethstore) - Ethereum key management.

View File

@ -4,10 +4,12 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
docopt = "0.8"
num_cpus = "1.6"
rustc-hex = "1.0" rustc-hex = "1.0"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
docopt = "0.8" parking_lot = "0.4"
ethstore = { path = "../" } ethstore = { path = "../" }
panic_hook = { path = "../../panic_hook" } panic_hook = { path = "../../panic_hook" }

50
ethstore/cli/src/crack.rs Normal file
View File

@ -0,0 +1,50 @@
use std::{cmp, thread};
use std::sync::Arc;
use std::collections::VecDeque;
use parking_lot::Mutex;
use ethstore::{PresaleWallet, Error};
use num_cpus;
pub fn run(passwords: VecDeque<String>, wallet_path: &str) -> Result<(), Error> {
let passwords = Arc::new(Mutex::new(passwords));
let mut handles = Vec::new();
for _ in 0..num_cpus::get() {
let passwords = passwords.clone();
let wallet = PresaleWallet::open(&wallet_path)?;
handles.push(thread::spawn(move || {
look_for_password(passwords, wallet);
}));
}
for handle in handles {
handle.join().map_err(|err| Error::Custom(format!("Error finishing thread: {:?}", err)))?;
}
Ok(())
}
fn look_for_password(passwords: Arc<Mutex<VecDeque<String>>>, wallet: PresaleWallet) {
let mut counter = 0;
while !passwords.lock().is_empty() {
let package = {
let mut passwords = passwords.lock();
let len = passwords.len();
passwords.split_off(cmp::min(len, 32))
};
for pass in package {
counter += 1;
match wallet.decrypt(&pass) {
Ok(_) => {
println!("Found password: {}", &pass);
passwords.lock().clear();
return;
},
_ if counter % 100 == 0 => print!("."),
_ => {},
}
}
}
}

View File

@ -14,21 +14,27 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate rustc_hex;
extern crate docopt; extern crate docopt;
extern crate ethstore;
extern crate num_cpus;
extern crate panic_hook;
extern crate parking_lot;
extern crate rustc_hex;
extern crate serde; extern crate serde;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate ethstore;
extern crate panic_hook;
use std::{env, process, fs, fmt}; use std::collections::VecDeque;
use std::io::Read; use std::io::Read;
use std::{env, process, fs, fmt};
use docopt::Docopt; use docopt::Docopt;
use ethstore::ethkey::Address;
use ethstore::dir::{paths, KeyDirectory, RootDiskDirectory}; use ethstore::dir::{paths, KeyDirectory, RootDiskDirectory};
use ethstore::{EthStore, SimpleSecretStore, SecretStore, import_accounts, PresaleWallet, use ethstore::ethkey::Address;
SecretVaultRef, StoreAccountRef}; use ethstore::{EthStore, SimpleSecretStore, SecretStore, import_accounts, PresaleWallet, SecretVaultRef, StoreAccountRef};
mod crack;
pub const USAGE: &'static str = r#" pub const USAGE: &'static str = r#"
Ethereum key management. Ethereum key management.
@ -40,6 +46,7 @@ Usage:
ethstore list [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore list [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore import [--src DIR] [--dir DIR] ethstore import [--src DIR] [--dir DIR]
ethstore import-wallet <path> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore import-wallet <path> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore find-wallet-pass <path> <password>
ethstore remove <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore remove <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore sign <address> <password> <message> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore sign <address> <password> <message> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore public <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore public <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
@ -69,6 +76,7 @@ Commands:
list List accounts. list List accounts.
import Import accounts from src. import Import accounts from src.
import-wallet Import presale wallet. import-wallet Import presale wallet.
find-wallet-pass Tries to open a wallet with list of passwords given.
remove Remove account. remove Remove account.
sign Sign message. sign Sign message.
public Displays public key for an address. public Displays public key for an address.
@ -86,6 +94,7 @@ struct Args {
cmd_list: bool, cmd_list: bool,
cmd_import: bool, cmd_import: bool,
cmd_import_wallet: bool, cmd_import_wallet: bool,
cmd_find_wallet_pass: bool,
cmd_remove: bool, cmd_remove: bool,
cmd_sign: bool, cmd_sign: bool,
cmd_public: bool, cmd_public: bool,
@ -239,6 +248,11 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
let vault_ref = open_args_vault(&store, &args)?; let vault_ref = open_args_vault(&store, &args)?;
let account_ref = store.insert_account(vault_ref, kp.secret().clone(), &password)?; let account_ref = store.insert_account(vault_ref, kp.secret().clone(), &password)?;
Ok(format!("0x{:?}", account_ref.address)) Ok(format!("0x{:?}", account_ref.address))
} else if args.cmd_find_wallet_pass {
let passwords = load_password(&args.arg_password)?;
let passwords = passwords.lines().map(str::to_owned).collect::<VecDeque<_>>();
crack::run(passwords, &args.arg_path)?;
Ok(format!("Password not found."))
} else if args.cmd_remove { } else if args.cmd_remove {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?; let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?; let password = load_password(&args.arg_password)?;

586
js-old/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@
"lint": "npm run lint:css && npm run lint:js", "lint": "npm run lint:css && npm run lint:js",
"lint:css": "stylelint ./src/**/*.css", "lint:css": "stylelint ./src/**/*.css",
"lint:js": "eslint --ignore-path .gitignore ./src/", "lint:js": "eslint --ignore-path .gitignore ./src/",
"test": "NODE_ENV=test mocha --compilers ejs:ejsify 'src/**/*.spec.js'", "test": "NODE_ENV=test mocha 'src/**/*.spec.js'",
"watch": "webpack --watch --config webpack/app" "watch": "webpack --watch --config webpack/app"
}, },
"napa": { "napa": {
@ -75,7 +75,6 @@
"cross-env": "5.1.1", "cross-env": "5.1.1",
"css-loader": "0.26.1", "css-loader": "0.26.1",
"ejs-loader": "0.3.0", "ejs-loader": "0.3.0",
"ejsify": "1.0.0",
"empty-module": "0.0.2", "empty-module": "0.0.2",
"enzyme": "2.7.1", "enzyme": "2.7.1",
"eslint": "3.16.1", "eslint": "3.16.1",
@ -93,7 +92,6 @@
"html-loader": "0.4.4", "html-loader": "0.4.4",
"html-webpack-plugin": "2.28.0", "html-webpack-plugin": "2.28.0",
"http-proxy-middleware": "0.17.3", "http-proxy-middleware": "0.17.3",
"ignore-styles": "5.0.1",
"istanbul": "1.0.0-alpha.2", "istanbul": "1.0.0-alpha.2",
"jsdom": "9.11.0", "jsdom": "9.11.0",
"json-loader": "0.5.4", "json-loader": "0.5.4",

View File

@ -24,17 +24,20 @@ git remote set-url origin $PRE_REPO_TOKEN > /dev/null 2>&1
echo "*** [$PRE_REPO] Copying build" echo "*** [$PRE_REPO] Copying build"
rm -rf build rm -rf build
cp -rf ../.dist/build . cp -rf ../.dist/build .
find . -name "*.css.map" -type f -delete
find . -name "*.js.map" -type f -delete
find . -name "package.json" -type f -delete
echo "*** [$PRE_REPO] Adding to git" echo "*** [$PRE_REPO] Adding to git"
echo "$UTCDATE" >README.md echo "$UTCDATE" >README.md
git add . git add --all .
git commit -m "$UTCDATE" git commit -m "$UTCDATE"
echo "*** [$PRE_REPO] Pushing upstream" echo "*** [$PRE_REPO] Pushing upstream"
git push --quiet origin HEAD:refs/heads/master > /dev/null 2>&1 git push --quiet origin HEAD:refs/heads/master > /dev/null 2>&1
cd .. cd ..
rm -rf precompiled rm -rf .dist .build .happypack precompiled
popd popd
# exit with exit code # exit with exit code

View File

@ -1 +1 @@
// test script 16 // test script 21

View File

@ -16,59 +16,15 @@
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import React from 'react'; import React from 'react';
import sinon from 'sinon';
import Home from './'; import Home from './';
const TEST_APP_HISTORY = [];
let api;
let component; let component;
let instance;
let store;
function createStore () {
store = {
dispatch: sinon.stub(),
subscribe: sinon.stub(),
getState: () => {
return {
nodeStatus: {
nodeKind: {
'availability': 'personal'
}
}
};
}
};
return store;
}
function createApi () {
api = {
parity: {
listRecentDapps: sinon.stub().resolves(TEST_APP_HISTORY)
}
};
return api;
}
function render () { function render () {
component = shallow( component = shallow(
<Home />, <Home />
{ );
context: {
store: createStore()
}
}
).find('Home').shallow({
context: {
api: createApi()
}
});
instance = component.instance();
return component; return component;
} }
@ -82,38 +38,9 @@ describe('views/Home', () => {
expect(component).to.be.ok; expect(component).to.be.ok;
}); });
describe('lifecycle', () => {
describe('componentWillMount', () => {
beforeEach(() => {
sinon.stub(instance.webStore, 'loadHistory');
return instance.componentWillMount();
});
afterEach(() => {
instance.webStore.loadHistory.restore();
});
it('calls into webStore loadHistory', () => {
expect(instance.webStore.loadHistory).to.have.been.called;
});
});
});
describe('components', () => { describe('components', () => {
it('renders Accounts', () => {
expect(component.find('Connect(Accounts)').length).to.equal(1);
});
it('renders Dapps', () => {
expect(component.find('Dapps').length).to.equal(1);
});
it('renders News', () => { it('renders News', () => {
expect(component.find('News').length).to.equal(1); expect(component.find('News').length).to.equal(1);
}); });
it('renders Urls', () => {
expect(component.find('Urls').length).to.equal(1);
});
}); });
}); });

View File

@ -68,7 +68,7 @@ function render () {
return component; return component;
} }
describe.only('views/Signer/components/SignRequest', () => { describe('views/Signer/components/SignRequest', () => {
beforeEach(() => { beforeEach(() => {
render(); render();
}); });

View File

@ -0,0 +1,24 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
const EXTENSIONS = ['.css', '.ejs', '.md', '.png', '.svg'];
function noop () {
}
EXTENSIONS.forEach((extension) => {
require.extensions[extension] = noop;
});

View File

@ -1,3 +1,3 @@
-r ./test/babel -r ./test/babel
-r ./test/mocha.config -r ./test/mocha.config
-r ignore-styles -r ./test/ignoreImports

2579
js/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "Parity", "name": "Parity",
"version": "1.9.13", "version": "1.9.22",
"main": "src/index.parity.js", "main": "src/index.parity.js",
"jsnext:main": "src/index.parity.js", "jsnext:main": "src/index.parity.js",
"author": "Parity Team <admin@parity.io>", "author": "Parity Team <admin@parity.io>",
@ -40,14 +40,14 @@
"start": "npm run clean && npm install && npm run build:inject && npm run start:app", "start": "npm run clean && npm install && npm run build:inject && npm run start:app",
"start:app": "node webpack/dev.server", "start:app": "node webpack/dev.server",
"start:electron": "npm run build:app && electron .build/", "start:electron": "npm run build:app && electron .build/",
"test": "cross-env NODE_ENV=test mocha --compilers ejs:ejsify 'src/**/*.spec.js'", "test": "cross-env NODE_ENV=test mocha 'src/**/*.spec.js'",
"test:coverage": "cross-env NODE_ENV=test istanbul cover _mocha -- --compilers ejs:ejsify 'src/**/*.spec.js'" "test:coverage": "cross-env NODE_ENV=test istanbul cover _mocha -- 'src/**/*.spec.js'"
}, },
"devDependencies": { "devDependencies": {
"@parity/dapp-console": "paritytech/dapp-console", "@parity/dapp-console": "paritytech/dapp-console",
"@parity/dapp-dapp-accounts": "paritytech/dapp-dapp-accounts", "@parity/dapp-dapp-accounts": "paritytech/dapp-dapp-accounts",
"@parity/dapp-dapp-methods": "js-dist-paritytech/dapp-dapp-methods", "@parity/dapp-dapp-methods": "js-dist-paritytech/dapp-dapp-methods",
"@parity/dapp-dapp-visible": "paritytech/dapp-dapp-visible", "@parity/dapp-dapp-visible": "js-dist-paritytech/dapp-dapp-visible",
"@parity/dapp-dappreg": "paritytech/dapp-dappreg", "@parity/dapp-dappreg": "paritytech/dapp-dappreg",
"@parity/dapp-githubhint": "paritytech/dapp-githubhint", "@parity/dapp-githubhint": "paritytech/dapp-githubhint",
"@parity/dapp-localtx": "paritytech/dapp-localtx", "@parity/dapp-localtx": "paritytech/dapp-localtx",
@ -76,7 +76,7 @@
"babel-register": "6.26.0", "babel-register": "6.26.0",
"chai": "3.5.0", "chai": "3.5.0",
"chai-as-promised": "6.0.0", "chai-as-promised": "6.0.0",
"chai-enzyme": "0.6.1", "chai-enzyme": "1.0.0-beta.0",
"chalk": "1.1.3", "chalk": "1.1.3",
"copy-webpack-plugin": "4.0.1", "copy-webpack-plugin": "4.0.1",
"core-js": "2.4.1", "core-js": "2.4.1",
@ -84,10 +84,10 @@
"cross-env": "5.1.1", "cross-env": "5.1.1",
"css-loader": "0.28.4", "css-loader": "0.28.4",
"ejs-loader": "0.3.0", "ejs-loader": "0.3.0",
"ejsify": "1.0.0",
"electron": "1.7.5", "electron": "1.7.5",
"empty-module": "0.0.2", "empty-module": "0.0.2",
"enzyme": "2.9.1", "enzyme": "3.2.0",
"enzyme-adapter-react-16": "1.1.0",
"eslint": "3.16.1", "eslint": "3.16.1",
"eslint-config-semistandard": "7.0.0", "eslint-config-semistandard": "7.0.0",
"eslint-config-standard": "6.2.1", "eslint-config-standard": "6.2.1",
@ -104,7 +104,6 @@
"html-loader": "0.4.4", "html-loader": "0.4.4",
"html-webpack-plugin": "2.30.1", "html-webpack-plugin": "2.30.1",
"http-proxy-middleware": "0.17.3", "http-proxy-middleware": "0.17.3",
"ignore-styles": "5.0.1",
"istanbul": "1.0.0-alpha.2", "istanbul": "1.0.0-alpha.2",
"jsdom": "9.11.0", "jsdom": "9.11.0",
"json-loader": "0.5.4", "json-loader": "0.5.4",
@ -120,8 +119,8 @@
"progress": "1.1.8", "progress": "1.1.8",
"raw-loader": "0.5.1", "raw-loader": "0.5.1",
"react-addons-perf": "15.4.2", "react-addons-perf": "15.4.2",
"react-addons-test-utils": "15.4.2", "react-addons-test-utils": "15.6.2",
"react-hot-loader": "3.0.0-beta.6", "react-hot-loader": "3.1.3",
"react-intl-aggregate-webpack-plugin": "0.0.1", "react-intl-aggregate-webpack-plugin": "0.0.1",
"rimraf": "2.6.2", "rimraf": "2.6.2",
"sinon": "1.17.7", "sinon": "1.17.7",
@ -150,22 +149,28 @@
"@parity/plugin-signer-hardware": "paritytech/plugin-signer-hardware", "@parity/plugin-signer-hardware": "paritytech/plugin-signer-hardware",
"@parity/plugin-signer-qr": "paritytech/plugin-signer-qr", "@parity/plugin-signer-qr": "paritytech/plugin-signer-qr",
"@parity/shared": "2.2.x", "@parity/shared": "2.2.x",
"@parity/ui": "2.2.x", "@parity/ui": "~3.0.4",
"keythereum": "1.0.2", "keythereum": "1.0.2",
"lodash.flatten": "4.4.0", "lodash.flatten": "4.4.0",
"lodash.omitby": "4.6.0", "lodash.omitby": "4.6.0",
"lodash.throttle": "4.1.1", "lodash.throttle": "4.1.1",
"lodash.uniq": "4.5.0", "lodash.uniq": "4.5.0",
"material-ui": "0.16.5", "material-ui": "0.16.5",
"mobx": "3.3.2",
"mobx-react": "4.3.5",
"prop-types": "15.5.10", "prop-types": "15.5.10",
"query-string": "5.0.1", "query-string": "5.0.1",
"react": "15.6.1", "react": "16.1.1",
"react-dom": "15.6.1", "react-dom": "16.1.1",
"react-intl": "2.1.5", "react-intl": "2.4.0",
"react-markdown": "2.5.0", "react-markdown": "3.0.2",
"react-router": "3.0.0", "react-redux": "^5.0.6",
"react-tap-event-plugin": "2.0.1", "react-router": "3.2.0",
"redux": "3.6.0", "react-router-redux": "4.0.8",
"react-tap-event-plugin": "3.0.2",
"react-transition-group": "2.2.1",
"redux": "3.7.2",
"semantic-ui-react": "0.77.0",
"solc": "ngotchac/solc-js", "solc": "ngotchac/solc-js",
"store": "1.3.20", "store": "1.3.20",
"web3": "0.17.0-beta" "web3": "0.17.0-beta"

View File

@ -3,7 +3,7 @@ set -e
# variables # variables
PVER="1-9" PVER="1-9"
PTYPE="v1" PTYPE="shell"
UTCDATE=`date -u "+%Y%m%d-%H%M%S"` UTCDATE=`date -u "+%Y%m%d-%H%M%S"`
PRE_REPO="js-dist-paritytech/parity-${CI_BUILD_REF_NAME}-${PVER}-${PTYPE}.git" PRE_REPO="js-dist-paritytech/parity-${CI_BUILD_REF_NAME}-${PVER}-${PTYPE}.git"
PRE_REPO_TOKEN="https://${GITHUB_JS_PRECOMPILED}:@github.com/${PRE_REPO}" PRE_REPO_TOKEN="https://${GITHUB_JS_PRECOMPILED}:@github.com/${PRE_REPO}"
@ -24,17 +24,20 @@ git remote set-url origin $PRE_REPO_TOKEN > /dev/null 2>&1
echo "*** [$PRE_REPO] Copying build" echo "*** [$PRE_REPO] Copying build"
rm -rf build rm -rf build
cp -rf ../.dist/build . cp -rf ../.dist/build .
find . -name "*.css.map" -type f -delete
find . -name "*.js.map" -type f -delete
find . -name "package.json" -type f -delete
echo "*** [$PRE_REPO] Adding to git" echo "*** [$PRE_REPO] Adding to git"
echo "$UTCDATE" >README.md echo "$UTCDATE" >README.md
git add . git add --all .
git commit -m "$UTCDATE" git commit -m "$UTCDATE"
echo "*** [$PRE_REPO] Pushing upstream" echo "*** [$PRE_REPO] Pushing upstream"
git push --quiet origin HEAD:refs/heads/master > /dev/null 2>&1 git push --quiet origin HEAD:refs/heads/master > /dev/null 2>&1
cd .. cd ..
rm -rf precompiled rm -rf .dist .build .happypack precompiled
popd popd
# exit with exit code # exit with exit code

View File

@ -1 +1 @@
// test script 21 // test script 26

View File

@ -23,7 +23,6 @@
opacity: 0; opacity: 0;
width: 100%; width: 100%;
z-index: 1; z-index: 1;
background: white;
} }
.full { .full {

View File

@ -15,13 +15,13 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import React, { PureComponent } from 'react'; import React, { Component } from 'react';
import RequestGroups from './RequestGroups'; import RequestGroups from './RequestGroups';
import Store from './store'; import Store from './store';
import styles from './dappRequests.css'; import styles from './dappRequests.css';
class DappRequests extends PureComponent { class DappRequests extends Component {
store = Store.get(); store = Store.get();
handleApproveRequestGroup = requestIds => { handleApproveRequestGroup = requestIds => {

View File

@ -0,0 +1,36 @@
/* Copyright 2015-2017 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify
/* it under the terms of the GNU General Public License as published by
/* the Free Software Foundation, either version 3 of the License, or
/* (at your option) any later version.
/*
/* Parity is distributed in the hope that it will be useful,
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/* GNU General Public License for more details.
/*
/* You should have received a copy of the GNU General Public License
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
.defaultContent {
color: rgba(0, 0, 0, 0.8);
vertical-align: middle !important;
}
.avatarWrapper {
width: 4.2em !important;
display: flex;
justify-content: center;
}
.bigAvatar {
width: 4em !important;
height: 4em !important;
}
.description {
margin-top: 0.5em;
}

View File

@ -0,0 +1,64 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Image from 'semantic-ui-react/dist/commonjs/elements/Image';
import List from 'semantic-ui-react/dist/commonjs/elements/List';
import IdentityIcon from '@parity/ui/lib/IdentityIcon';
import styles from './accountItem.css';
class AccountItem extends PureComponent {
static propTypes = {
account: PropTypes.object.isRequired,
isDefault: PropTypes.bool,
onClick: PropTypes.func
}
handleClick = () => {
this.props.onClick(this.props.account.address);
}
render () {
const { account, isDefault } = this.props;
return (
<List.Item
onClick={ this.handleClick }
disabled={ isDefault }
>
<Image avatar>
<div className={ styles.avatarWrapper }>
<IdentityIcon address={ account.address }
alt={ account.address }
className={ isDefault ? styles.bigAvatar : '' }
/>
</div>
</Image>
<List.Content className={ isDefault ? styles.defaultContent : '' }>
<List.Header>
{account.name}
</List.Header>
{account.address}
{isDefault && <p className={ styles.description }>{account.meta.description}</p>}
</List.Content>
</List.Item>
);
}
}
export default AccountItem;

View File

@ -0,0 +1,17 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './accountItem';

View File

@ -0,0 +1,38 @@
/* Copyright 2015-2017 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify
/* it under the terms of the GNU General Public License as published by
/* the Free Software Foundation, either version 3 of the License, or
/* (at your option) any later version.
/*
/* Parity is distributed in the hope that it will be useful,
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/* GNU General Public License for more details.
/*
/* You should have received a copy of the GNU General Public License
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
.defaultAccount {
cursor: pointer;
}
.popup {
padding: 0 !important;
}
.list {
margin: 0 !important;
padding: 1em 1em !important;
background-color: #f5f5f5;
}
.isDefault {
background-color: white;
}
.hasOtherAccounts {
border-bottom: 1px solid #D4D4D5;
}

View File

@ -0,0 +1,104 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { observer } from 'mobx-react';
import List from 'semantic-ui-react/dist/commonjs/elements/List';
import Popup from 'semantic-ui-react/dist/commonjs/modules/Popup';
import IdentityIcon from '@parity/ui/lib/IdentityIcon';
import AccountItem from './AccountItem';
import styles from './defaultAccount.css';
@observer
class DefaultAccount extends Component {
state = {
isOpen: false
}
static propTypes = {
accountStore: PropTypes.object.isRequired
}
handleOpen = () => {
this.setState({ isOpen: true });
}
handleClose = () => {
this.setState({ isOpen: false });
}
handleMakeDefault = (address) => {
this.handleClose();
if (address === this.props.accountStore.defaultAddress) { return; }
this.props.accountStore.makeDefaultAccount(address);
}
render () {
const { accounts, defaultAccount: defaultAddress } = this.props.accountStore;
const defaultAccount = accounts.find(({ address }) => address === defaultAddress);
if (!accounts || !defaultAccount) { return null; }
return (
<Popup
wide='very'
className={ styles.popup }
trigger={
<IdentityIcon
address={ defaultAddress } button
center
className={ styles.defaultAccount }
/>
}
content={
<div>
<List relaxed='very' selection className={ [styles.list, styles.isDefault, accounts.length > 1 && styles.hasOtherAccounts].join(' ') }>
<AccountItem
isDefault
account={ defaultAccount }
/>
</List>
{accounts.length > 1 &&
<List relaxed='very' selection className={ styles.list } divided>
{accounts
.filter(({ address }) => address !== defaultAddress)
.map(account => (
<AccountItem
key={ account.address }
account={ account }
onClick={ this.handleMakeDefault }
/>
))}
</List>
}
</div>
}
offset={ 13 } // Empirically looks better
on='click'
hideOnScroll
open={ this.state.isOpen }
onClose={ this.handleClose }
onOpen={ this.handleOpen }
position='bottom right'
/>
);
}
}
export default DefaultAccount;

View File

@ -0,0 +1,17 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './defaultAccount';

View File

@ -75,7 +75,6 @@ $textColor: #ccc;
opacity: 0.75; opacity: 0.75;
} }
.defaultAccount,
.signerPending { .signerPending {
cursor: pointer; cursor: pointer;
} }

View File

@ -23,13 +23,13 @@ import BlockNumber from '@parity/ui/lib/BlockNumber';
import ClientVersion from '@parity/ui/lib/ClientVersion'; import ClientVersion from '@parity/ui/lib/ClientVersion';
import GradientBg from '@parity/ui/lib/GradientBg'; import GradientBg from '@parity/ui/lib/GradientBg';
import { HomeIcon } from '@parity/ui/lib/Icons'; import { HomeIcon } from '@parity/ui/lib/Icons';
import IdentityIcon from '@parity/ui/lib/IdentityIcon';
import NetChain from '@parity/ui/lib/NetChain'; import NetChain from '@parity/ui/lib/NetChain';
import NetPeers from '@parity/ui/lib/NetPeers'; import NetPeers from '@parity/ui/lib/NetPeers';
import SignerPending from '@parity/ui/lib/SignerPending'; import SignerPending from '@parity/ui/lib/SignerPending';
import StatusIndicator from '@parity/ui/lib/StatusIndicator'; import StatusIndicator from '@parity/ui/lib/StatusIndicator';
import Consensus from './Consensus'; import Consensus from './Consensus';
import DefaultAccount from './DefaultAccount';
import AccountStore from '../ParityBar/accountStore'; import AccountStore from '../ParityBar/accountStore';
import ParityBarStore from '../ParityBar/store'; import ParityBarStore from '../ParityBar/store';
import SyncWarning from '../SyncWarning'; import SyncWarning from '../SyncWarning';
@ -67,12 +67,9 @@ function Status ({ className = '', upgradeStore }, { api }) {
className={ styles.signerPending } className={ styles.signerPending }
onClick={ parityBarStore.toggleOpenSigner } onClick={ parityBarStore.toggleOpenSigner }
/> />
<IdentityIcon
address={ accountStore.defaultAccount } <DefaultAccount
button accountStore={ accountStore }
center
className={ styles.defaultAccount }
onClick={ parityBarStore.toggleOpenAccounts }
/> />
<StatusIndicator <StatusIndicator
className={ styles.health } className={ styles.health }

View File

@ -40,12 +40,17 @@ injectTapEventPlugin();
window.React = window.React || React; window.React = window.React || React;
// FIXME
// Not working with React 16
// https://reactjs.org/docs/perf.html
/*
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
// Expose the React Performance Tools on the`window` object // Expose the React Performance Tools on the`window` object
const Perf = require('react-addons-perf'); const Perf = require('react-addons-perf');
window.Perf = Perf; window.Perf = Perf;
} }
*/
const AUTH_HASH = '#/auth?'; const AUTH_HASH = '#/auth?';

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import mobx from 'mobx'; import * as mobx from 'mobx';
import flatten from 'lodash.flatten'; import flatten from 'lodash.flatten';
import { sha3 } from '@parity/api/lib/util/sha3'; import { sha3 } from '@parity/api/lib/util/sha3';

24
js/test/ignoreImports.js Normal file
View File

@ -0,0 +1,24 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
const EXTENSIONS = ['.css', '.ejs', '.md', '.png', '.svg'];
function noop () {
}
EXTENSIONS.forEach((extension) => {
require.extensions[extension] = noop;
});

View File

@ -23,6 +23,8 @@ es6Promise.polyfill();
import injectTapEventPlugin from 'react-tap-event-plugin'; import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin(); injectTapEventPlugin();
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import chai from 'chai'; import chai from 'chai';
import chaiAsPromised from 'chai-as-promised'; import chaiAsPromised from 'chai-as-promised';
import chaiEnzyme from 'chai-enzyme'; import chaiEnzyme from 'chai-enzyme';
@ -31,6 +33,7 @@ import sinonChai from 'sinon-chai';
import { WebSocket } from 'mock-socket'; import { WebSocket } from 'mock-socket';
import jsdom from 'jsdom'; import jsdom from 'jsdom';
Enzyme.configure({ adapter: new Adapter() });
chai.use(chaiAsPromised); chai.use(chaiAsPromised);
chai.use(chaiEnzyme()); chai.use(chaiEnzyme());
chai.use(sinonChai); chai.use(sinonChai);
@ -44,7 +47,7 @@ global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = document.defaultView; global.window = document.defaultView;
global.navigator = global.window.navigator; global.navigator = global.window.navigator;
global.location = global.window.location; global.location = global.window.location;
global.Blob = () => {}; global.Blob = () => { };
// attach mocked localStorage onto the window as exposed by jsdom // attach mocked localStorage onto the window as exposed by jsdom
global.window.localStorage = global.localStorage; global.window.localStorage = global.localStorage;

View File

@ -1,3 +1,3 @@
-r ./test/babel -r ./test/babel
-r ./test/mocha.config -r ./test/mocha.config
-r ignore-styles -r ./test/ignoreImports

View File

@ -69,12 +69,12 @@ module.exports = {
{ {
test: /\.js$/, test: /\.js$/,
exclude: /node_modules/, exclude: /node_modules/,
use: [ { use: [{
loader: 'happypack/loader', loader: 'happypack/loader',
options: { options: {
id: 'babel' id: 'babel'
} }
} ] }]
}, },
{ {
test: /\.json$/, test: /\.json$/,
@ -90,7 +90,7 @@ module.exports = {
}, },
{ {
test: /\.css$/, test: /\.css$/,
include: /semantic-ui-css/, include: /semantic-ui-css|@parity\/ui/,
use: ExtractTextPlugin.extract({ use: ExtractTextPlugin.extract({
fallback: 'style-loader', fallback: 'style-loader',
use: [ use: [
@ -105,7 +105,7 @@ module.exports = {
}, },
{ {
test: /\.css$/, test: /\.css$/,
exclude: /semantic-ui-css/, exclude: /semantic-ui-css|@parity\/ui/,
use: ExtractTextPlugin.extract({ use: ExtractTextPlugin.extract({
fallback: 'style-loader', fallback: 'style-loader',
use: [ use: [
@ -231,17 +231,17 @@ module.exports = {
isProd ? null : 'dist.css.map', isProd ? null : 'dist.css.map',
isProd ? null : 'dist.js.map' isProd ? null : 'dist.js.map'
] ]
.filter((file) => file) .filter((file) => file)
.map((file) => path.join(dir, file)) .map((file) => path.join(dir, file))
.filter((from) => fs.existsSync(from)) .filter((from) => fs.existsSync(from))
.map((from) => ({ .map((from) => ({
from, from,
to: `dapps/${destination}/` to: `dapps/${destination}/`
})) }))
.concat({ .concat({
from: path.join(dir, 'dist'), from: path.join(dir, 'dist'),
to: `dapps/${destination}/dist/` to: `dapps/${destination}/dist/`
}); });
}) })
.filter((copy) => copy) .filter((copy) => copy)
) )

View File

@ -32,8 +32,8 @@ lazy_static! {
builder.parse(&log); builder.parse(&log);
} }
if builder.init().is_ok() { if !builder.init().is_ok() {
println!("logger initialized"); println!("logger initialization failed!");
} }
}; };
} }
@ -66,7 +66,11 @@ impl RotatingLogger {
/// Append new log entry /// Append new log entry
pub fn append(&self, log: String) { pub fn append(&self, log: String) {
self.logs.write().insert(0, log); let mut logs = self.logs.write();
if logs.is_full() {
logs.pop();
}
logs.insert(0, log);
} }
/// Return levels /// Return levels

View File

@ -25,7 +25,7 @@ use cli::{Args, ArgsError};
use hash::keccak; use hash::keccak;
use bigint::prelude::U256; use bigint::prelude::U256;
use bigint::hash::H256; use bigint::hash::H256;
use util::{version_data, Address}; use util::{version_data, Address, version};
use bytes::Bytes; use bytes::Bytes;
use ansi_term::Colour; use ansi_term::Colour;
use ethsync::{NetworkConfiguration, validate_node_url, self}; use ethsync::{NetworkConfiguration, validate_node_url, self};
@ -752,6 +752,7 @@ impl Configuration {
ret.config_path = Some(net_path.to_str().unwrap().to_owned()); ret.config_path = Some(net_path.to_str().unwrap().to_owned());
ret.reserved_nodes = self.init_reserved_nodes()?; ret.reserved_nodes = self.init_reserved_nodes()?;
ret.allow_non_reserved = !self.args.flag_reserved_only; ret.allow_non_reserved = !self.args.flag_reserved_only;
ret.client_version = version();
Ok(ret) Ok(ret)
} }

View File

@ -213,6 +213,7 @@ pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
ip_filter: IpFilter::default(), ip_filter: IpFilter::default(),
reserved_nodes: Vec::new(), reserved_nodes: Vec::new(),
allow_non_reserved: true, allow_non_reserved: true,
client_version: ::util::version(),
} }
} }

View File

@ -6,7 +6,7 @@ After=network.target
# run as root, set base_path in config.toml # run as root, set base_path in config.toml
ExecStart=/usr/bin/parity --config /etc/parity/config.toml ExecStart=/usr/bin/parity --config /etc/parity/config.toml
# To run as user, comment out above and uncomment below, fill in user and group # To run as user, comment out above and uncomment below, fill in user and group
# picks up users default config.toml in $HOME/.local/.share/io.parity.ethereum/ # picks up users default config.toml in $HOME/.local/share/io.parity.ethereum/
# User=username # User=username
# Group=groupname # Group=groupname
# ExecStart=/usr/bin/parity # ExecStart=/usr/bin/parity

View File

@ -546,6 +546,8 @@ pub struct NetworkConfiguration {
pub allow_non_reserved: bool, pub allow_non_reserved: bool,
/// IP Filtering /// IP Filtering
pub ip_filter: IpFilter, pub ip_filter: IpFilter,
/// Client version string
pub client_version: String,
} }
impl NetworkConfiguration { impl NetworkConfiguration {
@ -578,6 +580,7 @@ impl NetworkConfiguration {
reserved_nodes: self.reserved_nodes, reserved_nodes: self.reserved_nodes,
ip_filter: self.ip_filter, ip_filter: self.ip_filter,
non_reserved_mode: if self.allow_non_reserved { NonReservedPeerMode::Accept } else { NonReservedPeerMode::Deny }, non_reserved_mode: if self.allow_non_reserved { NonReservedPeerMode::Accept } else { NonReservedPeerMode::Deny },
client_version: self.client_version,
}) })
} }
} }
@ -601,6 +604,7 @@ impl From<BasicNetworkConfiguration> for NetworkConfiguration {
reserved_nodes: other.reserved_nodes, reserved_nodes: other.reserved_nodes,
ip_filter: other.ip_filter, ip_filter: other.ip_filter,
allow_non_reserved: match other.non_reserved_mode { NonReservedPeerMode::Accept => true, _ => false } , allow_non_reserved: match other.non_reserved_mode { NonReservedPeerMode::Accept => true, _ => false } ,
client_version: other.client_version,
} }
} }
} }

View File

@ -11,7 +11,6 @@ build = "build.rs"
log = "0.3" log = "0.3"
env_logger = "0.4" env_logger = "0.4"
rustc-hex = "1.0" rustc-hex = "1.0"
rocksdb = { git = "https://github.com/paritytech/rust-rocksdb" }
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" } eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
elastic-array = "0.9" elastic-array = "0.9"
rlp = { path = "rlp" } rlp = { path = "rlp" }

View File

@ -22,7 +22,6 @@ parking_lot = "0.4"
ansi_term = "0.9" ansi_term = "0.9"
rustc-hex = "1.0" rustc-hex = "1.0"
ethcore-io = { path = "../io" } ethcore-io = { path = "../io" }
ethcore-util = { path = ".." }
ethcore-bigint = { path = "../bigint" } ethcore-bigint = { path = "../bigint" }
ethcore-bytes = { path = "../bytes" } ethcore-bytes = { path = "../bytes" }
ethkey = { path = "../../ethkey" } ethkey = { path = "../../ethkey" }
@ -32,7 +31,7 @@ path = { path = "../path" }
ethcore-logger = { path ="../../logger" } ethcore-logger = { path ="../../logger" }
ipnetwork = "0.12.6" ipnetwork = "0.12.6"
keccak-hash = { path = "../hash" } keccak-hash = { path = "../hash" }
snappy = { path = "../snappy" } snappy = { git = "https://github.com/paritytech/rust-snappy" }
serde_json = "1.0" serde_json = "1.0"
error-chain = { version = "0.11", default-features = false } error-chain = { version = "0.11", default-features = false }

View File

@ -30,7 +30,6 @@ use mio::*;
use mio::deprecated::{EventLoop}; use mio::deprecated::{EventLoop};
use mio::tcp::*; use mio::tcp::*;
use bigint::hash::*; use bigint::hash::*;
use util::version;
use rlp::*; use rlp::*;
use session::{Session, SessionInfo, SessionData}; use session::{Session, SessionInfo, SessionData};
use io::*; use io::*;
@ -108,6 +107,8 @@ pub struct NetworkConfiguration {
pub non_reserved_mode: NonReservedPeerMode, pub non_reserved_mode: NonReservedPeerMode,
/// IP filter /// IP filter
pub ip_filter: IpFilter, pub ip_filter: IpFilter,
/// Client identifier
pub client_version: String,
} }
impl Default for NetworkConfiguration { impl Default for NetworkConfiguration {
@ -136,6 +137,7 @@ impl NetworkConfiguration {
ip_filter: IpFilter::default(), ip_filter: IpFilter::default(),
reserved_nodes: Vec::new(), reserved_nodes: Vec::new(),
non_reserved_mode: NonReservedPeerMode::Accept, non_reserved_mode: NonReservedPeerMode::Accept,
client_version: "Parity-network".into(),
} }
} }
@ -331,8 +333,6 @@ pub struct HostInfo {
nonce: H256, nonce: H256,
/// RLPx protocol version /// RLPx protocol version
pub protocol_version: u32, pub protocol_version: u32,
/// Client identifier
pub client_version: String,
/// Registered capabilities (handlers) /// Registered capabilities (handlers)
pub capabilities: Vec<CapabilityInfo>, pub capabilities: Vec<CapabilityInfo>,
/// Local address + discovery port /// Local address + discovery port
@ -357,6 +357,10 @@ impl HostInfo {
self.nonce = keccak(&self.nonce); self.nonce = keccak(&self.nonce);
self.nonce self.nonce
} }
pub fn client_version(&self) -> &str {
&self.config.client_version
}
} }
type SharedSession = Arc<Mutex<Session>>; type SharedSession = Arc<Mutex<Session>>;
@ -423,7 +427,6 @@ impl Host {
config: config, config: config,
nonce: H256::random(), nonce: H256::random(),
protocol_version: PROTOCOL_VERSION, protocol_version: PROTOCOL_VERSION,
client_version: version(),
capabilities: Vec::new(), capabilities: Vec::new(),
public_endpoint: None, public_endpoint: None,
local_endpoint: local_endpoint, local_endpoint: local_endpoint,
@ -519,10 +522,6 @@ impl Host {
Ok(()) Ok(())
} }
pub fn client_version() -> String {
version()
}
pub fn external_url(&self) -> Option<String> { pub fn external_url(&self) -> Option<String> {
let info = self.info.read(); let info = self.info.read();
info.public_endpoint.as_ref().map(|e| format!("{}", Node::new(info.id().clone(), e.clone()))) info.public_endpoint.as_ref().map(|e| format!("{}", Node::new(info.id().clone(), e.clone())))

View File

@ -59,7 +59,6 @@
#![recursion_limit="128"] #![recursion_limit="128"]
extern crate ethcore_io as io; extern crate ethcore_io as io;
extern crate ethcore_util as util;
extern crate ethcore_bigint as bigint; extern crate ethcore_bigint as bigint;
extern crate ethcore_bytes; extern crate ethcore_bytes;
extern crate parking_lot; extern crate parking_lot;

View File

@ -59,10 +59,9 @@ impl NetworkService {
let io_service = IoService::<NetworkIoMessage>::start()?; let io_service = IoService::<NetworkIoMessage>::start()?;
let stats = Arc::new(NetworkStats::new()); let stats = Arc::new(NetworkStats::new());
let host_info = Host::client_version();
Ok(NetworkService { Ok(NetworkService {
io_service: io_service, io_service: io_service,
host_info: host_info, host_info: config.client_version.clone(),
stats: stats, stats: stats,
host: RwLock::new(None), host: RwLock::new(None),
config: config, config: config,

View File

@ -489,7 +489,7 @@ impl Session {
rlp.append_raw(&[PACKET_HELLO as u8], 0); rlp.append_raw(&[PACKET_HELLO as u8], 0);
rlp.begin_list(5) rlp.begin_list(5)
.append(&host.protocol_version) .append(&host.protocol_version)
.append(&host.client_version) .append(&host.client_version())
.append_list(&host.capabilities) .append_list(&host.capabilities)
.append(&host.local_endpoint.address.port()) .append(&host.local_endpoint.address.port())
.append(host.id()); .append(host.id());

View File

@ -1,8 +0,0 @@
[package]
name = "snappy"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
libc = "0.2.7"
rocksdb = { git = "https://github.com/paritytech/rust-rocksdb" }

View File

@ -1,164 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Snappy compression bindings.
extern crate libc;
use std::fmt;
use libc::{c_char, c_int, size_t};
const SNAPPY_OK: c_int = 0;
const SNAPPY_INVALID_INPUT: c_int = 1;
const SNAPPY_BUFFER_TOO_SMALL: c_int = 2;
#[link(name = "snappy", kind = "static")]
extern {
fn snappy_compress(
input: *const c_char,
input_len: size_t,
compressed: *mut c_char,
compressed_len: *mut size_t
) -> c_int;
fn snappy_max_compressed_length(source_len: size_t) -> size_t;
fn snappy_uncompress(
compressed: *const c_char,
compressed_len: size_t,
uncompressed: *mut c_char,
uncompressed_len: *mut size_t,
) -> c_int;
fn snappy_uncompressed_length(
compressed: *const c_char,
compressed_len: size_t,
result: *mut size_t,
) -> c_int;
fn snappy_validate_compressed_buffer(
compressed: *const c_char,
compressed_len: size_t,
) -> c_int;
}
/// Attempted to decompress an uncompressed buffer.
#[derive(Debug)]
pub struct InvalidInput;
impl std::error::Error for InvalidInput {
fn description(&self) -> &str {
"Attempted snappy decompression with invalid input"
}
}
impl fmt::Display for InvalidInput {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Attempted snappy decompression with invalid input")
}
}
/// The maximum compressed length given a size.
pub fn max_compressed_len(len: usize) -> usize {
unsafe { snappy_max_compressed_length(len as size_t) as usize }
}
/// How large the given data will be when decompressed.
pub fn decompressed_len(compressed: &[u8]) -> Result<usize, InvalidInput> {
let mut size: size_t = 0;
let len = compressed.len() as size_t;
let status = unsafe { snappy_uncompressed_length(compressed.as_ptr() as *const c_char, len, &mut size) };
if status == SNAPPY_INVALID_INPUT {
Err(InvalidInput)
} else {
Ok(size)
}
}
/// Compress a buffer using snappy.
pub fn compress(input: &[u8]) -> Vec<u8> {
let mut buf = Vec::new();
compress_into(input, &mut buf);
buf
}
/// Compress a buffer using snappy, writing the result into
/// the given output buffer, growing it if necessary.
/// Otherwise, returns the length of the compressed data.
pub fn compress_into(input: &[u8], output: &mut Vec<u8>) -> usize {
let mut len = max_compressed_len(input.len());
if output.len() < len {
output.resize(len, 0);
}
let status = unsafe {
snappy_compress(
input.as_ptr() as *const c_char,
input.len() as size_t,
output.as_mut_ptr() as *mut c_char,
&mut len as &mut size_t,
)
};
match status {
SNAPPY_OK => len,
SNAPPY_INVALID_INPUT => panic!("snappy compression has no concept of invalid input"),
SNAPPY_BUFFER_TOO_SMALL => panic!("buffer cannot be too small, the capacity was just ensured."),
_ => panic!("snappy returned unspecified status"),
}
}
/// Decompress a buffer using snappy. Will return an error if the buffer is not snappy-compressed.
pub fn decompress(input: &[u8]) -> Result<Vec<u8>, InvalidInput> {
let mut v = Vec::new();
decompress_into(input, &mut v).map(|_| v)
}
/// Decompress a buffer using snappy, writing the result into
/// the given output buffer, growing it if necessary.
/// Will error if the input buffer is not snappy-compressed.
/// Otherwise, returns the length of the decompressed data.
pub fn decompress_into(input: &[u8], output: &mut Vec<u8>) -> Result<usize, InvalidInput> {
let mut len = decompressed_len(input)?;
if output.len() < len {
output.resize(len, 0);
}
let status = unsafe {
snappy_uncompress(
input.as_ptr() as *const c_char,
input.len() as size_t,
output.as_mut_ptr() as *mut c_char,
&mut len as &mut size_t,
)
};
match status {
SNAPPY_OK => Ok(len as usize),
SNAPPY_INVALID_INPUT => Err(InvalidInput),
SNAPPY_BUFFER_TOO_SMALL => panic!("buffer cannot be too small, size was just set to large enough."),
_ => panic!("snappy returned unspecified status"),
}
}
/// Validate a compressed buffer. True if valid, false if not.
pub fn validate_compressed_buffer(input: &[u8]) -> bool {
let status = unsafe { snappy_validate_compressed_buffer(input.as_ptr() as *const c_char, input.len() as size_t )};
status == SNAPPY_OK
}

View File

@ -88,7 +88,6 @@
//! ``` //! ```
extern crate rustc_hex; extern crate rustc_hex;
extern crate rocksdb;
extern crate env_logger; extern crate env_logger;
extern crate secp256k1; extern crate secp256k1;
extern crate elastic_array; extern crate elastic_array;