diff --git a/Cargo.lock b/Cargo.lock index 7c2ad2c77..7f4d8ff11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,6 +3,7 @@ name = "parity" version = "1.5.0" dependencies = [ "ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)", "daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -42,7 +43,7 @@ dependencies = [ "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -58,6 +59,17 @@ name = "ansi_term" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "app_dirs" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayvec" version = "0.3.16" @@ -196,7 +208,7 @@ source = "git+https://github.com/ethcore/rust-ctrlc.git#f4927770f89eca80ec250911 dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -277,7 +289,7 @@ name = "ethash" version = "1.5.0" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.1.0", ] @@ -395,7 +407,7 @@ dependencies = [ "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.1 (git+https://github.com/ethcore/mio)", - "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -500,7 +512,7 @@ dependencies = [ "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.1 (git+https://github.com/ethcore/mio)", - "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -597,7 +609,7 @@ dependencies = [ "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", @@ -659,7 +671,7 @@ dependencies = [ "itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -688,7 +700,7 @@ dependencies = [ "ethkey 0.2.0", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -845,7 +857,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -864,7 +876,7 @@ version = "4.0.0" source = "git+https://github.com/ethcore/jsonrpc.git#33262d626a294a00c20435dec331058ba65e224a" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -925,7 +937,7 @@ name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1026,7 +1038,7 @@ dependencies = [ "nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1042,7 +1054,7 @@ dependencies = [ "nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1057,7 +1069,7 @@ dependencies = [ "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (git+https://github.com/carllerche/slab?rev=5476efcafb)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1073,7 +1085,7 @@ dependencies = [ "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1083,7 +1095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1094,7 +1106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1123,7 +1135,7 @@ dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1262,6 +1274,15 @@ name = "odds" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ole32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" version = "0.2.2" @@ -1307,7 +1328,7 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1323,7 +1344,7 @@ dependencies = [ "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1546,7 +1567,7 @@ dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1650,6 +1671,15 @@ dependencies = [ "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "shell32-sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "siphasher" version = "0.1.1" @@ -1785,7 +1815,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1794,7 +1824,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1829,7 +1859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1925,7 +1955,7 @@ name = "vecio" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1956,7 +1986,7 @@ dependencies = [ [[package]] name = "winapi" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1984,10 +2014,15 @@ name = "ws2_32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "xdg" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "xml-rs" version = "0.3.4" @@ -2018,6 +2053,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67077478f0a03952bed2e6786338d400d40c25e9836e08ad50af96607317fd03" "checksum ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1f46cd5b1d660c938e3f92dfe7a73d832b3281479363dd0cd9c1c2fbf60f7962" +"checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4" "checksum arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "16e3bdb2f54b3ace0285975d59a97cf8ed3855294b2b6bc651fcf22a9c352975" "checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a" "checksum aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df293303e8a52e1df7984ac1415e195f5fcbf51e4bb7bda54557861a3954a08" @@ -2104,10 +2140,11 @@ dependencies = [ "checksum num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "51fedae97a05f7353612fe017ab705a37e6db8f4d67c5c6fe739a9e70d6eed09" "checksum number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "084d05f4bf60621a9ac9bde941a410df548f4de9545f06e5ee9d3aef4b97cd77" "checksum odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b28c06e81b0f789122d415d6394b5fe849bde8067469f4c2980d3cdc10c78ec1" +"checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" "checksum parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98378dec0a185da2b7180308752f0bad73aaa949c3e0a3b0528d0e067945f7ab" "checksum parity-ui-precompiled 1.4.0 (git+https://github.com/ethcore/js-precompiled.git)" = "" -"checksum parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc5847584161f273e69edc63c1a86254a22f570a0b5dd87aa6f9773f6f7d125" +"checksum parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e1435e7a2a00dfebededd6c6bdbd54008001e94b4a2aadd6aef0dc4c56317621" "checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" "checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026" "checksum phf_codegen 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8af7ae7c3f75a502292b491e5cc0a1f69e3407744abe6e57e2a3b712bb82f01d" @@ -2145,6 +2182,7 @@ dependencies = [ "checksum serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f877e2781ed0a323295d1c9f0e26556117b5a11489fc47b1848dfb98b3173d21" "checksum serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e10f8a9d94b06cf5d3bef66475f04c8ff90950f1be7004c357ff9472ccbaebc" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" +"checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d" "checksum siphasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c44e42fa187b5a8782489cf7740cc27c3125806be2bf33563cf5e02e9533fcd" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" "checksum slab 0.2.0 (git+https://github.com/carllerche/slab?rev=5476efcafb)" = "" @@ -2185,10 +2223,11 @@ dependencies = [ "checksum vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56b639f935488eb40f06d17c3e3bcc3054f6f75d264e187b1107c8d1cba8d31c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum webpki 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "813503a5985585e0812d430cd1328ee322f47f66629c8ed4ecab939cf9e92f91" -"checksum winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfaaa8fbdaa618fa6914b59b2769d690dd7521920a18d84b42d254678dd5fd4" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum ws 0.5.3 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)" = "" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77b831a5ba77110f438f0ac5583aafeb087f70432998ba6b7dcb1d32185db453" "checksum xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "65e74b96bd3179209dc70a980da6df843dff09e46eee103a0376c0949257e3ef" "checksum xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "472a9d37c7c53ab2391161df5b89b1f3bf76dab6ab150d7941ecbdd832282082" "checksum zip 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "3ceb33a75b3d0608942302eed325b59d2c3ed777cc6c01627ae14e5697c6a31c" diff --git a/Cargo.toml b/Cargo.toml index bce959f61..a02bb2323 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ isatty = "0.1" toml = "0.2" serde = "0.8.0" serde_json = "0.8.0" +app_dirs = "1.1.1" hyper = { version = "0.9", default-features = false } ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" } fdlimit = "0.1" diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index a08dde33b..223978ca4 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -1,6 +1,6 @@ { "name": "Ethereum Classic", - "forkName": "classic", + "dataDir": "classic", "engine": { "Ethash": { "params": { diff --git a/ethcore/res/ethereum/expanse.json b/ethcore/res/ethereum/expanse.json index 8d580b6f5..d8cbd5b0c 100644 --- a/ethcore/res/ethereum/expanse.json +++ b/ethcore/res/ethereum/expanse.json @@ -1,6 +1,6 @@ { "name": "Expanse", - "forkName": "expanse", + "dataDir": "expanse", "engine": { "Ethash": { "params": { diff --git a/ethcore/res/ethereum/frontier.json b/ethcore/res/ethereum/frontier.json index 3a9dce456..91a8ae9e6 100644 --- a/ethcore/res/ethereum/frontier.json +++ b/ethcore/res/ethereum/frontier.json @@ -1,5 +1,6 @@ { "name": "Frontier/Homestead", + "dataDir": "ethereum", "engine": { "Ethash": { "params": { diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index d24e0ec0c..d21756250 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -1,5 +1,6 @@ { "name": "Morden", + "dataDir": "test", "engine": { "Ethash": { "params": { diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 62282801d..d388ce9a1 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -1,5 +1,6 @@ { "name": "Ropsten", + "dataDir": "test", "engine": { "Ethash": { "params": { diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 7a149c528..732d12a5b 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -81,9 +81,6 @@ impl ClientService { panic_handler.forward_from(&io_service); info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name())); - if spec.fork_name.is_some() { - warn!("Your chain is an alternative fork. {}", Colour::Red.bold().paint("TRANSACTIONS MAY BE REPLAYED ON THE MAINNET!")); - } let mut db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index f7a14ad82..bdcd5eee2 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -66,8 +66,8 @@ pub struct Spec { pub name: String, /// What engine are we using for this? pub engine: Arc, - /// The fork identifier for this chain. Only needed to distinguish two chains sharing the same genesis. - pub fork_name: Option, + /// Name of the subdir inside the main data dir to use for chain data and settings. + pub data_dir: String, /// Known nodes on the network in enode format. pub nodes: Vec, @@ -110,10 +110,10 @@ impl From for Spec { let GenericSeal(seal_rlp) = g.seal.into(); let params = CommonParams::from(s.params); Spec { - name: s.name.into(), + name: s.name.clone().into(), params: params.clone(), engine: Spec::engine(s.engine, params, builtins), - fork_name: s.fork_name.map(Into::into), + data_dir: s.data_dir.unwrap_or(s.name).into(), nodes: s.nodes.unwrap_or_else(Vec::new), parent_hash: g.parent_hash, transactions_root: g.transactions_root, diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index 22d6b36d8..fb289f11b 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -27,8 +27,8 @@ pub struct Spec { /// Spec name. pub name: String, /// Special fork name. - #[serde(rename="forkName")] - pub fork_name: Option, + #[serde(rename="dataDir")] + pub data_dir: Option, /// Engine. pub engine: Engine, /// Spec params. @@ -57,6 +57,7 @@ mod tests { fn spec_deserialization() { let s = r#"{ "name": "Morden", + "dataDir": "morden", "engine": { "Ethash": { "params": { diff --git a/parity/account.rs b/parity/account.rs index e790eb596..15e712413 100644 --- a/parity/account.rs +++ b/parity/account.rs @@ -14,23 +14,32 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::path::PathBuf; use ethcore::ethstore::{EthStore, SecretStore, import_accounts, read_geth_accounts}; use ethcore::ethstore::dir::DiskDirectory; use ethcore::account_provider::AccountProvider; use helpers::{password_prompt, password_from_file}; +use params::SpecType; #[derive(Debug, PartialEq)] pub enum AccountCmd { New(NewAccount), - List(String), + List(ListAccounts), Import(ImportAccounts), ImportFromGeth(ImportFromGethAccounts) } +#[derive(Debug, PartialEq)] +pub struct ListAccounts { + pub path: String, + pub spec: SpecType, +} + #[derive(Debug, PartialEq)] pub struct NewAccount { pub iterations: u32, pub path: String, + pub spec: SpecType, pub password_file: Option, } @@ -38,6 +47,7 @@ pub struct NewAccount { pub struct ImportAccounts { pub from: Vec, pub to: String, + pub spec: SpecType, } /// Parameters for geth accounts' import @@ -47,18 +57,22 @@ pub struct ImportFromGethAccounts { pub testnet: bool, /// directory to import accounts to pub to: String, + pub spec: SpecType, } pub fn execute(cmd: AccountCmd) -> Result { match cmd { AccountCmd::New(new_cmd) => new(new_cmd), - AccountCmd::List(path) => list(path), + AccountCmd::List(list_cmd) => list(list_cmd), AccountCmd::Import(import_cmd) => import(import_cmd), AccountCmd::ImportFromGeth(import_geth_cmd) => import_geth(import_geth_cmd) } } -fn keys_dir(path: String) -> Result { +fn keys_dir(path: String, spec: SpecType) -> Result { + let spec = try!(spec.spec()); + let mut path = PathBuf::from(&path); + path.push(spec.data_dir); DiskDirectory::create(path).map_err(|e| format!("Could not open keys directory: {}", e)) } @@ -75,15 +89,15 @@ fn new(n: NewAccount) -> Result { None => try!(password_prompt()), }; - let dir = Box::new(try!(keys_dir(n.path))); + let dir = Box::new(try!(keys_dir(n.path, n.spec))); let secret_store = Box::new(try!(secret_store(dir, Some(n.iterations)))); let acc_provider = AccountProvider::new(secret_store); let new_account = try!(acc_provider.new_account(&password).map_err(|e| format!("Could not create new account: {}", e))); Ok(format!("{:?}", new_account)) } -fn list(path: String) -> Result { - let dir = Box::new(try!(keys_dir(path))); +fn list(list_cmd: ListAccounts) -> Result { + let dir = Box::new(try!(keys_dir(list_cmd.path, list_cmd.spec))); let secret_store = Box::new(try!(secret_store(dir, None))); let acc_provider = AccountProvider::new(secret_store); let accounts = acc_provider.accounts(); @@ -96,7 +110,7 @@ fn list(path: String) -> Result { } fn import(i: ImportAccounts) -> Result { - let to = try!(keys_dir(i.to)); + let to = try!(keys_dir(i.to, i.spec)); let mut imported = 0; for path in &i.from { let from = DiskDirectory::at(path); @@ -109,7 +123,7 @@ fn import_geth(i: ImportFromGethAccounts) -> Result { use std::io::ErrorKind; use ethcore::ethstore::Error; - let dir = Box::new(try!(keys_dir(i.to))); + let dir = Box::new(try!(keys_dir(i.to, i.spec))); let secret_store = Box::new(try!(secret_store(dir, None))); let geth_accounts = read_geth_accounts(i.testnet); match secret_store.import_geth_accounts(geth_accounts, i.testnet) { diff --git a/parity/blockchain.rs b/parity/blockchain.rs index 10fe1d32e..94e9e7709 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -64,11 +64,19 @@ impl FromStr for DataFormat { #[derive(Debug, PartialEq)] pub enum BlockchainCmd { + Kill(KillBlockchain), Import(ImportBlockchain), Export(ExportBlockchain), ExportState(ExportState), } +#[derive(Debug, PartialEq)] +pub struct KillBlockchain { + pub spec: SpecType, + pub dirs: Directories, + pub pruning: Pruning, +} + #[derive(Debug, PartialEq)] pub struct ImportBlockchain { pub spec: SpecType, @@ -128,6 +136,7 @@ pub struct ExportState { pub fn execute(cmd: BlockchainCmd) -> Result { match cmd { + BlockchainCmd::Kill(kill_cmd) => kill_db(kill_cmd), BlockchainCmd::Import(import_cmd) => execute_import(import_cmd), BlockchainCmd::Export(export_cmd) => execute_export(export_cmd), BlockchainCmd::ExportState(export_cmd) => execute_export_state(export_cmd), @@ -140,9 +149,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result { // Setup panic handler let panic_handler = PanicHandler::new_in_arc(); - // create dirs used by parity - try!(cmd.dirs.create_dirs(false, false)); - // load spec file let spec = try!(cmd.spec.spec()); @@ -150,7 +156,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result { let genesis_hash = spec.genesis_header().hash(); // database paths - let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone()); + let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir.clone()); // user defaults path let user_defaults_path = db_dirs.user_defaults_path(); @@ -174,7 +180,10 @@ fn execute_import(cmd: ImportBlockchain) -> Result { let snapshot_path = db_dirs.snapshot_path(); // execute upgrades - try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path()))); + try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path()))); + + // create dirs used by parity + try!(cmd.dirs.create_dirs(false, false)); // prepare client config let mut client_config = to_client_config( @@ -311,9 +320,6 @@ fn start_client( wal: bool, cache_config: CacheConfig) -> Result { - // create dirs used by parity - try!(dirs.create_dirs(false, false)); - // load spec file let spec = try!(spec.spec()); @@ -321,7 +327,7 @@ fn start_client( let genesis_hash = spec.genesis_header().hash(); // database paths - let db_dirs = dirs.database(genesis_hash, spec.fork_name.clone()); + let db_dirs = dirs.database(genesis_hash, None, spec.data_dir.clone()); // user defaults path let user_defaults_path = db_dirs.user_defaults_path(); @@ -345,7 +351,10 @@ fn start_client( let snapshot_path = db_dirs.snapshot_path(); // execute upgrades - try!(execute_upgrades(&db_dirs, algorithm, compaction.compaction_profile(db_dirs.fork_path().as_path()))); + try!(execute_upgrades(&db_dirs, algorithm, compaction.compaction_profile(db_dirs.db_root_path().as_path()))); + + // create dirs used by parity + try!(dirs.create_dirs(false, false)); // prepare client config let client_config = to_client_config(&cache_config, Mode::Active, tracing, fat_db, compaction, wal, VMType::default(), "".into(), algorithm, pruning_history, true); @@ -473,6 +482,18 @@ fn execute_export_state(cmd: ExportState) -> Result { Ok("Export completed.".into()) } +pub fn kill_db(cmd: KillBlockchain) -> Result { + let spec = try!(cmd.spec.spec()); + let genesis_hash = spec.genesis_header().hash(); + let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir); + let user_defaults_path = db_dirs.user_defaults_path(); + let user_defaults = try!(UserDefaults::load(&user_defaults_path)); + let algorithm = cmd.pruning.to_algorithm(&user_defaults); + let dir = db_dirs.db_path(algorithm); + try!(fs::remove_dir_all(&dir).map_err(|e| format!("Error removing database: {:?}", e))); + Ok("Database deleted.".to_owned()) +} + #[cfg(test)] mod test { use super::DataFormat; diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 39e4d5867..0b2cbad28 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -16,6 +16,7 @@ #[macro_use] mod usage; +use dir::default_data_path; usage! { { @@ -36,6 +37,8 @@ usage! { cmd_ui: bool, cmd_tools: bool, cmd_hash: bool, + cmd_kill: bool, + cmd_db: bool, // Arguments arg_pid_file: String, @@ -80,8 +83,8 @@ usage! { flag_mode_timeout: u64 = 300u64, or |c: &Config| otry!(c.parity).mode_timeout.clone(), flag_mode_alarm: u64 = 3600u64, or |c: &Config| otry!(c.parity).mode_alarm.clone(), flag_chain: String = "homestead", or |c: &Config| otry!(c.parity).chain.clone(), - flag_db_path: String = "$HOME/.parity", or |c: &Config| otry!(c.parity).db_path.clone(), - flag_keys_path: String = "$HOME/.parity/keys", or |c: &Config| otry!(c.parity).keys_path.clone(), + flag_db_path: String = default_data_path(), or |c: &Config| otry!(c.parity).db_path.clone(), + flag_keys_path: String = "$DATA/keys", or |c: &Config| otry!(c.parity).keys_path.clone(), flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(), // -- Account Options @@ -100,7 +103,7 @@ usage! { or |c: &Config| otry!(c.ui).port.clone(), flag_ui_interface: String = "local", or |c: &Config| otry!(c.ui).interface.clone(), - flag_ui_path: String = "$HOME/.parity/signer", + flag_ui_path: String = "$DATA/signer", or |c: &Config| otry!(c.ui).path.clone(), // NOTE [todr] For security reasons don't put this to config files flag_ui_no_validation: bool = false, or |_| None, @@ -156,7 +159,7 @@ usage! { // IPC flag_no_ipc: bool = false, or |c: &Config| otry!(c.ipc).disable.clone(), - flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc", + flag_ipc_path: String = "$DATA/jsonrpc.ipc", or |c: &Config| otry!(c.ipc).path.clone(), flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc", or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")), @@ -170,7 +173,7 @@ usage! { or |c: &Config| otry!(c.dapps).interface.clone(), flag_dapps_hosts: String = "none", or |c: &Config| otry!(c.dapps).hosts.clone().map(|vec| vec.join(",")), - flag_dapps_path: String = "$HOME/.parity/dapps", + flag_dapps_path: String = "$DATA/dapps", or |c: &Config| otry!(c.dapps).path.clone(), flag_dapps_user: Option = None, or |c: &Config| otry!(c.dapps).user.clone().map(Some), @@ -271,7 +274,7 @@ usage! { or |c: &Config| otry!(c.vm).jit.clone(), // -- Miscellaneous Options - flag_config: String = "$HOME/.parity/config.toml", or |_| None, + flag_config: String = "$DATA/config.toml", or |_| None, flag_logging: Option = None, or |c: &Config| otry!(c.misc).logging.clone().map(Some), flag_log_file: Option = None, @@ -512,6 +515,8 @@ mod tests { cmd_ui: false, cmd_tools: false, cmd_hash: false, + cmd_db: false, + cmd_kill: false, // Arguments arg_pid_file: "".into(), @@ -665,7 +670,7 @@ mod tests { // -- Miscellaneous Options flag_version: false, - flag_config: "$HOME/.parity/config.toml".into(), + flag_config: "$DATA/config.toml".into(), flag_logging: Some("own_tx=trace".into()), flag_log_file: Some("/var/log/parity.log".into()), flag_no_color: false, diff --git a/parity/cli/usage.rs b/parity/cli/usage.rs index cd94e0299..8c8b54c87 100644 --- a/parity/cli/usage.rs +++ b/parity/cli/usage.rs @@ -145,7 +145,7 @@ macro_rules! usage { } let config_file = raw_args.flag_config.clone().unwrap_or_else(|| raw_args.clone().into_args(Config::default()).flag_config); - let config_file = replace_home(&config_file); + let config_file = replace_home("", &config_file); let config = match (fs::File::open(&config_file), raw_args.flag_config.is_some()) { // Load config file (Ok(mut file), _) => { diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index 1e99c76fe..13f1ed491 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -15,6 +15,7 @@ Usage: parity snapshot [options] parity restore [ ] [options] parity tools hash + parity db kill [options] Operating Options: --mode MODE Set the operating mode. MODE can be one of: @@ -282,10 +283,8 @@ Import/Export Options: (default: {flag_format:?} = Import: auto, Export: binary) --no-seal-check Skip block seal check. (default: {flag_no_seal_check}) --at BLOCK Export state at the given block, which may be an - index, hash, or 'latest'. Note that taking snapshots at - non-recent blocks will only work with --pruning archive - (default: {flag_at}) - --no-storage Don't export account storge. (default: {flag_no_storage}) + index, hash, or 'latest'. (default: {flag_at}) + --no-storage Don't export account storage. (default: {flag_no_storage}) --no-code Don't export account code. (default: {flag_no_code}) --min-balance WEI Don't export accounts with balance less than specified. (default: {flag_min_balance:?}) diff --git a/parity/configuration.rs b/parity/configuration.rs index 59333c883..9afbb30ee 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -38,9 +38,9 @@ use dir::Directories; use dapps::Configuration as DappsConfiguration; use signer::{Configuration as SignerConfiguration}; use run::RunCmd; -use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState, DataFormat}; +use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockchain, ExportState, DataFormat}; use presale::ImportWallet; -use account::{AccountCmd, NewAccount, ImportAccounts, ImportFromGethAccounts}; +use account::{AccountCmd, NewAccount, ListAccounts, ImportAccounts, ImportFromGethAccounts}; use snapshot::{self, SnapshotCommand}; #[derive(Debug, PartialEq)] @@ -107,20 +107,32 @@ impl Configuration { Cmd::SignerToken(signer_conf) } else if self.args.cmd_tools && self.args.cmd_hash { Cmd::Hash(self.args.arg_file) + } else if self.args.cmd_db && self.args.cmd_kill { + Cmd::Blockchain(BlockchainCmd::Kill(KillBlockchain { + spec: spec, + dirs: dirs, + pruning: pruning, + })) } else if self.args.cmd_account { let account_cmd = if self.args.cmd_new { let new_acc = NewAccount { iterations: self.args.flag_keys_iterations, path: dirs.keys, + spec: spec, password_file: self.args.flag_password.first().cloned(), }; AccountCmd::New(new_acc) } else if self.args.cmd_list { - AccountCmd::List(dirs.keys) + let list_acc = ListAccounts { + path: dirs.keys, + spec: spec, + }; + AccountCmd::List(list_acc) } else if self.args.cmd_import { let import_acc = ImportAccounts { from: self.args.arg_path.clone(), to: dirs.keys, + spec: spec, }; AccountCmd::Import(import_acc) } else { @@ -130,6 +142,7 @@ impl Configuration { } else if self.args.flag_import_geth_keys { let account_cmd = AccountCmd::ImportFromGeth( ImportFromGethAccounts { + spec: spec, to: dirs.keys, testnet: self.args.flag_testnet } @@ -139,6 +152,7 @@ impl Configuration { let presale_cmd = ImportWallet { iterations: self.args.flag_keys_iterations, path: dirs.keys, + spec: spec, wallet_path: self.args.arg_path.first().unwrap().clone(), password_file: self.args.flag_password.first().cloned(), }; @@ -530,7 +544,7 @@ impl Configuration { ret.snapshot_peers = self.snapshot_peers(); ret.allow_ips = try!(self.allow_ips()); ret.max_pending_peers = self.max_pending_peers(); - let mut net_path = PathBuf::from(self.directories().db); + let mut net_path = PathBuf::from(self.directories().data); net_path.push("network"); ret.config_path = Some(net_path.to_str().unwrap().to_owned()); ret.reserved_nodes = try!(self.init_reserved_nodes()); @@ -624,18 +638,11 @@ impl Configuration { fn directories(&self) -> Directories { use util::path; - let db_path = replace_home(self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path)); + let data_path = replace_home("", self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path)); - let keys_path = replace_home( - if self.args.flag_testnet { - "$HOME/.parity/testnet_keys" - } else { - &self.args.flag_keys_path - } - ); - - let dapps_path = replace_home(&self.args.flag_dapps_path); - let ui_path = replace_home(&self.args.flag_ui_path); + let keys_path = replace_home(&data_path, &self.args.flag_keys_path); + let dapps_path = replace_home(&data_path, &self.args.flag_dapps_path); + let ui_path = replace_home(&data_path, &self.args.flag_ui_path); if self.args.flag_geth && !cfg!(windows) { let geth_root = if self.args.flag_testnet { path::ethereum::test() } else { path::ethereum::default() }; @@ -644,7 +651,7 @@ impl Configuration { } if cfg!(feature = "ipc") && !cfg!(feature = "windows") { - let mut path_buf = PathBuf::from(db_path.clone()); + let mut path_buf = PathBuf::from(data_path.clone()); path_buf.push("ipc"); let ipc_path = path_buf.to_str().unwrap(); ::std::fs::create_dir_all(ipc_path).unwrap_or_else( @@ -654,7 +661,7 @@ impl Configuration { Directories { keys: keys_path, - db: db_path, + data: data_path, dapps: dapps_path, signer: ui_path, } @@ -664,7 +671,7 @@ impl Configuration { if self.args.flag_geth { geth_ipc_path(self.args.flag_testnet) } else { - parity_ipc_path(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) + parity_ipc_path(&self.directories().data, &self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) } } @@ -732,12 +739,14 @@ mod tests { use ethcore_rpc::NetworkSettings; use ethcore::client::{VMType, BlockId}; use ethcore::miner::{MinerOptions, PrioritizationStrategy}; - use helpers::{replace_home, default_network_config}; + use helpers::{default_network_config}; use run::RunCmd; + use dir::Directories; use signer::{Configuration as SignerConfiguration}; use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat, ExportState}; use presale::ImportWallet; - use account::{AccountCmd, NewAccount, ImportAccounts}; + use params::SpecType; + use account::{AccountCmd, NewAccount, ImportAccounts, ListAccounts}; use devtools::{RandomTempPath}; use std::io::Write; use std::fs::{File, create_dir}; @@ -764,8 +773,9 @@ mod tests { let conf = parse(&args); assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::New(NewAccount { iterations: 10240, - path: replace_home("$HOME/.parity/keys"), + path: Directories::default().keys, password_file: None, + spec: SpecType::default(), }))); } @@ -774,7 +784,10 @@ mod tests { let args = vec!["parity", "account", "list"]; let conf = parse(&args); assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account( - AccountCmd::List(replace_home("$HOME/.parity/keys")), + AccountCmd::List(ListAccounts { + path: Directories::default().keys, + spec: SpecType::default(), + }) )); } @@ -784,7 +797,8 @@ mod tests { let conf = parse(&args); assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::Import(ImportAccounts { from: vec!["my_dir".into(), "another_dir".into()], - to: replace_home("$HOME/.parity/keys"), + to: Directories::default().keys, + spec: SpecType::default(), }))); } @@ -794,9 +808,10 @@ mod tests { let conf = parse(&args); assert_eq!(conf.into_command().unwrap().cmd, Cmd::ImportPresaleWallet(ImportWallet { iterations: 10240, - path: replace_home("$HOME/.parity/keys"), + path: Directories::default().keys, wallet_path: "my_wallet.json".into(), password_file: Some("pwd".into()), + spec: SpecType::default(), })); } @@ -895,7 +910,7 @@ mod tests { fn test_command_signer_new_token() { let args = vec!["parity", "signer", "new-token"]; let conf = parse(&args); - let expected = replace_home("$HOME/.parity/signer"); + let expected = Directories::default().signer; assert_eq!(conf.into_command().unwrap().cmd, Cmd::SignerToken(SignerConfiguration { enabled: true, signer_path: expected, diff --git a/parity/dapps.rs b/parity/dapps.rs index 4eed929ca..e54638ed2 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -20,6 +20,7 @@ use rpc_apis; use ethcore::client::Client; use ethsync::SyncProvider; use helpers::replace_home; +use dir::default_data_path; #[derive(Debug, PartialEq, Clone)] pub struct Configuration { @@ -34,6 +35,7 @@ pub struct Configuration { impl Default for Configuration { fn default() -> Self { + let data_dir = default_data_path(); Configuration { enabled: true, interface: "127.0.0.1".into(), @@ -41,7 +43,7 @@ impl Default for Configuration { hosts: Some(Vec::new()), user: None, pass: None, - dapps_path: replace_home("$HOME/.parity/dapps"), + dapps_path: replace_home(&data_dir, "$DATA/dapps"), } } } diff --git a/parity/dir.rs b/parity/dir.rs index 0a49cd528..f9c2f30c9 100644 --- a/parity/dir.rs +++ b/parity/dir.rs @@ -19,6 +19,7 @@ use std::path::{PathBuf, Path}; use util::{H64, H256}; use util::journaldb::Algorithm; use helpers::replace_home; +use app_dirs::{AppInfo, get_app_root, AppDataType}; // this const is irrelevent cause we do have migrations now, // but we still use it for backwards compatibility @@ -26,7 +27,7 @@ const LEGACY_CLIENT_DB_VER_STR: &'static str = "5.3"; #[derive(Debug, PartialEq)] pub struct Directories { - pub db: String, + pub data: String, pub keys: String, pub signer: String, pub dapps: String, @@ -34,18 +35,19 @@ pub struct Directories { impl Default for Directories { fn default() -> Self { + let data_dir = default_data_path(); Directories { - db: replace_home("$HOME/.parity"), - keys: replace_home("$HOME/.parity/keys"), - signer: replace_home("$HOME/.parity/signer"), - dapps: replace_home("$HOME/.parity/dapps"), + data: replace_home(&data_dir, "$DATA"), + keys: replace_home(&data_dir, "$DATA/keys"), + signer: replace_home(&data_dir, "$DATA/signer"), + dapps: replace_home(&data_dir, "$DATA/dapps"), } } } impl Directories { pub fn create_dirs(&self, dapps_enabled: bool, signer_enabled: bool) -> Result<(), String> { - try!(fs::create_dir_all(&self.db).map_err(|e| e.to_string())); + try!(fs::create_dir_all(&self.data).map_err(|e| e.to_string())); try!(fs::create_dir_all(&self.keys).map_err(|e| e.to_string())); if signer_enabled { try!(fs::create_dir_all(&self.signer).map_err(|e| e.to_string())); @@ -57,20 +59,38 @@ impl Directories { } /// Database paths. - pub fn database(&self, genesis_hash: H256, fork_name: Option) -> DatabaseDirectories { + pub fn database(&self, genesis_hash: H256, fork_name: Option, spec_name: String) -> DatabaseDirectories { DatabaseDirectories { - path: self.db.clone(), + path: self.data.clone(), genesis_hash: genesis_hash, fork_name: fork_name, + spec_name: spec_name, } } /// Get the ipc sockets path pub fn ipc_path(&self) -> PathBuf { - let mut dir = Path::new(&self.db).to_path_buf(); + let mut dir = Path::new(&self.data).to_path_buf(); dir.push("ipc"); dir } + + // TODO: remove in 1.7 + pub fn legacy_keys_path(&self, testnet: bool) -> PathBuf { + let mut dir = Path::new(&self.data).to_path_buf(); + if testnet { + dir.push("testnet_keys"); + } else { + dir.push("keys"); + } + dir + } + + pub fn keys_path(&self, spec_name: &str) -> PathBuf { + let mut dir = PathBuf::from(&self.keys); + dir.push(spec_name); + dir + } } #[derive(Debug, PartialEq)] @@ -78,52 +98,103 @@ pub struct DatabaseDirectories { pub path: String, pub genesis_hash: H256, pub fork_name: Option, + pub spec_name: String, } impl DatabaseDirectories { /// Base DB directory for the given fork. - pub fn fork_path(&self) -> PathBuf { + // TODO: remove in 1.7 + pub fn legacy_fork_path(&self) -> PathBuf { let mut dir = Path::new(&self.path).to_path_buf(); dir.push(format!("{:?}{}", H64::from(self.genesis_hash), self.fork_name.as_ref().map(|f| format!("-{}", f)).unwrap_or_default())); dir } - /// Get the root path for database - pub fn version_path(&self, pruning: Algorithm) -> PathBuf { - let mut dir = self.fork_path(); - dir.push(format!("v{}-sec-{}", LEGACY_CLIENT_DB_VER_STR, pruning.as_internal_name_str())); + pub fn spec_root_path(&self) -> PathBuf { + let mut dir = Path::new(&self.path).to_path_buf(); + dir.push("chains"); + dir.push(&self.spec_name); dir } - /// Get the path for the databases given the genesis_hash and information on the databases. pub fn client_path(&self, pruning: Algorithm) -> PathBuf { - let mut dir = self.version_path(pruning); + let mut dir = self.db_root_path(); + dir.push(pruning.as_internal_name_str()); dir.push("db"); dir } + pub fn db_root_path(&self) -> PathBuf { + let mut dir = self.spec_root_path(); + dir.push("db"); + dir.push(H64::from(self.genesis_hash).hex()); + dir + } + + pub fn db_path(&self, pruning: Algorithm) -> PathBuf { + let mut dir = self.db_root_path(); + dir.push(pruning.as_internal_name_str()); + dir + } + + /// Get the root path for database + // TODO: remove in 1.7 + pub fn legacy_version_path(&self, pruning: Algorithm) -> PathBuf { + let mut dir = self.legacy_fork_path(); + dir.push(format!("v{}-sec-{}", LEGACY_CLIENT_DB_VER_STR, pruning.as_internal_name_str())); + dir + } + /// Get user defaults path + // TODO: remove in 1.7 + pub fn legacy_user_defaults_path(&self) -> PathBuf { + let mut dir = self.legacy_fork_path(); + dir.push("user_defaults"); + dir + } + + /// Get user defaults path + // TODO: remove in 1.7 + pub fn legacy_snapshot_path(&self) -> PathBuf { + let mut dir = self.legacy_fork_path(); + dir.push("snapshot"); + dir + } + + /// Get user defaults path + // TODO: remove in 1.7 + pub fn legacy_network_path(&self) -> PathBuf { + let mut dir = self.legacy_fork_path(); + dir.push("network"); + dir + } + pub fn user_defaults_path(&self) -> PathBuf { - let mut dir = self.fork_path(); + let mut dir = self.spec_root_path(); dir.push("user_defaults"); dir } /// Get the path for the snapshot directory given the genesis hash and fork name. pub fn snapshot_path(&self) -> PathBuf { - let mut dir = self.fork_path(); + let mut dir = self.db_root_path(); dir.push("snapshot"); dir } /// Get the path for the network directory. pub fn network_path(&self) -> PathBuf { - let mut dir = self.fork_path(); + let mut dir = self.spec_root_path(); dir.push("network"); dir } } +pub fn default_data_path() -> String { + let app_info = AppInfo { name: "parity", author: "parity" }; + get_app_root(AppDataType::UserData, &app_info).map(|p| p.to_string_lossy().into_owned()).unwrap_or_else(|_| "$HOME/.parity".to_owned()) +} + #[cfg(test)] mod tests { use super::Directories; @@ -131,11 +202,12 @@ mod tests { #[test] fn test_default_directories() { + let data_dir = super::default_data_path(); let expected = Directories { - db: replace_home("$HOME/.parity"), - keys: replace_home("$HOME/.parity/keys"), - signer: replace_home("$HOME/.parity/signer"), - dapps: replace_home("$HOME/.parity/dapps"), + data: replace_home(&data_dir, "$DATA"), + keys: replace_home(&data_dir, "$DATA/keys"), + signer: replace_home(&data_dir, "$DATA/signer"), + dapps: replace_home(&data_dir, "$DATA/dapps"), }; assert_eq!(expected, Directories::default()); } diff --git a/parity/helpers.rs b/parity/helpers.rs index d1b1e4027..f359d617f 100644 --- a/parity/helpers.rs +++ b/parity/helpers.rs @@ -24,7 +24,7 @@ use ethcore::client::{Mode, BlockId, VMType, DatabaseCompactionProfile, ClientCo use ethcore::miner::{PendingSet, GasLimit, PrioritizationStrategy}; use cache::CacheConfig; use dir::DatabaseDirectories; -use upgrade::upgrade; +use upgrade::{upgrade, upgrade_data_paths}; use migration::migrate; use ethsync::is_valid_node_url; @@ -132,9 +132,10 @@ pub fn to_price(s: &str) -> Result { } /// Replaces `$HOME` str with home directory path. -pub fn replace_home(arg: &str) -> String { +pub fn replace_home(base: &str, arg: &str) -> String { // the $HOME directory on mac os should be `~/Library` or `~/Library/Application Support` let r = arg.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()); + let r = r.replace("$DATA", base ); r.replace("/", &::std::path::MAIN_SEPARATOR.to_string() ) } @@ -159,13 +160,13 @@ pub fn geth_ipc_path(testnet: bool) -> String { } /// Formats and returns parity ipc path. -pub fn parity_ipc_path(s: &str) -> String { +pub fn parity_ipc_path(base: &str, s: &str) -> String { // Windows path should not be hardcoded here. if cfg!(windows) { return r"\\.\pipe\parity.jsonrpc".to_owned(); } - replace_home(s) + replace_home(base, s) } /// Validates and formats bootnodes option. @@ -187,7 +188,7 @@ pub fn to_bootnodes(bootnodes: &Option) -> Result, String> { pub fn default_network_config() -> ::ethsync::NetworkConfiguration { use ethsync::{NetworkConfiguration, AllowIP}; NetworkConfiguration { - config_path: Some(replace_home("$HOME/.parity/network")), + config_path: Some(replace_home(&::dir::default_data_path(), "$DATA/network")), net_config_path: None, listen_address: Some("0.0.0.0:30303".into()), public_address: None, @@ -261,6 +262,8 @@ pub fn execute_upgrades( compaction_profile: CompactionProfile ) -> Result<(), String> { + upgrade_data_paths(dirs, pruning); + match upgrade(Some(&dirs.path)) { Ok(upgrades_applied) if upgrades_applied > 0 => { debug!("Executed {} upgrade scripts - ok", upgrades_applied); @@ -271,7 +274,7 @@ pub fn execute_upgrades( _ => {}, } - let client_path = dirs.version_path(pruning); + let client_path = dirs.db_path(pruning); migrate(&client_path, pruning, compaction_profile).map_err(|e| format!("{}", e)) } diff --git a/parity/main.rs b/parity/main.rs index 8c1f88e1e..3db6847a1 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -54,6 +54,7 @@ extern crate ansi_term; extern crate regex; extern crate isatty; extern crate toml; +extern crate app_dirs; #[macro_use] extern crate ethcore_util as util; diff --git a/parity/params.rs b/parity/params.rs index aaaa12085..9f549acee 100644 --- a/parity/params.rs +++ b/parity/params.rs @@ -76,6 +76,14 @@ impl SpecType { } } } + + pub fn legacy_fork_name(&self) -> Option { + match *self { + SpecType::Classic => Some("classic".to_owned()), + SpecType::Expanse => Some("expanse".to_owned()), + _ => None, + } + } } #[derive(Debug, PartialEq)] diff --git a/parity/presale.rs b/parity/presale.rs index 7754e7e18..d8e19a96a 100644 --- a/parity/presale.rs +++ b/parity/presale.rs @@ -18,11 +18,13 @@ use ethcore::ethstore::{PresaleWallet, EthStore}; use ethcore::ethstore::dir::DiskDirectory; use ethcore::account_provider::AccountProvider; use helpers::{password_prompt, password_from_file}; +use params::SpecType; #[derive(Debug, PartialEq)] pub struct ImportWallet { pub iterations: u32, pub path: String, + pub spec: SpecType, pub wallet_path: String, pub password_file: Option, } diff --git a/parity/rpc.rs b/parity/rpc.rs index 2551b0736..b0668bf57 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -23,6 +23,7 @@ use ethcore_rpc::{RpcServerError, RpcServer as Server, IpcServerError}; use rpc_apis; use rpc_apis::ApiSet; use helpers::parity_ipc_path; +use dir::default_data_path; pub use ethcore_rpc::{IpcServer, Server as HttpServer}; @@ -58,9 +59,10 @@ pub struct IpcConfiguration { impl Default for IpcConfiguration { fn default() -> Self { + let data_dir = default_data_path(); IpcConfiguration { enabled: true, - socket_addr: parity_ipc_path("$HOME/.parity/jsonrpc.ipc"), + socket_addr: parity_ipc_path(&data_dir, "$DATA/jsonrpc.ipc"), apis: ApiSet::IpcContext, } } diff --git a/parity/run.rs b/parity/run.rs index 346567842..140c2050c 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -41,6 +41,7 @@ use params::{ tracing_switch_to_bool, fatdb_switch_to_bool, mode_switch_to_bool }; use helpers::{to_client_config, execute_upgrades, passwords_from_files}; +use upgrade::upgrade_key_location; use dir::Directories; use cache::CacheConfig; use user_defaults::UserDefaults; @@ -129,9 +130,6 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { // increase max number of open files raise_fd_limit(); - // create dirs used by parity - try!(cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.signer_conf.enabled)); - // load spec let spec = try!(cmd.spec.spec()); @@ -139,7 +137,7 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { let genesis_hash = spec.genesis_header().hash(); // database paths - let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone()); + let db_dirs = cmd.dirs.database(genesis_hash, cmd.spec.legacy_fork_name(), spec.data_dir.clone()); // user defaults path let user_defaults_path = db_dirs.user_defaults_path(); @@ -166,7 +164,10 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { let snapshot_path = db_dirs.snapshot_path(); // execute upgrades - try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path()))); + try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.db_root_path().as_path()))); + + // create dirs used by parity + try!(cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.signer_conf.enabled)); // run in daemon mode if let Some(pid_file) = cmd.daemon { @@ -217,7 +218,7 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result<(), String> { let passwords = try!(passwords_from_files(&cmd.acc_conf.password_files)); // prepare account provider - let account_provider = Arc::new(try!(prepare_account_provider(&cmd.dirs, cmd.acc_conf, &passwords))); + let account_provider = Arc::new(try!(prepare_account_provider(&cmd.dirs, &spec.data_dir, cmd.acc_conf, &passwords))); // let the Engine access the accounts spec.engine.register_account_provider(account_provider.clone()); @@ -449,11 +450,13 @@ fn daemonize(_pid_file: String) -> Result<(), String> { Err("daemon is no supported on windows".into()) } -fn prepare_account_provider(dirs: &Directories, cfg: AccountsConfig, passwords: &[String]) -> Result { +fn prepare_account_provider(dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[String]) -> Result { use ethcore::ethstore::EthStore; use ethcore::ethstore::dir::DiskDirectory; - let dir = Box::new(try!(DiskDirectory::create(dirs.keys.clone()).map_err(|e| format!("Could not open keys directory: {}", e)))); + let path = dirs.keys_path(data_dir); + upgrade_key_location(&dirs.legacy_keys_path(cfg.testnet), &path); + let dir = Box::new(try!(DiskDirectory::create(&path).map_err(|e| format!("Could not open keys directory: {}", e)))); let account_service = AccountProvider::new(Box::new( try!(EthStore::open_with_iterations(dir, cfg.iterations).map_err(|e| format!("Could not open keys directory: {}", e))) )); diff --git a/parity/signer.rs b/parity/signer.rs index d247453f1..4d282888e 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -23,6 +23,7 @@ use util::path::restrict_permissions_owner; use rpc_apis; use ethcore_signer as signer; use helpers::replace_home; +use dir::default_data_path; pub use ethcore_signer::Server as SignerServer; const CODES_FILENAME: &'static str = "authcodes"; @@ -38,11 +39,12 @@ pub struct Configuration { impl Default for Configuration { fn default() -> Self { + let data_dir = default_data_path(); Configuration { enabled: true, port: 8180, interface: "127.0.0.1".into(), - signer_path: replace_home("$HOME/.parity/signer"), + signer_path: replace_home(&data_dir, "$DATA/signer"), skip_origin_validation: false, } } diff --git a/parity/snapshot.rs b/parity/snapshot.rs index 2963e9b84..d71ffe924 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -143,7 +143,7 @@ impl SnapshotCommand { let genesis_hash = spec.genesis_header().hash(); // database paths - let db_dirs = self.dirs.database(genesis_hash, spec.fork_name.clone()); + let db_dirs = self.dirs.database(genesis_hash, None, spec.data_dir.clone()); // user defaults path let user_defaults_path = db_dirs.user_defaults_path(); @@ -167,7 +167,7 @@ impl SnapshotCommand { let snapshot_path = db_dirs.snapshot_path(); // execute upgrades - try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.fork_path().as_path()))); + try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile(db_dirs.db_root_path().as_path()))); // prepare client config let client_config = to_client_config(&self.cache_config, Mode::Active, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history, true); diff --git a/parity/upgrade.rs b/parity/upgrade.rs index 401f6a722..5c49cb997 100644 --- a/parity/upgrade.rs +++ b/parity/upgrade.rs @@ -18,10 +18,14 @@ use semver::Version; use std::collections::*; -use std::fs::{File, create_dir_all}; +use std::fs::{self, File, create_dir_all}; use std::env; +use std::io; use std::io::{Read, Write}; -use std::path::PathBuf; +use std::path::{PathBuf, Path}; +use dir::{DatabaseDirectories, default_data_path}; +use helpers::replace_home; +use util::journaldb::Algorithm; #[cfg_attr(feature="dev", allow(enum_variant_names))] #[derive(Debug)] @@ -126,3 +130,84 @@ pub fn upgrade(db_path: Option<&str>) -> Result { upgrade_from_version(ver) }) } + +fn file_exists(path: &Path) -> bool { + match fs::metadata(&path) { + Err(ref e) if e.kind() == io::ErrorKind::NotFound => false, + _ => true, + } +} + +pub fn upgrade_key_location(from: &PathBuf, to: &PathBuf) { + let mut parent = to.clone(); + parent.pop(); + match fs::create_dir_all(&parent).and_then(|()| fs::read_dir(from)) { + Ok(entries) => { + let files: Vec<_> = entries.filter_map(|f| f.ok().and_then(|f| if f.file_type().ok().map_or(false, |f| f.is_file()) { f.file_name().to_str().map(|s| s.to_owned()) } else { None })).collect(); + let mut num: usize = 0; + for name in files { + let mut from = from.clone(); + from.push(&name); + let mut to = to.clone(); + to.push(&name); + if !file_exists(&to) { + if let Err(e) = fs::rename(&from, &to) { + debug!("Error upgrading key {:?}: {:?}", from, e); + } else { + num += 1; + } + } else { + debug!("Skipped upgrading key {:?}", from); + } + } + if num > 0 { + info!("Moved {} keys from {} to {}", num, from.to_string_lossy(), to.to_string_lossy()); + } + }, + Err(e) => { + warn!("Error moving keys from {:?} to {:?}: {:?}", from, to, e); + } + } +} + +fn upgrade_dir_location(source: &PathBuf, dest: &PathBuf) { + if file_exists(&source) { + if !file_exists(&dest) { + let mut parent = dest.clone(); + parent.pop(); + if let Err(e) = fs::create_dir_all(&parent).and_then(|()| fs::rename(&source, &dest)) { + debug!("Skipped path {:?} -> {:?} :{:?}", source, dest, e); + } else { + info!("Moved {} to {}", source.to_string_lossy(), dest.to_string_lossy()); + } + } else { + debug!("Skipped upgrading directory {:?}, Destination already exists at {:?}", source, dest); + } + } +} + +fn upgrade_user_defaults(dirs: &DatabaseDirectories) { + let source = dirs.legacy_user_defaults_path(); + let dest = dirs.user_defaults_path(); + if file_exists(&source) { + if !file_exists(&dest) { + if let Err(e) = fs::rename(&source, &dest) { + debug!("Skipped upgrading user defaults {:?}:{:?}", dest, e); + } + } else { + debug!("Skipped upgrading user defaults {:?}, File exists at {:?}", source, dest); + } + } +} + +pub fn upgrade_data_paths(dirs: &DatabaseDirectories, pruning: Algorithm) { + let legacy_root_path = replace_home("", "$HOME/.parity"); + let default_path = default_data_path(); + if legacy_root_path != dirs.path && dirs.path == default_path { + upgrade_dir_location(&PathBuf::from(legacy_root_path), &PathBuf::from(&dirs.path)); + } + upgrade_dir_location(&dirs.legacy_version_path(pruning), &dirs.db_path(pruning)); + upgrade_dir_location(&dirs.legacy_snapshot_path(), &dirs.snapshot_path()); + upgrade_dir_location(&dirs.legacy_network_path(), &dirs.network_path()); + upgrade_user_defaults(&dirs); +}