From 366335a015f6b7306970cf86a214a9648cba65dd Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Tue, 13 Oct 2020 13:30:23 +0100 Subject: [PATCH 1/7] Feature/remove validator (#380) * Replacing Rust validator sketch with Cosmos-based code. * Removing old build instructions * go fmt on generated code * Removing build files for github and pi * Starting transplant surgery * Directory now running in validator, sans metrics * Updating go sum * A partly-working directory startup integrated into the nymcli app. * Removing the Swagger docs header from nymcli, it can live in server.go * Working swagger docs. * Updating test title on Swagger docs * Directory server now integrated into validator (primitive but working) * Noted location of mixmining reports database. * Bumped golang version * Removing validator cargo files. * Moving directory API init method into the nymd module * Ditching a test which is causing tooling problems - presence will go away soon anyway * Removing the validator and merging develop --- Cargo.lock | 940 +++--------------- Cargo.toml | 4 +- validator/Cargo.toml | 29 - validator/README.md | 21 - validator/diesel.toml | 5 - validator/migrations/.gitkeep | 0 validator/src/commands/init.rs | 58 -- validator/src/commands/mod.rs | 31 - validator/src/commands/run.rs | 66 -- validator/src/config/mod.rs | 263 ----- validator/src/config/template.rs | 81 -- validator/src/main.rs | 84 -- validator/src/network/ethereum/ethereum.rs | 15 - validator/src/network/mod.rs | 19 - validator/src/network/rest/capacity/mod.rs | 59 -- validator/src/network/rest/mod.rs | 72 -- validator/src/network/rest/models/mod.rs | 15 - validator/src/network/rest/models/presence.rs | 50 - .../src/network/rest/presence/conversions.rs | 135 --- .../src/network/rest/presence/mixnode.rs | 38 - validator/src/network/rest/presence/mod.rs | 6 - validator/src/network/rest/presence/models.rs | 66 -- .../src/network/rest/presence/topology.rs | 23 - validator/src/network/rest/routes/mod.rs | 18 - validator/src/network/rest/routes/topology.rs | 26 - validator/src/network/rest/staking/mod.rs | 1 - validator/src/network/tendermint/mod.rs | 82 -- validator/src/schema.rs | 1 - validator/src/services/mixmining/db.rs | 105 -- validator/src/services/mixmining/mod.rs | 176 ---- validator/src/services/mixmining/models.rs | 51 - validator/src/services/mixmining/tests/mod.rs | 11 - validator/src/services/mod.rs | 15 - validator/src/validator.rs | 57 -- 34 files changed, 131 insertions(+), 2492 deletions(-) delete mode 100644 validator/Cargo.toml delete mode 100644 validator/README.md delete mode 100644 validator/diesel.toml delete mode 100644 validator/migrations/.gitkeep delete mode 100644 validator/src/commands/init.rs delete mode 100644 validator/src/commands/mod.rs delete mode 100644 validator/src/commands/run.rs delete mode 100644 validator/src/config/mod.rs delete mode 100644 validator/src/config/template.rs delete mode 100644 validator/src/main.rs delete mode 100644 validator/src/network/ethereum/ethereum.rs delete mode 100644 validator/src/network/mod.rs delete mode 100644 validator/src/network/rest/capacity/mod.rs delete mode 100644 validator/src/network/rest/mod.rs delete mode 100644 validator/src/network/rest/models/mod.rs delete mode 100644 validator/src/network/rest/models/presence.rs delete mode 100644 validator/src/network/rest/presence/conversions.rs delete mode 100644 validator/src/network/rest/presence/mixnode.rs delete mode 100644 validator/src/network/rest/presence/mod.rs delete mode 100644 validator/src/network/rest/presence/models.rs delete mode 100644 validator/src/network/rest/presence/topology.rs delete mode 100644 validator/src/network/rest/routes/mod.rs delete mode 100644 validator/src/network/rest/routes/topology.rs delete mode 100644 validator/src/network/rest/staking/mod.rs delete mode 100644 validator/src/network/tendermint/mod.rs delete mode 100644 validator/src/schema.rs delete mode 100644 validator/src/services/mixmining/db.rs delete mode 100644 validator/src/services/mixmining/mod.rs delete mode 100644 validator/src/services/mixmining/models.rs delete mode 100644 validator/src/services/mixmining/tests/mod.rs delete mode 100644 validator/src/services/mod.rs delete mode 100644 validator/src/validator.rs diff --git a/Cargo.lock b/Cargo.lock index 5c07f4b39e..2166190574 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,22 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "abci" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfb90d266d6ca61cea4d155dd5033c9516495f4f74f82faf1ca5c4feeb82577" -dependencies = [ - "byteorder", - "bytes 0.4.12", - "env_logger 0.7.1", - "futures 0.3.5", - "integer-encoding", - "log 0.4.11", - "protobuf", - "protobuf-codegen-pure", - "tokio 0.1.22", -] - [[package]] name = "addr2line" version = "0.13.0" @@ -164,12 +147,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - [[package]] name = "autocfg" version = "1.0.1" @@ -190,16 +167,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - [[package]] name = "base64" version = "0.11.0" @@ -304,19 +271,6 @@ dependencies = [ "byte-tools", ] -[[package]] -name = "bodyparser" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f023abfa58aad6f6bc4ae0630799e24d5ee0ab8bb2e49f651d9b1f9aa4f52f30" -dependencies = [ - "iron", - "persistent", - "plugin", - "serde", - "serde_json", -] - [[package]] name = "bs58" version = "0.3.1" @@ -341,16 +295,6 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "iovec", -] - [[package]] name = "bytes" version = "0.5.6" @@ -416,15 +360,15 @@ dependencies = [ "futures 0.3.5", "gateway-client", "gateway-requests", - "log 0.4.11", + "log", "nonexhaustive-delayqueue", "nymsphinx", "pemstore", - "rand 0.7.3", + "rand", "serde", "sled 0.33.0", "tempfile", - "tokio 0.2.22", + "tokio", "topology", ] @@ -513,24 +457,13 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-deque" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", - "maybe-uninit", -] - [[package]] name = "crossbeam-epoch" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.0.1", + "autocfg", "cfg-if", "crossbeam-utils", "lazy_static", @@ -539,24 +472,13 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "crossbeam-queue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "maybe-uninit", -] - [[package]] name = "crossbeam-utils" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.1", + "autocfg", "cfg-if", "lazy_static", ] @@ -573,11 +495,11 @@ dependencies = [ "generic-array 0.14.4", "hkdf 0.9.0", "hmac 0.8.1", - "log 0.4.11", + "log", "nymsphinx-types", "pemstore", "pretty_env_logger", - "rand 0.7.3", + "rand", "stream-cipher 0.4.1", "x25519-dalek", ] @@ -629,7 +551,7 @@ checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" dependencies = [ "byteorder", "digest 0.8.1", - "rand_core 0.5.1", + "rand_core", "subtle 2.2.3", "zeroize", ] @@ -642,7 +564,7 @@ checksum = "c8492de420e9e60bc9a1d66e2dbb91825390b738a388606600663fc529b4b307" dependencies = [ "byteorder", "digest 0.9.0", - "rand_core 0.5.1", + "rand_core", "subtle 2.2.3", "zeroize", ] @@ -685,12 +607,12 @@ name = "directory-client" version = "0.1.0" dependencies = [ "directory-client-models", - "log 0.4.11", + "log", "mockito", "pretty_env_logger", "reqwest", "serde", - "tokio 0.2.22", + "tokio", ] [[package]] @@ -767,7 +689,7 @@ checksum = "53d2e93f837d749c16d118e7ddf7a4dfd0ac8f452cf51e46e9348824e5ef6851" dependencies = [ "curve25519-dalek 3.0.0", "ed25519", - "rand 0.7.3", + "rand", "serde", "sha2 0.9.1", "zeroize", @@ -790,20 +712,7 @@ checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" dependencies = [ "atty", "humantime", - "log 0.4.11", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime", - "log 0.4.11", + "log", "regex", "termcolor", ] @@ -814,7 +723,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" dependencies = [ - "version_check 0.9.2", + "version_check", ] [[package]] @@ -866,12 +775,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -1005,9 +908,9 @@ dependencies = [ "crypto", "futures 0.3.5", "gateway-requests", - "log 0.4.11", + "log", "nymsphinx", - "tokio 0.2.22", + "tokio", "tokio-tungstenite", "tungstenite", "wasm-bindgen", @@ -1023,10 +926,10 @@ dependencies = [ "bs58", "crypto", "futures 0.3.5", - "log 0.4.11", + "log", "nymsphinx", "pemstore", - "rand 0.7.3", + "rand", "serde", "serde_json", "tungstenite", @@ -1048,7 +951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" dependencies = [ "typenum", - "version_check 0.9.2", + "version_check", ] [[package]] @@ -1075,7 +978,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" dependencies = [ - "bytes 0.5.6", + "bytes", "fnv", "futures-core", "futures-sink", @@ -1083,7 +986,7 @@ dependencies = [ "http", "indexmap", "slab", - "tokio 0.2.22", + "tokio", "tokio-util", "tracing", ] @@ -1094,7 +997,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5deefd4816fb852b1ff3cb48f6c41da67be2d0e1d20b26a7a3b076da11f064b1" dependencies = [ - "log 0.4.11", + "log", "pest", "pest_derive", "quick-error 2.0.0", @@ -1163,7 +1066,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" dependencies = [ - "bytes 0.5.6", + "bytes", "fnv", "itoa", ] @@ -1174,7 +1077,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" dependencies = [ - "bytes 0.5.6", + "bytes", "http", ] @@ -1193,32 +1096,13 @@ dependencies = [ "quick-error 1.2.3", ] -[[package]] -name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -dependencies = [ - "base64 0.9.3", - "httparse", - "language-tags", - "log 0.3.9", - "mime 0.2.6", - "num_cpus", - "time", - "traitobject", - "typeable", - "unicase 1.4.2", - "url 1.7.2", -] - [[package]] name = "hyper" version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-channel", "futures-core", "futures-util", @@ -1230,7 +1114,7 @@ dependencies = [ "pin-project", "socket2", "time", - "tokio 0.2.22", + "tokio", "tower-service", "tracing", "want", @@ -1242,24 +1126,13 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed" dependencies = [ - "bytes 0.5.6", - "hyper 0.13.7", + "bytes", + "hyper", "native-tls", - "tokio 0.2.22", + "tokio", "tokio-tls", ] -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.2.0" @@ -1277,7 +1150,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" dependencies = [ - "autocfg 1.0.1", + "autocfg", "hashbrown", ] @@ -1287,7 +1160,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" dependencies = [ - "bytes 0.5.6", + "bytes", ] [[package]] @@ -1296,12 +1169,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" -[[package]] -name = "integer-encoding" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4ebd0bd29be0f11973e9b3e219005661042a019fd757798c36a47c87852625" - [[package]] name = "iovec" version = "0.1.4" @@ -1317,22 +1184,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" -[[package]] -name = "iron" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6d308ca2d884650a8bf9ed2ff4cb13fbb2207b71f64cda11dc9b892067295e8" -dependencies = [ - "hyper 0.10.16", - "log 0.3.9", - "mime_guess 1.8.8", - "modifier", - "num_cpus", - "plugin", - "typemap", - "url 1.7.2", -] - [[package]] name = "itoa" version = "0.4.6" @@ -1364,12 +1215,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28" -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - [[package]] name = "lazy_static" version = "1.4.0" @@ -1412,15 +1257,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.11", -] - [[package]] name = "log" version = "0.4.11" @@ -1460,7 +1296,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c198b026e1bbf08a937e94c6c60f9ec4a2267f5b0d2eec9c1b21b061ce2be55f" dependencies = [ - "autocfg 1.0.1", + "autocfg", ] [[package]] @@ -1469,41 +1305,20 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", -] - [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -[[package]] -name = "mime_guess" -version = "1.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216929a5ee4dd316b1702eedf5e74548c123d370f47841ceaac38ca154690ca3" -dependencies = [ - "mime 0.2.6", - "phf", - "phf_codegen", - "unicase 1.4.2", -] - [[package]] name = "mime_guess" version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" dependencies = [ - "mime 0.3.16", - "unicase 2.6.0", + "mime", + "unicase", ] [[package]] @@ -1527,7 +1342,7 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log 0.4.11", + "log", "miow 0.2.1", "net2", "slab", @@ -1540,7 +1355,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" dependencies = [ - "log 0.4.11", + "log", "mio", "miow 0.3.5", "winapi 0.3.9", @@ -1584,9 +1399,9 @@ name = "mixnet-client" version = "0.1.0" dependencies = [ "futures 0.3.5", - "log 0.4.11", + "log", "nymsphinx", - "tokio 0.2.22", + "tokio", "tokio-util", ] @@ -1596,7 +1411,7 @@ version = "0.1.0" dependencies = [ "dashmap", "futures 0.3.5", - "log 0.4.11", + "log", "nonexhaustive-delayqueue", "nymsphinx-acknowledgements", "nymsphinx-addressing", @@ -1604,7 +1419,7 @@ dependencies = [ "nymsphinx-framing", "nymsphinx-params", "nymsphinx-types", - "tokio 0.2.22", + "tokio", ] [[package]] @@ -1618,19 +1433,13 @@ dependencies = [ "difference", "httparse", "lazy_static", - "log 0.4.11", - "percent-encoding 2.1.0", - "rand 0.7.3", + "log", + "percent-encoding", + "rand", "regex", "serde_json", ] -[[package]] -name = "modifier" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" - [[package]] name = "native-tls" version = "0.2.4" @@ -1639,7 +1448,7 @@ checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" dependencies = [ "lazy_static", "libc", - "log 0.4.11", + "log", "openssl", "openssl-probe", "openssl-sys", @@ -1668,12 +1477,12 @@ dependencies = [ "directory-client", "futures 0.3.5", "gateway-client", - "log 0.4.11", + "log", "nymsphinx", "pretty_env_logger", - "rand 0.7.3", + "rand", "serde", - "tokio 0.2.22", + "tokio", "topology", "version-checker", ] @@ -1682,7 +1491,7 @@ dependencies = [ name = "nonexhaustive-delayqueue" version = "0.1.0" dependencies = [ - "tokio 0.2.22", + "tokio", ] [[package]] @@ -1691,7 +1500,7 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-traits", ] @@ -1701,7 +1510,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ - "autocfg 1.0.1", + "autocfg", ] [[package]] @@ -1728,19 +1537,19 @@ dependencies = [ "futures 0.3.5", "gateway-client", "gateway-requests", - "log 0.4.11", + "log", "nymsphinx", "pemstore", "pretty_env_logger", - "rand 0.7.3", + "rand", "serde", "serde_json", "sled 0.33.0", "tempfile", - "tokio 0.2.22", + "tokio", "tokio-tungstenite", "topology", - "url 2.1.1", + "url", "websocket-requests", ] @@ -1755,7 +1564,7 @@ dependencies = [ "gateway-client", "js-sys", "nymsphinx", - "rand 0.7.3", + "rand", "serde", "topology", "wasm-bindgen", @@ -1778,17 +1587,17 @@ dependencies = [ "dotenv", "futures 0.3.5", "gateway-requests", - "log 0.4.11", + "log", "mixnet-client", "mixnode-common", "nymsphinx", "pemstore", "pretty_env_logger", - "rand 0.7.3", + "rand", "serde", "sled 0.31.0", "tempfile", - "tokio 0.2.22", + "tokio", "tokio-tungstenite", "tokio-util", "tungstenite", @@ -1807,7 +1616,7 @@ dependencies = [ "dirs 2.0.2", "dotenv", "futures 0.3.5", - "log 0.4.11", + "log", "mixnet-client", "mixnode-common", "nymsphinx", @@ -1815,7 +1624,7 @@ dependencies = [ "pretty_env_logger", "serde", "tempfile", - "tokio 0.2.22", + "tokio", "tokio-util", "topology", ] @@ -1834,43 +1643,21 @@ dependencies = [ "futures 0.3.5", "gateway-client", "gateway-requests", - "log 0.4.11", + "log", "nymsphinx", "ordered-buffer", "pin-project", "pretty_env_logger", "proxy-helpers", - "rand 0.7.3", + "rand", "serde", "snafu", "socks5-requests", "tempfile", - "tokio 0.2.22", + "tokio", "topology", ] -[[package]] -name = "nym-validator" -version = "0.9.0-dev" -dependencies = [ - "abci", - "bodyparser", - "byteorder", - "clap", - "config", - "dirs 2.0.2", - "dotenv", - "futures 0.3.5", - "iron", - "log 0.4.11", - "pretty_env_logger", - "router", - "serde", - "serde_json", - "tempfile", - "tokio 0.2.22", -] - [[package]] name = "nymsphinx" version = "0.1.0" @@ -1885,9 +1672,9 @@ dependencies = [ "nymsphinx-framing", "nymsphinx-params", "nymsphinx-types", - "rand 0.7.3", + "rand", "rand_distr", - "tokio 0.2.22", + "tokio", "topology", ] @@ -1900,7 +1687,7 @@ dependencies = [ "nymsphinx-params", "nymsphinx-types", "pemstore", - "rand 0.7.3", + "rand", "topology", ] @@ -1922,7 +1709,7 @@ dependencies = [ "nymsphinx-addressing", "nymsphinx-params", "nymsphinx-types", - "rand 0.7.3", + "rand", "serde", "topology", ] @@ -1931,11 +1718,11 @@ dependencies = [ name = "nymsphinx-chunking" version = "0.1.0" dependencies = [ - "log 0.4.11", + "log", "nymsphinx-addressing", "nymsphinx-params", "nymsphinx-types", - "rand 0.7.3", + "rand", ] [[package]] @@ -1949,7 +1736,7 @@ dependencies = [ "nymsphinx-forwarding", "nymsphinx-params", "nymsphinx-types", - "rand 0.7.3", + "rand", "topology", ] @@ -1966,7 +1753,7 @@ dependencies = [ name = "nymsphinx-framing" version = "0.1.0" dependencies = [ - "bytes 0.5.6", + "bytes", "nymsphinx-params", "nymsphinx-types", "tokio-util", @@ -2037,7 +1824,7 @@ version = "0.9.58" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" dependencies = [ - "autocfg 1.0.1", + "autocfg", "cc", "libc", "pkg-config", @@ -2048,18 +1835,7 @@ dependencies = [ name = "ordered-buffer" version = "0.1.0" dependencies = [ - "log 0.4.11", -] - -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.6.2", - "rustc_version", + "log", ] [[package]] @@ -2083,21 +1859,6 @@ dependencies = [ "parking_lot_core 0.8.0", ] -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -dependencies = [ - "cfg-if", - "cloudabi 0.0.3", - "libc", - "redox_syscall", - "rustc_version", - "smallvec 0.6.13", - "winapi 0.3.9", -] - [[package]] name = "parking_lot_core" version = "0.7.2" @@ -2108,7 +1869,7 @@ dependencies = [ "cloudabi 0.0.3", "libc", "redox_syscall", - "smallvec 1.4.2", + "smallvec", "winapi 0.3.9", ] @@ -2123,7 +1884,7 @@ dependencies = [ "instant", "libc", "redox_syscall", - "smallvec 1.4.2", + "smallvec", "winapi 0.3.9", ] @@ -2145,28 +1906,12 @@ dependencies = [ "pem", ] -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -[[package]] -name = "persistent" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8fa0009c4f3d350281309909c618abddf10bb7e3145f28410782f6a5ec74c5" -dependencies = [ - "iron", - "plugin", -] - [[package]] name = "pest" version = "2.1.3" @@ -2210,45 +1955,6 @@ dependencies = [ "sha-1 0.8.2", ] -[[package]] -name = "phf" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_codegen" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" -dependencies = [ - "phf_shared", - "rand 0.6.5", -] - -[[package]] -name = "phf_shared" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -dependencies = [ - "siphasher", - "unicase 1.4.2", -] - [[package]] name = "pin-project" version = "0.4.23" @@ -2287,15 +1993,6 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" -[[package]] -name = "plugin" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" -dependencies = [ - "typemap", -] - [[package]] name = "ppv-lite86" version = "0.2.9" @@ -2309,8 +2006,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074" dependencies = [ "chrono", - "env_logger 0.6.2", - "log 0.4.11", + "env_logger", + "log", ] [[package]] @@ -2323,7 +2020,7 @@ dependencies = [ "proc-macro2 1.0.20", "quote 1.0.7", "syn 1.0.40", - "version_check 0.9.2", + "version_check", ] [[package]] @@ -2334,7 +2031,7 @@ checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2 1.0.20", "quote 1.0.7", - "version_check 0.9.2", + "version_check", ] [[package]] @@ -2367,41 +2064,16 @@ dependencies = [ "unicode-xid 0.2.1", ] -[[package]] -name = "protobuf" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6563a657a014b771e7f69f06447d88d8fbb5a215ffc4cab724afb3acedcc7701" - -[[package]] -name = "protobuf-codegen" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f1bbc6db30d5d3e730b6e2326e9a64a75ca9c80d6427d6f054dc8cacc79d225" -dependencies = [ - "protobuf", -] - -[[package]] -name = "protobuf-codegen-pure" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5473ffa23d2ea3b9046764f1a22149791967aad946b6cbd99601e720afc4d0" -dependencies = [ - "protobuf", - "protobuf-codegen", -] - [[package]] name = "proxy-helpers" version = "0.1.0" dependencies = [ - "bytes 0.5.6", + "bytes", "futures 0.3.5", - "log 0.4.11", + "log", "ordered-buffer", "socks5-requests", - "tokio 0.2.22", + "tokio", "tokio-test", ] @@ -2412,11 +2084,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" dependencies = [ "error-chain", - "idna 0.2.0", + "idna", "lazy_static", "native-tls", "regex", - "url 2.1.1", + "url", ] [[package]] @@ -2449,25 +2121,6 @@ dependencies = [ "proc-macro2 1.0.20", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.7", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi 0.3.9", -] - [[package]] name = "rand" version = "0.7.3" @@ -2476,19 +2129,9 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom", "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.3.1", + "rand_chacha", + "rand_core", + "rand_hc", ] [[package]] @@ -2498,24 +2141,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", - "rand_core 0.5.1", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" @@ -2531,16 +2159,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2" dependencies = [ - "rand 0.7.3", -] - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", + "rand", ] [[package]] @@ -2549,69 +2168,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi 0.3.9", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi 0.0.3", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi 0.3.9", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", + "rand_core", ] [[package]] @@ -2665,52 +2222,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9eaa17ac5d7b838b7503d118fa16ad88f440498bf9ffe5424e621f93190d61e" dependencies = [ "base64 0.12.3", - "bytes 0.5.6", + "bytes", "encoding_rs", "futures-core", "futures-util", "http", "http-body", - "hyper 0.13.7", + "hyper", "hyper-tls", "ipnet", "js-sys", "lazy_static", - "log 0.4.11", - "mime 0.3.16", - "mime_guess 2.0.3", + "log", + "mime", + "mime_guess", "native-tls", - "percent-encoding 2.1.0", + "percent-encoding", "pin-project-lite", "serde", "serde_json", "serde_urlencoded", - "tokio 0.2.22", + "tokio", "tokio-tls", - "url 2.1.1", + "url", "wasm-bindgen", "wasm-bindgen-futures 0.4.17", "web-sys", "winreg", ] -[[package]] -name = "route-recognizer" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea509065eb0b3c446acdd0102f0d46567dc30902dc0be91d6552035d92b0f4f8" - -[[package]] -name = "router" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc63b6f3b8895b0d04e816b2b1aa58fdba2d5acca3cbb8f0ab8e017347d57397" -dependencies = [ - "iron", - "route-recognizer", - "url 1.7.2", -] - [[package]] name = "rust-argon2" version = "0.8.2" @@ -2729,27 +2269,12 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - [[package]] name = "ryu" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - [[package]] name = "schannel" version = "0.1.19" @@ -2850,7 +2375,7 @@ dependencies = [ "dtoa", "itoa", "serde", - "url 2.1.1", + "url", ] [[package]] @@ -2919,12 +2444,6 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" -[[package]] -name = "siphasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" - [[package]] name = "slab" version = "0.4.2" @@ -2943,7 +2462,7 @@ dependencies = [ "fs2", "fxhash", "libc", - "log 0.4.11", + "log", "parking_lot 0.10.2", ] @@ -2960,19 +2479,10 @@ dependencies = [ "fs2", "fxhash", "libc", - "log 0.4.11", + "log", "parking_lot 0.11.0", ] -[[package]] -name = "smallvec" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -dependencies = [ - "maybe-uninit", -] - [[package]] name = "smallvec" version = "1.4.2" @@ -3036,8 +2546,8 @@ dependencies = [ "hkdf 0.8.0", "hmac 0.7.1", "lioness", - "log 0.4.11", - "rand 0.7.3", + "log", + "rand", "rand_distr", "sha2 0.8.2", ] @@ -3049,15 +2559,15 @@ dependencies = [ "clap", "dirs 2.0.2", "futures 0.3.5", - "log 0.4.11", + "log", "nymsphinx", "ordered-buffer", "pretty_env_logger", "proxy-helpers", "publicsuffix", - "rand 0.7.3", + "rand", "socks5-requests", - "tokio 0.2.22", + "tokio", "tokio-tungstenite", "websocket-requests", ] @@ -3141,7 +2651,7 @@ checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ "cfg-if", "libc", - "rand 0.7.3", + "rand", "redox_syscall", "remove_dir_all", "winapi 0.3.9", @@ -3191,33 +2701,13 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" -[[package]] -name = "tokio" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "mio", - "num_cpus", - "tokio-codec", - "tokio-current-thread", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", -] - [[package]] name = "tokio" version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" dependencies = [ - "bytes 0.5.6", + "bytes", "fnv", "futures-core", "iovec", @@ -3235,48 +2725,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "tokio-codec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "tokio-io", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -dependencies = [ - "futures 0.1.29", - "tokio-executor", -] - -[[package]] -name = "tokio-executor" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -dependencies = [ - "crossbeam-utils", - "futures 0.1.29", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "log 0.4.11", -] - [[package]] name = "tokio-macros" version = "0.2.5" @@ -3288,87 +2736,15 @@ dependencies = [ "syn 1.0.40", ] -[[package]] -name = "tokio-reactor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -dependencies = [ - "crossbeam-utils", - "futures 0.1.29", - "lazy_static", - "log 0.4.11", - "mio", - "num_cpus", - "parking_lot 0.9.0", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", -] - -[[package]] -name = "tokio-sync" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures 0.1.29", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "iovec", - "mio", - "tokio-io", - "tokio-reactor", -] - [[package]] name = "tokio-test" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed0049c119b6d505c4447f5c64873636c7af6c75ab0d45fd9f618d82acb8016d" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-core", - "tokio 0.2.22", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils", - "futures 0.1.29", - "lazy_static", - "log 0.4.11", - "num_cpus", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-timer" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -dependencies = [ - "crossbeam-utils", - "futures 0.1.29", - "slab", - "tokio-executor", + "tokio", ] [[package]] @@ -3378,7 +2754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343" dependencies = [ "native-tls", - "tokio 0.2.22", + "tokio", ] [[package]] @@ -3388,9 +2764,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d9e878ad426ca286e4dcae09cbd4e1973a7f8987d97570e2469703dd7f5720c" dependencies = [ "futures-util", - "log 0.4.11", + "log", "pin-project", - "tokio 0.2.22", + "tokio", "tungstenite", ] @@ -3400,12 +2776,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-core", "futures-sink", - "log 0.4.11", + "log", "pin-project-lite", - "tokio 0.2.22", + "tokio", ] [[package]] @@ -3423,11 +2799,11 @@ version = "0.1.0" dependencies = [ "bs58", "crypto", - "log 0.4.11", + "log", "nymsphinx-addressing", "nymsphinx-types", "pretty_env_logger", - "rand 0.7.3", + "rand", "version-checker", ] @@ -3444,7 +2820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" dependencies = [ "cfg-if", - "log 0.4.11", + "log", "tracing-core", ] @@ -3457,12 +2833,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" - [[package]] name = "try-lock" version = "0.2.3" @@ -3477,32 +2847,17 @@ checksum = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23" dependencies = [ "base64 0.12.3", "byteorder", - "bytes 0.5.6", + "bytes", "http", "httparse", "input_buffer", - "log 0.4.11", - "rand 0.7.3", + "log", + "rand", "sha-1 0.9.1", - "url 2.1.1", + "url", "utf-8", ] -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" - -[[package]] -name = "typemap" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" -dependencies = [ - "unsafe-any", -] - [[package]] name = "typenum" version = "1.12.0" @@ -3515,22 +2870,13 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -dependencies = [ - "version_check 0.1.5", -] - [[package]] name = "unicase" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.2", + "version_check", ] [[package]] @@ -3569,35 +2915,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" -[[package]] -name = "unsafe-any" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" -dependencies = [ - "traitobject", -] - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - [[package]] name = "url" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" dependencies = [ - "idna 0.2.0", + "idna", "matches", - "percent-encoding 2.1.0", + "percent-encoding", ] [[package]] @@ -3610,7 +2936,7 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" name = "validator-client" version = "0.1.0" dependencies = [ - "log 0.4.11", + "log", "pretty_env_logger", ] @@ -3633,12 +2959,6 @@ dependencies = [ "semver", ] -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "version_check" version = "0.9.2" @@ -3651,7 +2971,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log 0.4.11", + "log", "try-lock", ] @@ -3687,7 +3007,7 @@ checksum = "bc71e4c5efa60fb9e74160e89b93353bc24059999c0ae0fb03affc39770310b0" dependencies = [ "bumpalo", "lazy_static", - "log 0.4.11", + "log", "proc-macro2 1.0.20", "quote 1.0.7", "syn 1.0.40", @@ -3900,7 +3220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc614d95359fd7afc321b66d2107ede58b246b844cf5d8a0adcca413e439f088" dependencies = [ "curve25519-dalek 3.0.0", - "rand_core 0.5.1", + "rand_core", "zeroize", ] diff --git a/Cargo.toml b/Cargo.toml index eaacd1d191..48176f6c33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,10 +39,9 @@ members = [ "common/wasm-utils", "gateway", "gateway/gateway-requests", - "service-providers/sphinx-socks", "mixnode", "network-monitor", - "validator", + "service-providers/sphinx-socks", ] default-members = [ @@ -52,6 +51,5 @@ default-members = [ "gateway", "service-providers/sphinx-socks", "mixnode", - "validator", "network-monitor", ] diff --git a/validator/Cargo.toml b/validator/Cargo.toml deleted file mode 100644 index dfae7e6705..0000000000 --- a/validator/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "nym-validator" -version = "0.9.0-dev" -authors = ["Dave Hrycyszyn ", "Jedrzej Stuczynski "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -abci = "0.6.4" -bodyparser = "0.8.0" -byteorder = "1.3.2" -clap = "2.33.0" -dirs = "2.0.2" -dotenv = "0.15.0" -futures = "0.3.1" -iron = "0.6.1" -log = "0.4" -pretty_env_logger = "0.3" -router = "0.6.0" -serde = "1.0.104" -serde_json = "1.0.48" -tokio = { version = "0.2", features = ["full"] } - -## internal -config = { path = "../common/config" } - -[dev-dependencies] -tempfile = "3.1.0" \ No newline at end of file diff --git a/validator/README.md b/validator/README.md deleted file mode 100644 index 47b90bec59..0000000000 --- a/validator/README.md +++ /dev/null @@ -1,21 +0,0 @@ -Nym Validator -============= - -The Nym Validator has several jobs: - -* use Tendermint (v0.33.0) to maintain a total global ordering of incoming transactions -* rewards + stake slashing based quality of service measurements for mixnet nodes (aka "mixmining") -* generate Coconut credentials and ensure they're not double spent -* maintain a decentralized directory of all Nym nodes that have staked into the system - -Some of these functions may be moved away to their own node types in the future, for example to increase scalability or performance. At the moment, we'd like to keep deployments simple, so they're all in the validator node. - -Running the validator on your local machine -------------------------------------------- - -1. Download and install [Tendermint 0.32.7](https://github.com/tendermint/tendermint/releases/tag/v0.32.7) -2. `tendermint init` sets up Tendermint for use -3. `tendermint node` runs Tendermint. You'll get errors until you run the Nym validator, this is normal :). -4. `cp sample-configs/validator-config.toml.sample sample-configs/validator-config.toml` -5. `cargo run -- run --config ../sample-configs/validator-config.toml` builds the Nym Validator and runs it - diff --git a/validator/diesel.toml b/validator/diesel.toml deleted file mode 100644 index 92267c829f..0000000000 --- a/validator/diesel.toml +++ /dev/null @@ -1,5 +0,0 @@ -# For documentation on how to configure this file, -# see diesel.rs/guides/configuring-diesel-cli - -[print_schema] -file = "src/schema.rs" diff --git a/validator/migrations/.gitkeep b/validator/migrations/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/validator/src/commands/init.rs b/validator/src/commands/init.rs deleted file mode 100644 index d3efa04064..0000000000 --- a/validator/src/commands/init.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::commands::override_config; -use clap::{App, Arg, ArgMatches}; -use config::NymConfig; - -pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { - App::new("init") - .about("Initialise the validator") - .arg( - Arg::with_name("id") - .long("id") - .help("Id of the nym-validator we want to create config for.") - .takes_value(true) - .required(true), - ) - .arg( - Arg::with_name("location") - .long("location") - .help("Optional geographical location of this node") - .takes_value(true), - ) - .arg( - Arg::with_name("directory") - .long("directory") - .help("Address of the directory server the validator is sending presence to and uses for mix mining") - .takes_value(true), - ) -} - -pub fn execute(matches: &ArgMatches) { - let id = matches.value_of("id").unwrap(); - println!("Initialising validator {}...", id); - - let mut config = crate::config::Config::new(id); - - config = override_config(config, matches); - - let config_save_location = config.get_config_file_save_location(); - config - .save_to_file(None) - .expect("Failed to save the config file"); - println!("Saved configuration file to {:?}", config_save_location); - - println!("Validator configuration completed.\n\n\n") -} diff --git a/validator/src/commands/mod.rs b/validator/src/commands/mod.rs deleted file mode 100644 index 01b11b3a47..0000000000 --- a/validator/src/commands/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::config::Config; -use clap::ArgMatches; - -pub mod init; -pub mod run; - -pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config { - if let Some(directory) = matches.value_of("directory") { - config = config.with_custom_directory(directory); - } - - if let Some(location) = matches.value_of("location") { - config = config.with_location(location); - } - - config -} diff --git a/validator/src/commands/run.rs b/validator/src/commands/run.rs deleted file mode 100644 index cc636163e3..0000000000 --- a/validator/src/commands/run.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Commenting config out temporarily, we'll undoubtedly need it back soon. -// use crate::commands::override_config; -// use crate::config::Config; -// use config::NymConfig; -use crate::validator::Validator; -use clap::{App, Arg, ArgMatches}; - -pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { - App::new("run") - .about("Starts the validator") - .arg( - Arg::with_name("id") - .long("id") - .help("Id of the nym-validator we want to run") - .takes_value(true) - .required(true), - ) - // the rest of arguments are optional, they are used to override settings in config file - .arg( - Arg::with_name("location") - .long("location") - .help("Optional geographical location of this node") - .takes_value(true), - ) - .arg( - Arg::with_name("config") - .long("config") - .help("Custom path to the nym-validator configuration file") - .takes_value(true), - ) - .arg( - Arg::with_name("directory") - .long("directory") - .help("Address of the directory server the validator is sending presence to and uses for mix mining") - .takes_value(true), - ) -} - -pub fn execute(matches: &ArgMatches) { - let id = matches.value_of("id").unwrap(); - - println!("Starting validator {}...", id); - - // let mut config = - // Config::load_from_file(matches.value_of("config").map(|path| path.into()), Some(id)) - // .expect("Failed to load config file"); - - // config = override_config(config, matches); - - let validator = Validator::new(); - validator.start() -} diff --git a/validator/src/config/mod.rs b/validator/src/config/mod.rs deleted file mode 100644 index 1bd21771ea..0000000000 --- a/validator/src/config/mod.rs +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::config::template::config_template; -use config::NymConfig; -use serde::{Deserialize, Serialize}; -use std::path::PathBuf; -use std::time; - -mod template; - -// where applicable, the below are defined in milliseconds -const DEFAULT_DIRECTORY_SERVER: &str = "https://directory.nymtech.net"; - -// 'MIXMINING' -const DEFAULT_MIX_MINING_DELAY: u64 = 10_000; -const DEFAULT_MIX_MINING_RESOLUTION_TIMEOUT: u64 = 5_000; -const DEFAULT_MIX_MINING_CONNECTION_TIMEOUT: u64 = 1_500; - -const DEFAULT_NUMBER_OF_MIX_MINING_TEST_PACKETS: u64 = 2; - -// 'DEBUG' -const DEFAULT_PRESENCE_SENDING_DELAY: u64 = 3000; - -#[derive(Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] -pub struct Config { - validator: Validator, - - mix_mining: MixMining, - - tendermint: Tendermint, - - #[serde(default)] - logging: Logging, - #[serde(default)] - debug: Debug, -} - -impl NymConfig for Config { - fn template() -> &'static str { - config_template() - } - - fn config_file_name() -> String { - "config.toml".to_string() - } - - fn default_root_directory() -> PathBuf { - dirs::home_dir() - .expect("Failed to evaluate $HOME value") - .join(".nym") - .join("validators") - } - - fn root_directory(&self) -> PathBuf { - self.validator.nym_root_directory.clone() - } - - fn config_directory(&self) -> PathBuf { - self.validator - .nym_root_directory - .join(&self.validator.id) - .join("config") - } - - fn data_directory(&self) -> PathBuf { - self.validator - .nym_root_directory - .join(&self.validator.id) - .join("data") - } -} - -impl Config { - pub fn new>(id: S) -> Self { - Config::default().with_id(id) - } - - // builder methods - pub fn with_id>(mut self, id: S) -> Self { - let id = id.into(); - - // calls to any defaults requiring id (see: client, mixnode, provider): - - self.validator.id = id; - self - } - - pub fn with_custom_directory>(mut self, directory_server: S) -> Self { - let directory_server_string = directory_server.into(); - self.debug.presence_directory_server = directory_server_string.clone(); - self.mix_mining.directory_server = directory_server_string; - self - } - - pub fn with_location>(mut self, location: S) -> Self { - self.validator.location = location.into(); - self - } - - // getters - pub fn get_config_file_save_location(&self) -> PathBuf { - self.config_directory().join(Self::config_file_name()) - } - - #[allow(dead_code)] - pub fn get_location(&self) -> String { - self.validator.location.clone() - } - - // dead_code until validator actually sends the presence data - #[allow(dead_code)] - pub fn get_presence_directory_server(&self) -> String { - self.debug.presence_directory_server.clone() - } - - #[allow(dead_code)] - pub fn get_presence_sending_delay(&self) -> time::Duration { - time::Duration::from_millis(self.debug.presence_sending_delay) - } -} - -#[derive(Debug, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] -pub struct Validator { - /// ID specifies the human readable ID of this particular validator. - id: String, - - /// Completely optional value specifying geographical location of this particular node. - /// Currently it's used entirely for debug purposes, as there are no mechanisms implemented - /// to verify correctness of the information provided. However, feel free to fill in - /// this field with as much accuracy as you wish to share. - location: String, - - /// nym_home_directory specifies absolute path to the home nym MixNodes directory. - /// It is expected to use default value and hence .toml file should not redefine this field. - nym_root_directory: PathBuf, -} - -impl Validator { - fn default_location() -> String { - "unknown".into() - } -} - -impl Default for Validator { - fn default() -> Self { - Validator { - id: "".to_string(), - location: Self::default_location(), - nym_root_directory: Config::default_root_directory(), - } - } -} - -#[derive(Debug, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] -pub struct MixMining { - /// Directory server from which the validator will obtain initial topology. - directory_server: String, - - /// The uniform delay every which validator are running their mix-mining procedure. - /// The provided value is interpreted as milliseconds. - run_delay: u64, - - /// During the mix-mining process, test packets are sent through various network - /// paths. This timeout determines waiting period until it is decided that the packet - /// did not reach its destination. - /// The provided value is interpreted as milliseconds. - resolution_timeout: u64, - - /// Timeout for trying to establish connection to node endpoints. - /// The provided value is interpreted as milliseconds. - connection_timeout: u64, - - /// How many packets should be sent through each path during the mix-mining procedure. - number_of_test_packets: u64, -} - -impl Default for MixMining { - fn default() -> Self { - MixMining { - directory_server: "https://directory.nymtech.net".to_string(), - run_delay: DEFAULT_MIX_MINING_DELAY, - resolution_timeout: DEFAULT_MIX_MINING_RESOLUTION_TIMEOUT, - number_of_test_packets: DEFAULT_NUMBER_OF_MIX_MINING_TEST_PACKETS, - connection_timeout: DEFAULT_MIX_MINING_CONNECTION_TIMEOUT, - } - } -} - -#[derive(Debug, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] -pub struct Tendermint {} - -impl Default for Tendermint { - fn default() -> Self { - Tendermint {} - } -} - -#[derive(Debug, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] -pub struct Logging {} - -impl Default for Logging { - fn default() -> Self { - Logging {} - } -} - -#[derive(Debug, Deserialize, PartialEq, Serialize)] -#[serde(default, deny_unknown_fields)] -pub struct Debug { - /// Directory server to which the server will be reporting their presence data. - presence_directory_server: String, - - /// Delay between each subsequent presence data being sent. - presence_sending_delay: u64, -} - -impl Debug {} - -impl Default for Debug { - fn default() -> Self { - Debug { - presence_directory_server: DEFAULT_DIRECTORY_SERVER.to_string(), - presence_sending_delay: DEFAULT_PRESENCE_SENDING_DELAY, - } - } -} - -#[cfg(test)] -mod validator_config { - use super::*; - - #[test] - fn after_saving_default_config_the_loaded_one_is_identical() { - // need to figure out how to do something similar but without touching the disk - // or the file system at all... - let temp_location = tempfile::tempdir().unwrap().path().join("config.toml"); - let default_config = Config::default().with_id("foomp".to_string()); - default_config - .save_to_file(Some(temp_location.clone())) - .unwrap(); - - let loaded_config = Config::load_from_file(Some(temp_location), None).unwrap(); - - assert_eq!(default_config, loaded_config); - } -} diff --git a/validator/src/config/template.rs b/validator/src/config/template.rs deleted file mode 100644 index 7525dc7a8c..0000000000 --- a/validator/src/config/template.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -pub(crate) fn config_template() -> &'static str { - // While using normal toml marshalling would have been way simpler with less overhead, - // I think it's useful to have comments attached to the saved config file to explain behaviour of - // particular fields. - // Note: any changes to the template must be reflected in the appropriate structs in mod.rs. - r#" -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base mixnode config options ##### - -[validator] -# Human readable ID of this particular validator. -id = '{{ validator.id }}' - -# Completely optional value specifying geographical location of this particular node. -# Currently it's used entirely for debug purposes, as there are no mechanisms implemented -# to verify correctness of the information provided. However, feel free to fill in -# this field with as much accuracy as you wish to share. -location = '{{ validator.location }}' - -##### advanced configuration options ##### - -# nym_home_directory specifies absolute path to the home nym validators directory. -# It is expected to use default value and hence .toml file should not redefine this field. -nym_root_directory = '{{ validator.nym_root_directory }}' - - -##### mix mining config options ##### - -[mix_mining] - -# Directory server from which the validator will obtain initial topology. -directory_server = '{{ mix_mining.directory_server }}' - -# The uniform delay every which validator are running their mix-mining procedure. -# The provided value is interpreted as milliseconds. -run_delay = {{ mix_mining.run_delay }} - -# During the mix-mining process, test packets are sent through various network -# paths. This timeout determines waiting period until it is decided that the packet -# did not reach its destination. -# The provided value is interpreted as milliseconds. -resolution_timeout = {{ mix_mining.resolution_timeout }} - -# Timeout for trying to establish connection to node endpoints. -# The provided value is interpreted as milliseconds. -connection_timeout = {{ mix_mining.connection_timeout }} - -# How many packets should be sent through each path during the mix-mining procedure. -number_of_test_packets = {{ mix_mining.number_of_test_packets }} - - -##### tendermint config options ##### - -[tendermint] - - - -##### logging configuration options ##### - -[logging] - -# TODO - -"# -} diff --git a/validator/src/main.rs b/validator/src/main.rs deleted file mode 100644 index 55acc93523..0000000000 --- a/validator/src/main.rs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use clap::{App, ArgMatches}; - -mod commands; -mod config; -mod network; -mod services; -mod validator; - -fn main() { - dotenv::dotenv().ok(); - setup_logging(); - println!("{}", banner()); - - let arg_matches = App::new("Nym Validator") - .version(env!("CARGO_PKG_VERSION")) - .author("Nymtech") - .about("Implementation of Nym Validator") - .subcommand(commands::init::command_args()) - .subcommand(commands::run::command_args()) - .get_matches(); - - execute(arg_matches); -} - -fn execute(matches: ArgMatches) { - match matches.subcommand() { - ("init", Some(m)) => commands::init::execute(m), - ("run", Some(m)) => commands::run::execute(m), - _ => println!("{}", usage()), - } -} - -fn usage() -> &'static str { - "usage: --help to see available options.\n\n" -} - -fn banner() -> String { - format!( - r#" - - _ __ _ _ _ __ ___ - | '_ \| | | | '_ \ _ \ - | | | | |_| | | | | | | - |_| |_|\__, |_| |_| |_| - |___/ - - (validator - version {:}) - - "#, - env!("CARGO_PKG_VERSION") - ) -} - -fn setup_logging() { - let mut log_builder = pretty_env_logger::formatted_timed_builder(); - if let Ok(s) = ::std::env::var("RUST_LOG") { - log_builder.parse_filters(&s); - } else { - // default to 'Info' - log_builder.filter(None, log::LevelFilter::Info); - } - - log_builder - .filter_module("hyper", log::LevelFilter::Warn) - .filter_module("tokio_reactor", log::LevelFilter::Warn) - .filter_module("reqwest", log::LevelFilter::Warn) - .filter_module("mio", log::LevelFilter::Warn) - .filter_module("want", log::LevelFilter::Warn) - .init(); -} diff --git a/validator/src/network/ethereum/ethereum.rs b/validator/src/network/ethereum/ethereum.rs deleted file mode 100644 index 69f4679332..0000000000 --- a/validator/src/network/ethereum/ethereum.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// placeholder for Ethereum / ERC20 bridge integration diff --git a/validator/src/network/mod.rs b/validator/src/network/mod.rs deleted file mode 100644 index 1084c25e7a..0000000000 --- a/validator/src/network/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! The `network` module provides interfaces to external systems via network -//! connectivity. -//! -pub mod rest; -pub mod tendermint; diff --git a/validator/src/network/rest/capacity/mod.rs b/validator/src/network/rest/capacity/mod.rs deleted file mode 100644 index 6813023401..0000000000 --- a/validator/src/network/rest/capacity/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use super::*; -use bodyparser::Struct; -use iron::mime::Mime; -use iron::status; -use iron::Handler; - -/// Holds data for a capacity update (json) -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Capacity { - value: usize, -} - -pub struct Update { - service: Arc>, -} - -impl Update { - pub fn new(service: Arc>) -> Update { - Update { service } - } -} - -impl Handler for Update { - fn handle(&self, req: &mut Request) -> IronResult { - let json_parse = req.get::>(); - - match json_parse { - Ok(capacity) => { - let capacity = capacity.expect("Unexpected JSON parsing problem").value; - self.service.lock().unwrap().set_capacity(capacity); - Ok(Response::with(status::Created)) - } - Err(err) => Ok(Response::with((status::BadRequest, err.detail))), - } - } -} - -pub struct Get { - service: Arc>, -} - -impl Get { - pub fn new(service: Arc>) -> Get { - Get { service } - } -} - -impl Handler for Get { - fn handle(&self, _: &mut Request) -> IronResult { - let content_type = "application/json".parse::().unwrap(); - let value = self.service.lock().unwrap().capacity(); - let c = Capacity { value }; - let json = serde_json::to_string(&c).unwrap(); - Ok(Response::with((content_type, status::Ok, json))) - } -} diff --git a/validator/src/network/rest/mod.rs b/validator/src/network/rest/mod.rs deleted file mode 100644 index 4b991caf00..0000000000 --- a/validator/src/network/rest/mod.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -use crate::services::mixmining; -use iron::prelude::*; -use presence::mixnode; -use presence::topology; -use router::Router; -use std::sync::{Arc, Mutex}; - -mod capacity; -mod presence; -mod staking; - -pub struct Api { - mixmining_service: Arc>, -} - -impl Api { - pub fn new(mixmining_service: mixmining::Service) -> Api { - let service = Arc::new(Mutex::new(mixmining_service)); - Api { - mixmining_service: service, - } - } - - /// Run the REST API. - pub async fn run(self) { - let port = 3000; // TODO: make this configurable - let address = format!("localhost:{}", port); - println!("* starting REST API on http://{}", address); - - let router = self.setup_router(); - - Iron::new(router).http(address).unwrap(); - } - - /// Tie together URL route paths with handler functions. - fn setup_router(self) -> Router { - // define a Router to hold our routes - let mut router = Router::new(); - - // set up handlers - let capacity_update = capacity::Update::new(Arc::clone(&self.mixmining_service)); - let capacity_get = capacity::Get::new(Arc::clone(&self.mixmining_service)); - let presence_mixnode_create = - mixnode::CreatePresence::new(Arc::clone(&self.mixmining_service)); - let topology_get = topology::GetTopology::new(Arc::clone(&self.mixmining_service)); - - // tie routes to handlers - router.get("/capacity", capacity_get, "capacity_get"); - router.post("/capacity", capacity_update, "capacity_update"); - router.get("/topology", topology_get, "topology_get"); - router.post( - "/presence/mixnodes", - presence_mixnode_create, - "presence_mixnodes_post", - ); - - router - } -} diff --git a/validator/src/network/rest/models/mod.rs b/validator/src/network/rest/models/mod.rs deleted file mode 100644 index 82b6b328e2..0000000000 --- a/validator/src/network/rest/models/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -pub mod presence; diff --git a/validator/src/network/rest/models/presence.rs b/validator/src/network/rest/models/presence.rs deleted file mode 100644 index a2a781a236..0000000000 --- a/validator/src/network/rest/models/presence.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use serde::{Deserialize, Serialize}; - -// Topology shows us the current state of the overall Nym network -#[derive(Serialize, Deserialize, Debug)] -pub struct Topology { - pub validators: Vec, - pub mix_nodes: Vec, - pub service_providers: Vec, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct Validator { - host: String, - public_key: String, - version: String, - last_seen: u64, - location: String, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct MixNode { - host: String, - public_key: String, - version: String, - last_seen: u64, - location: String, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ServiceProvider { - host: String, - public_key: String, - version: String, - last_seen: u64, - location: String, -} diff --git a/validator/src/network/rest/presence/conversions.rs b/validator/src/network/rest/presence/conversions.rs deleted file mode 100644 index eae70296cf..0000000000 --- a/validator/src/network/rest/presence/conversions.rs +++ /dev/null @@ -1,135 +0,0 @@ -use super::models::Timestamp; -use crate::network::rest::presence::models::Mixnode as RestMixnode; -use crate::network::rest::presence::models::Topology as RestTopology; -use crate::services::mixmining::models::Mixnode as ServiceMixnode; -use crate::services::mixmining::models::Topology as ServiceTopology; -use std::convert::From; - -impl ServiceMixnode { - pub fn from_rest_mixnode_with_timestamp( - rest_mix: RestMixnode, - timestamp: Timestamp, - ) -> ServiceMixnode { - ServiceMixnode { - host: rest_mix.host, - last_seen: timestamp.into(), - location: rest_mix.location, - public_key: rest_mix.public_key, - stake: 0, - version: rest_mix.version, - } - } -} - -impl From for RestMixnode { - fn from(value: ServiceMixnode) -> RestMixnode { - RestMixnode { - host: value.host, - location: value.location, - public_key: value.public_key, - version: value.version, - } - } -} - -impl ServiceTopology { - #[cfg(test)] // un-testify this when you need it for real code, this kills warning - pub fn from_rest_topology_with_timestamp( - rest_topology: RestTopology, - timestamp: Timestamp, - ) -> ServiceTopology { - let mut converted_mixnodes: Vec = Vec::new(); - for mixnode in rest_topology.mixnodes { - converted_mixnodes.push(ServiceMixnode::from_rest_mixnode_with_timestamp( - mixnode, timestamp, - )); - } - ServiceTopology { - mixnodes: converted_mixnodes.to_vec(), - service_providers: vec![], // add these when conversions exist - validators: vec![], // add these when conversions exist - } - } -} - -impl From for RestTopology { - fn from(value: ServiceTopology) -> RestTopology { - let mut converted_mixnodes: Vec = Vec::new(); - for mixnode in value.mixnodes { - converted_mixnodes.push(mixnode.into()); - } - RestTopology { - mixnodes: converted_mixnodes.to_vec(), - service_providers: vec![], // add these when conversions exist - validators: vec![], // add these when conversions exist - } - } -} - -#[cfg(test)] -mod test_presence_conversions_for_mixmining_service { - fn rest_mixnode_fixture() -> RestMixnode { - RestMixnode { - host: "foo.org".to_owned(), - public_key: "abc".to_owned(), - location: "London".to_owned(), - version: "1.0.0".to_owned(), - } - } - - fn service_mixnode_fixture() -> ServiceMixnode { - ServiceMixnode { - host: "foo.org".to_owned(), - public_key: "abc".to_owned(), - last_seen: 1234, - location: "London".to_owned(), - stake: 0, - version: "1.0.0".to_owned(), - } - } - - use super::*; - - #[test] - fn test_building_service_mixnode_from_rest_mixnode() { - let rest_mixnode = rest_mixnode_fixture(); - let timestamp = Timestamp::default(); - let service_mixnode = - ServiceMixnode::from_rest_mixnode_with_timestamp(rest_mixnode.clone(), timestamp); - assert_eq!(service_mixnode.host, rest_mixnode.host); - assert_eq!(service_mixnode.public_key, rest_mixnode.public_key); - assert_eq!(service_mixnode.location, rest_mixnode.location); - assert_eq!(service_mixnode.stake, 0); - assert_eq!(service_mixnode.version, rest_mixnode.version); - // I'm not going to test the last_seen timestamp as I can't be bothered - // setting up a fake clock right now. - // The behaviour is: it should set time to SystemTime::now(). - } - - #[test] - fn test_building_rest_mixnode_from_service_mixnode() { - let service_mixnode = service_mixnode_fixture(); - let rest_mixnode = RestMixnode::from(service_mixnode.clone()); - assert_eq!(rest_mixnode.host, service_mixnode.host); - assert_eq!(rest_mixnode.public_key, service_mixnode.public_key); - assert_eq!(rest_mixnode.location, service_mixnode.location); - assert_eq!(rest_mixnode.version, service_mixnode.version); - } - - #[test] - fn test_building_service_topology_from_rest_topology() { - let rest_mixnode = rest_mixnode_fixture(); - let rest_topology = RestTopology { - mixnodes: vec![rest_mixnode.clone()], - service_providers: vec![], - validators: vec![], - }; - - let timestamp = Timestamp::default(); - let service_topology = - ServiceTopology::from_rest_topology_with_timestamp(rest_topology, timestamp); - let service_mixnode = - ServiceMixnode::from_rest_mixnode_with_timestamp(rest_mixnode, timestamp); - assert_eq!(service_mixnode, service_topology.mixnodes[0]); - } -} diff --git a/validator/src/network/rest/presence/mixnode.rs b/validator/src/network/rest/presence/mixnode.rs deleted file mode 100644 index aa57f6d2fa..0000000000 --- a/validator/src/network/rest/presence/mixnode.rs +++ /dev/null @@ -1,38 +0,0 @@ -use super::*; -use crate::network::rest::presence::models::Mixnode as PresenceMixnode; -use crate::services::mixmining::models::Mixnode as ServiceMixnode; -use bodyparser::Struct; -use iron::status; -use iron::Handler; -use models::Timestamp; - -pub struct CreatePresence { - service: Arc>, -} - -impl CreatePresence { - pub fn new(service: Arc>) -> CreatePresence { - CreatePresence { service } - } -} - -impl Handler for CreatePresence { - fn handle(&self, req: &mut Request) -> IronResult { - let json_parse = req.get::>(); - - match json_parse { - Ok(mixnode) => { - let mixnode = mixnode.expect("Unexpected JSON parsing problem"); - self.service - .lock() - .unwrap() - .add(ServiceMixnode::from_rest_mixnode_with_timestamp( - mixnode, - Timestamp::default(), - )); - Ok(Response::with(status::Created)) - } - Err(err) => Ok(Response::with((status::BadRequest, err.detail))), - } - } -} diff --git a/validator/src/network/rest/presence/mod.rs b/validator/src/network/rest/presence/mod.rs deleted file mode 100644 index 108d75277e..0000000000 --- a/validator/src/network/rest/presence/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -use super::*; - -mod conversions; -pub mod mixnode; -mod models; -pub mod topology; diff --git a/validator/src/network/rest/presence/models.rs b/validator/src/network/rest/presence/models.rs deleted file mode 100644 index b4efde2808..0000000000 --- a/validator/src/network/rest/presence/models.rs +++ /dev/null @@ -1,66 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::time::{SystemTime, UNIX_EPOCH}; - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Mixnode { - pub host: String, - pub public_key: String, - pub version: String, - pub location: String, -} - -#[derive(Serialize, Deserialize, Debug, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct ServiceProvider { - host: String, - public_key: String, - version: String, - last_seen: u64, - location: String, -} - -/// Topology shows us the current state of the overall Nym network -#[derive(Serialize, Deserialize, Debug, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct Topology { - pub mixnodes: Vec, - pub service_providers: Vec, - pub validators: Vec, -} - -#[derive(Serialize, Deserialize, Debug, PartialEq)] -#[serde(rename_all = "camelCase")] -pub struct Validator { - host: String, - public_key: String, - version: String, - last_seen: u64, - location: String, -} - -#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)] -pub struct Timestamp(u64); - -impl Default for Timestamp { - fn default() -> Timestamp { - Timestamp( - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_millis() as u64, - ) - } -} - -impl From for Timestamp { - fn from(v: u64) -> Timestamp { - Timestamp(v) - } -} - -impl Into for Timestamp { - fn into(self) -> u64 { - self.0 - } -} diff --git a/validator/src/network/rest/presence/topology.rs b/validator/src/network/rest/presence/topology.rs deleted file mode 100644 index 46517c62f7..0000000000 --- a/validator/src/network/rest/presence/topology.rs +++ /dev/null @@ -1,23 +0,0 @@ -use super::*; -use iron::status; -use iron::Handler; - -pub struct GetTopology { - service: Arc>, -} - -impl GetTopology { - pub fn new(service: Arc>) -> GetTopology { - GetTopology { service } - } -} - -impl Handler for GetTopology { - fn handle(&self, _req: &mut Request) -> IronResult { - println!("Getting topology!..."); - let service_topology = self.service.lock().unwrap().topology(); - let topology = models::Topology::from(service_topology); - let response = serde_json::to_string_pretty(&topology).unwrap(); - Ok(Response::with((status::Ok, response))) - } -} diff --git a/validator/src/network/rest/routes/mod.rs b/validator/src/network/rest/routes/mod.rs deleted file mode 100644 index fcd639a99f..0000000000 --- a/validator/src/network/rest/routes/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use iron::prelude::*; -use iron::status; - -pub mod topology; diff --git a/validator/src/network/rest/routes/topology.rs b/validator/src/network/rest/routes/topology.rs deleted file mode 100644 index d2783cbfc7..0000000000 --- a/validator/src/network/rest/routes/topology.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use super::*; -use crate::network::rest::models::presence::{MixNode, ServiceProvider, Topology, Validator}; - -pub fn get(_req: &mut Request) -> IronResult { - let topology = Topology { - mix_nodes: Vec::::new(), - service_providers: Vec::::new(), - validators: Vec::::new(), - }; - let response = serde_json::to_string_pretty(&topology).unwrap(); - Ok(Response::with((status::Ok, response))) -} diff --git a/validator/src/network/rest/staking/mod.rs b/validator/src/network/rest/staking/mod.rs deleted file mode 100644 index b4780ebde8..0000000000 --- a/validator/src/network/rest/staking/mod.rs +++ /dev/null @@ -1 +0,0 @@ -// pub struct StakeUpdate {} diff --git a/validator/src/network/tendermint/mod.rs b/validator/src/network/tendermint/mod.rs deleted file mode 100644 index 140a8153be..0000000000 --- a/validator/src/network/tendermint/mod.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use abci::*; -use byteorder::{BigEndian, ByteOrder}; - -// Convert incoming tx network data to the proper BigEndian size. txs.len() > 8 will return 0 -fn convert_tx(tx: &[u8]) -> u64 { - if tx.len() < 8 { - let pad = 8 - tx.len(); - let mut x = vec![0; pad]; - x.extend_from_slice(tx); - return BigEndian::read_u64(x.as_slice()); - } - BigEndian::read_u64(tx) -} - -pub struct Abci { - count: u64, -} - -impl Abci { - pub fn new() -> Abci { - Abci { count: 0 } - } - - pub async fn run(self) { - println!("* starting Tendermint abci"); - abci::run_local(self); - } -} - -impl abci::Application for Abci { - // Validate transactions. Rule: Transactions must be incremental: 1,2,3,4... - fn check_tx(&mut self, req: &RequestCheckTx) -> ResponseCheckTx { - // Get the Tx [u8] and convert to u64 - let c = convert_tx(req.get_tx()); - let mut response = ResponseCheckTx::new(); - - // Validation logic - if c != self.count + 1 { - response.set_code(1); - response.set_log(String::from("Count must be incremental!")); - return response; - } - - // Update state to keep state correct for next check_tx call - self.count = c; - response - } - - fn deliver_tx(&mut self, req: &RequestDeliverTx) -> ResponseDeliverTx { - // Get the Tx [u8] - let c = convert_tx(req.get_tx()); - // Update state - self.count = c; - // Return default code 0 == bueno - ResponseDeliverTx::new() - } - - fn commit(&mut self, _req: &RequestCommit) -> ResponseCommit { - // Create the response - let mut response = ResponseCommit::new(); - // Convert count to bits - let mut buf = [0; 8]; - BigEndian::write_u64(&mut buf, self.count); - // Set data so last state is included in the block - response.set_data(buf.to_vec()); - response - } -} diff --git a/validator/src/schema.rs b/validator/src/schema.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/validator/src/schema.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/validator/src/services/mixmining/db.rs b/validator/src/services/mixmining/db.rs deleted file mode 100644 index c53a2e19f0..0000000000 --- a/validator/src/services/mixmining/db.rs +++ /dev/null @@ -1,105 +0,0 @@ -use super::Mixnode; - -/// A (currently RAM-based) data store to keep tabs on which nodes have what -/// stake assigned to them. -#[derive(Clone, Debug, PartialEq)] -pub struct MixminingDb { - mixnodes: Vec, - capacity: usize, -} - -impl MixminingDb { - pub fn new() -> MixminingDb { - let mixnodes = Vec::::new(); - MixminingDb { - capacity: 6, - mixnodes, - } - } - - pub fn add(&mut self, mixnode: Mixnode) { - self.mixnodes.push(mixnode); - } - - pub fn get_mixnodes(&self) -> &Vec { - &self.mixnodes - } - - pub fn set_capacity(&mut self, capacity: usize) { - self.capacity = capacity; - } - - pub fn capacity(&self) -> usize { - self.capacity - } -} - -#[cfg(test)] -mod capacity { - use super::*; - - #[test] - fn starts_at_6() { - let db = MixminingDb::new(); - assert_eq!(6, db.capacity()); - } - - #[test] - fn setting_and_getting_work() { - let mut db = MixminingDb::new(); - db.set_capacity(1); - assert_eq!(1, db.capacity()); - } -} - -#[cfg(test)] -mod adding_and_retrieving_mixnodes { - use super::*; - - #[test] - fn add_and_retrieve_one_works() { - let node = fake_mixnode("London, UK"); - let mut db = MixminingDb::new(); - - db.add(node.clone()); - - assert_eq!(&node, db.get_mixnodes().first().unwrap()); - } - - #[test] - fn add_and_retrieve_two_works() { - let node1 = fake_mixnode("London, UK"); - let node2 = fake_mixnode("Neuchatel"); - let mut db = MixminingDb::new(); - - db.add(node1.clone()); - db.add(node2.clone()); - - assert_eq!(node1, db.get_mixnodes()[0]); - assert_eq!(node2, db.get_mixnodes()[1]); - } - - #[test] - fn starts_empty() { - let db = MixminingDb::new(); - assert_eq!(0, db.mixnodes.len()); - } - - #[test] - fn calling_list_when_empty_returns_empty_vec() { - let db = MixminingDb::new(); - let empty: Vec = vec![]; - assert_eq!(&empty, db.get_mixnodes()); - } - - fn fake_mixnode(location: &str) -> Mixnode { - Mixnode { - host: String::from("foo.com"), - last_seen: 123, - location: String::from(location), - public_key: String::from("abc123"), - stake: 8, - version: String::from("1.0"), - } - } -} diff --git a/validator/src/services/mixmining/mod.rs b/validator/src/services/mixmining/mod.rs deleted file mode 100644 index 42af4c865f..0000000000 --- a/validator/src/services/mixmining/mod.rs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use db::MixminingDb; -use models::*; - -pub mod db; -pub mod models; -mod tests; - -pub struct Service { - db: MixminingDb, -} - -/// The mixmining::Service provides logic for updating and slashing mixnode -/// stake, retrieving lists of mixnodes based on stake, and adding/removing -/// mixnodes from the active set. It monitors mixnodes and rewards or slashes -/// based on the observed quality of service provided by a given mixnode. -/// -/// Mixing and staking interact. Mixnodes first need to announce -/// their presence to the validators. -/// -/// The mixnode then goes into the stack of available mixnodes. -/// -/// However, it's not necessarily going to start actively mixing traffic. -/// That depends on how much stake is riding on it, and how much capacity the -/// network requires right now. We depend on the wisdom of stakers to put their -/// money on trustworthy mixnodes. -/// -/// The active set of mixnodes will be able to expand or contract based on capacity. -/// For now, we simply take the top nodes available, ordered by -/// . -/// -/// A lot is going to need to change here. Commented code is here mainly to -/// quickly sketch out the guts of the mixmining and staking service. This is not the basis -/// of our real staking system quite yet - it's a way to start getting the system -/// to function with all the different node types to start talking to each other, -/// and will be dramatically reworked over the next few months. -impl Service { - pub fn new(db: MixminingDb) -> Service { - Service { db } - } - - // Add a mixnode so that it becomes part of the possible mixnode set. - pub fn add(&mut self, mixnode: Mixnode) { - self.db.add(mixnode); - } - - pub fn topology(&self) -> Topology { - let mixnodes = self.db.get_mixnodes(); - let service_providers: Vec = vec![]; - let validators: Vec = vec![]; - Topology::new(mixnodes.to_vec(), service_providers, validators) - } - - pub fn set_capacity(&mut self, capacity: usize) { - self.db.set_capacity(capacity); - } - - /// A fake capacity, so we can take the top n mixnodes based on stake - pub fn capacity(&self) -> usize { - self.db.capacity() - } - - /* - - /// Update (or create) a given mixnode stake, identified by the mixnode's public key - fn update(&self, public_key: &str, amount: u64) { - // retrieve the given Mixnode from the database and update its stake - } - - /// For now, we have no notion of measuring capacity. For now just use capacity(). - fn active_mixnodes(&self) -> Vec { - Vec::::new() - // hit the database - } - - - /// Remove a mixnode from the active set in a way that does not impact its stake. - /// In a more built-out system, this method would mean: - /// "mixnode x has done its job well and requested to leave, so it can be removed - /// at the end of an epoch." - fn remove(&self, public_key: &str) { - // free locked up stake back to originating stakeholder - // remove the mixnode from the database - } - - /// Add the given amount of stake to the given Mixnode. Presumably it has done - /// its job well. - fn reward(&self, public_key: &str, amount: u64) {} - - /// Slash a mixnode's stake based on bad performance or detected malign intent. - fn slash(&self, public_key: &str, amount: u64) { - // transfer slashed stake amount to reserve fund - // retrieve the mixnode from the database, and decrement its stake amount - // by the amount given. - } - - /// Slash a mixnode's stake and immediately remove it from the mixnode set. - fn slash_remove(&self, public_key: String, amount: u64) { - // call slash (the method, not the guitarist) - // remove the mixnode from the database - } - */ -} - -#[cfg(test)] -mod mixnodes { - use super::*; - - #[test] - fn adding_and_retrieving_works() { - let mock_db = MixminingDb::new(); - let mut service = Service::new(mock_db); - let node1 = tests::fake_mixnode("London, UK"); - - service.add(node1.clone()); - let nodes = service.topology().mixnodes; - assert_eq!(1, nodes.len()); - assert_eq!(node1.clone(), nodes[0]); - let node2 = tests::fake_mixnode("Neuchatel"); - - service.add(node2.clone()); - let nodes = service.topology().mixnodes; - assert_eq!(2, nodes.len()); - assert_eq!(node1, nodes[0]); - assert_eq!(node2, nodes[1]); - } -} - -#[cfg(test)] -mod constructor { - use super::*; - - #[test] - fn sets_database() { - let db = db::MixminingDb::new(); - let service = Service::new(db.clone()); - - assert_eq!(db, service.db); - } -} - -#[cfg(test)] -mod capacity { - use super::*; - - #[test] - fn setting_capacity_sends_correct_value_to_datastore() { - let mock_db = db::MixminingDb::new(); - let mut service = Service::new(mock_db); - - service.set_capacity(3); - - assert_eq!(3, service.capacity()); - } - - #[test] - fn getting_capacity_works() { - let mut mock_db = db::MixminingDb::new(); - mock_db.set_capacity(3); - let service = Service::new(mock_db); - assert_eq!(3, service.capacity()); - } -} diff --git a/validator/src/services/mixmining/models.rs b/validator/src/services/mixmining/models.rs deleted file mode 100644 index bff8702ed7..0000000000 --- a/validator/src/services/mixmining/models.rs +++ /dev/null @@ -1,51 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Mixnode { - pub host: String, - pub public_key: String, - pub last_seen: u64, - pub location: String, - pub stake: u64, - pub version: String, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ServiceProvider { - host: String, - public_key: String, - version: String, - last_seen: u64, - location: String, -} - -/// Topology shows us the current state of the overall Nym network -#[derive(Serialize, Deserialize, Debug)] -pub struct Topology { - pub mixnodes: Vec, - pub service_providers: Vec, - pub validators: Vec, -} - -impl Topology { - pub fn new( - mixnodes: Vec, - service_providers: Vec, - validators: Vec, - ) -> Topology { - Topology { - mixnodes, - service_providers, - validators, - } - } -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct Validator { - host: String, - public_key: String, - version: String, - last_seen: u64, - location: String, -} diff --git a/validator/src/services/mixmining/tests/mod.rs b/validator/src/services/mixmining/tests/mod.rs deleted file mode 100644 index fac930f902..0000000000 --- a/validator/src/services/mixmining/tests/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[cfg(test)] -pub fn fake_mixnode(location: &str) -> super::Mixnode { - super::Mixnode { - host: String::from("foo.com"), - last_seen: 123, - location: String::from(location), - public_key: String::from("abc123"), - stake: 8, - version: String::from("1.0"), - } -} diff --git a/validator/src/services/mod.rs b/validator/src/services/mod.rs deleted file mode 100644 index 90af524fc8..0000000000 --- a/validator/src/services/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -pub mod mixmining; diff --git a/validator/src/validator.rs b/validator/src/validator.rs deleted file mode 100644 index 195a6ae9db..0000000000 --- a/validator/src/validator.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// use crate::config::Config; -use crate::network::rest; -use crate::network::tendermint; -use crate::services::mixmining; -use tokio::runtime::Runtime; - -pub struct Validator { - // when you re-introduce keys, check which ones you want: - // MixIdentityKeyPair (like 'nym-client' ) <- probably that one (after maybe renaming to just identity::KeyPair) - // encryption::KeyPair (like 'nym-mixnode' or 'sfw-provider') - tendermint_abci: tendermint::Abci, - rest_api: rest::Api, -} - -impl Validator { - pub fn new() -> Self { - let mixmining_db = mixmining::db::MixminingDb::new(); - let mixmining_service = mixmining::Service::new(mixmining_db); - - let rest_api = rest::Api::new(mixmining_service); - - Validator { - rest_api, - - // perhaps you might want to pass &config to the constructor - // there to get the config.tendermint (assuming you create appropriate fields + getters) - tendermint_abci: tendermint::Abci::new(), - } - } - - // TODO: Fix Tendermint startup here, see https://github.com/nymtech/nym/issues/147 - pub fn start(self) { - let mut rt = Runtime::new().unwrap(); - rt.spawn(self.rest_api.run()); - rt.spawn(self.tendermint_abci.run()); - - // TODO: this message is going to come out of order (if at all), as spawns are async, see issue above - println!("Validator startup complete."); - rt.block_on(blocker()); - } -} - -pub async fn blocker() {} // once Tendermint unblocks us, make this block forever. From 174206ca3676afbe403e4256f015da1cd7bc0b53 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Tue, 13 Oct 2020 18:36:13 +0100 Subject: [PATCH 2/7] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index f104d9a3dc..8ef27ffaca 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@ ## The Nym Privacy Platform -This repository contains the full Nym platform. +This repository contains the Nym mixnet. The platform is composed of multiple Rust crates. Top-level executable binary crates include: * nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers. * nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes. * nym-sfw-provider - a store-and-forward service provider. The provider acts sort of like a mailbox for mixnet messages. -* nym-validator - currently just starting development. Handles consensus ordering of transactions, mixmining, and coconut credential generation and validation. [![Build Status](https://travis-ci.com/nymtech/nym.svg?branch=develop)](https://travis-ci.com/nymtech/nym) From e7bd27a2d0008c6323a65f674970fe76b872c505 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Tue, 13 Oct 2020 18:37:08 +0100 Subject: [PATCH 3/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ef27ffaca..08b33bddb6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr * nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers. * nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes. -* nym-sfw-provider - a store-and-forward service provider. The provider acts sort of like a mailbox for mixnet messages. +* nym-gateway - acts sort of like a mailbox for mixnet messages, removing the need for directly delivery to potentially offline or firewalled devices. [![Build Status](https://travis-ci.com/nymtech/nym.svg?branch=develop)](https://travis-ci.com/nymtech/nym) From c8bf454ccc73c613aa8c9f6d02189b0e24761680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 14 Oct 2020 10:36:10 +0100 Subject: [PATCH 4/7] Feature/upgrade command (#381) * Exposed version parsing from version checker * Ability to upgrade mixnode from 0.8.X to 0.9.0 * Ability to upgrade gateway from 0.8.X to 0.9.0 * Ability to upgrade native client from 0.8.X to 0.9.0 * Ability to upgrade socks5 client from 0.8.X to 0.9.0 * Typo * Minor renaming * Preventing upgrade if current is not a release version * Additional upgrade restrictions * Corrected version bound --- Cargo.lock | 4 + clients/client-core/src/config/mod.rs | 16 +++ clients/native/Cargo.toml | 1 + clients/native/src/client/config/mod.rs | 1 + clients/native/src/commands/mod.rs | 5 +- clients/native/src/commands/upgrade.rs | 171 ++++++++++++++++++++++++ clients/native/src/main.rs | 2 + clients/socks5/Cargo.toml | 1 + clients/socks5/src/client/config/mod.rs | 1 + clients/socks5/src/commands/mod.rs | 5 +- clients/socks5/src/commands/upgrade.rs | 171 ++++++++++++++++++++++++ clients/socks5/src/main.rs | 2 + common/version-checker/src/lib.rs | 7 +- gateway/Cargo.toml | 1 + gateway/src/commands/mod.rs | 5 +- gateway/src/commands/upgrade.rs | 170 +++++++++++++++++++++++ gateway/src/config/mod.rs | 16 +++ gateway/src/main.rs | 2 + mixnode/Cargo.toml | 1 + mixnode/src/commands/mod.rs | 5 +- mixnode/src/commands/upgrade.rs | 170 +++++++++++++++++++++++ mixnode/src/config/mod.rs | 16 +++ mixnode/src/main.rs | 2 + 23 files changed, 766 insertions(+), 9 deletions(-) create mode 100644 clients/native/src/commands/upgrade.rs create mode 100644 clients/socks5/src/commands/upgrade.rs create mode 100644 gateway/src/commands/upgrade.rs create mode 100644 mixnode/src/commands/upgrade.rs diff --git a/Cargo.lock b/Cargo.lock index 2166190574..ae3ec06761 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1550,6 +1550,7 @@ dependencies = [ "tokio-tungstenite", "topology", "url", + "version-checker", "websocket-requests", ] @@ -1601,6 +1602,7 @@ dependencies = [ "tokio-tungstenite", "tokio-util", "tungstenite", + "version-checker", ] [[package]] @@ -1627,6 +1629,7 @@ dependencies = [ "tokio", "tokio-util", "topology", + "version-checker", ] [[package]] @@ -1656,6 +1659,7 @@ dependencies = [ "tempfile", "tokio", "topology", + "version-checker", ] [[package]] diff --git a/clients/client-core/src/config/mod.rs b/clients/client-core/src/config/mod.rs index 1e04d21964..5c865fa312 100644 --- a/clients/client-core/src/config/mod.rs +++ b/clients/client-core/src/config/mod.rs @@ -21,6 +21,8 @@ use std::time::Duration; pub mod persistence; +pub const MISSING_VALUE: &str = "MISSING VALUE"; + // 'CLIENT' const DEFAULT_DIRECTORY_SERVER: &str = "https://directory.nymtech.net"; // 'DEBUG' @@ -39,6 +41,10 @@ const DEFAULT_VPN_KEY_REUSE_LIMIT: usize = 1000; const ZERO_DELAY: Duration = Duration::from_nanos(0); +pub fn missing_string_value() -> String { + MISSING_VALUE.to_string() +} + #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] pub struct Config { @@ -140,6 +146,10 @@ impl Config { self.debug.vpn_key_reuse_limit = Some(reuse_limit) } + pub fn set_custom_version(&mut self, version: &str) { + self.client.version = version.to_string(); + } + pub fn get_id(&self) -> String { self.client.id.clone() } @@ -251,6 +261,10 @@ impl Config { ), } } + + pub fn get_version(&self) -> &str { + &self.client.version + } } impl Default for Config { @@ -267,6 +281,7 @@ impl Default for Config { #[serde(deny_unknown_fields)] pub struct Client { /// Version of the client for which this configuration was created. + #[serde(default = "missing_string_value")] version: String, /// ID specifies the human readable ID of this particular client. @@ -278,6 +293,7 @@ pub struct Client { /// Special mode of the system such that all messages are sent as soon as they are received /// and no cover traffic is generated. If set all message delays are set to 0 and overwriting /// 'Debug' values will have no effect. + #[serde(default)] vpn_mode: bool, /// Path to file containing private identity key. diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index f8d24a72a0..54e55f4c55 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -40,6 +40,7 @@ nymsphinx = { path = "../../common/nymsphinx" } pemstore = { path = "../../common/pemstore" } topology = { path = "../../common/topology" } websocket-requests = { path = "websocket-requests" } +version-checker = { path = "../../common/version-checker" } [dev-dependencies] tempfile = "3.1.0" diff --git a/clients/native/src/client/config/mod.rs b/clients/native/src/client/config/mod.rs index 9de9b8ee90..d100ce72dd 100644 --- a/clients/native/src/client/config/mod.rs +++ b/clients/native/src/client/config/mod.rs @@ -14,6 +14,7 @@ use crate::client::config::template::config_template; use client_core::config::Config as BaseConfig; +pub use client_core::config::MISSING_VALUE; use config::NymConfig; use serde::{Deserialize, Serialize}; use std::path::PathBuf; diff --git a/clients/native/src/commands/mod.rs b/clients/native/src/commands/mod.rs index 927ff08736..f7792206c3 100644 --- a/clients/native/src/commands/mod.rs +++ b/clients/native/src/commands/mod.rs @@ -15,8 +15,9 @@ use crate::client::config::{Config, SocketType}; use clap::ArgMatches; -pub mod init; -pub mod run; +pub(crate) mod init; +pub(crate) mod run; +pub(crate) mod upgrade; pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config { if let Some(directory) = matches.value_of("directory") { diff --git a/clients/native/src/commands/upgrade.rs b/clients/native/src/commands/upgrade.rs new file mode 100644 index 0000000000..47802b1eab --- /dev/null +++ b/clients/native/src/commands/upgrade.rs @@ -0,0 +1,171 @@ +// Copyright 2020 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::client::config::{Config, MISSING_VALUE}; +use clap::{App, Arg, ArgMatches}; +use config::NymConfig; +use std::fmt::Display; +use std::process; +use version_checker::{parse_version, Version}; + +fn print_start_upgrade(from: D1, to: D2) { + println!( + "\n==================\nTrying to upgrade mixnode from {} to {} ...", + from, to + ); +} + +fn print_failed_upgrade(from: D1, to: D2) { + eprintln!( + "Upgrade from {} to {} failed!\n==================\n", + from, to + ); +} + +fn print_successful_upgrade(from: D1, to: D2) { + println!( + "Upgrade from {} to {} was successful!\n==================\n", + from, to + ); +} + +fn pre_090_upgrade(from: &str, mut config: Config) -> Config { + // this is not extracted to separate function as you only have to manually pass version + // if upgrading from pre090 version + let from = match from.strip_prefix("v") { + Some(stripped) => stripped, + None => from, + }; + + let from = match from.strip_prefix("V") { + Some(stripped) => stripped, + None => from, + }; + + let from_version = parse_version(from).expect("invalid version provided!"); + if from_version.major == 0 && from_version.minor < 8 { + // technically this could be implemented, but is there any point in that? + eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead"); + process::exit(1) + } + + if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 { + eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version"); + process::exit(1) + } + + // note: current is guaranteed to not have any `build` information suffix (nor pre-release + // information), as this was asserted at the beginning of this command) + // + // upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate + // step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0) + // this way we don't need to have all the crazy paths on how to upgrade from any version to any + // other version. We just upgrade one minor version at a time. + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + let to_version = if current.major == 0 && current.minor == 9 { + current + } else { + Version::new(0, 9, 0) + }; + + print_start_upgrade(&from_version, &to_version); + + config + .get_base_mut() + .set_custom_version(to_version.to_string().as_ref()); + + config.save_to_file(None).unwrap_or_else(|err| { + eprintln!("failed to overwrite config file! - {:?}", err); + print_failed_upgrade(&from_version, &to_version); + process::exit(1); + }); + + print_successful_upgrade(from_version, to_version); + + config +} + +pub fn command_args<'a, 'b>() -> App<'a, 'b> { + App::new("upgrade").about("Try to upgrade the mixnode") + .arg( + Arg::with_name("id") + .long("id") + .help("Id of the nym-client we want to upgrade") + .takes_value(true) + .required(true), + ) + // the rest of arguments depend on the upgrade path + .arg(Arg::with_name("current version") + .long("current-version") + .help("REQUIRED FOR PRE-0.9.0 UPGRADES. Self provided version of the nym-client if none is available in the config. NOTE: if provided incorrectly, results may be catastrophic.") + .takes_value(true) + ) +} + +pub fn execute(matches: &ArgMatches) { + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + + // technically this is not a correct way of checking it as a released version might contain valid build identifiers + // however, we are not using them ourselves at the moment and hence it should be fine. + // if we change our mind, we could easily tweak this code + if current.is_prerelease() || !current.build.is_empty() { + eprintln!( + "Trying to upgrade to a non-released version {}. This is not supported!", + current + ); + process::exit(1) + } + + let id = matches.value_of("id").unwrap(); + + let mut existing_config = Config::load_from_file(None, Some(id)).unwrap_or_else(|err| { + eprintln!("failed to load existing config file! - {:?}", err); + process::exit(1) + }); + + // versions fields were added in 0.9.0 + if existing_config.get_base().get_version() == MISSING_VALUE { + let self_reported_version = matches.value_of("current version").unwrap_or_else(|| { + eprintln!( + "trying to upgrade from pre v0.9.0 without providing current system version!" + ); + process::exit(1) + }); + + // upgrades up to 0.9.0 + existing_config = pre_090_upgrade(self_reported_version, existing_config); + } + + let config_version = + Version::parse(existing_config.get_base().get_version()).unwrap_or_else(|err| { + eprintln!("failed to parse node version! - {:?}", err); + process::exit(1) + }); + + if config_version.is_prerelease() || !config_version.build.is_empty() { + eprintln!( + "Trying to upgrade to from non-released version {}. This is not supported!", + current + ); + process::exit(1) + } + + // here be upgrade path to 0.10.0 and beyond based on version number from config + if config_version == current { + println!("You're using the most recent version!"); + } else { + eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue!", config_version, current); + process::exit(1) + } +} diff --git a/clients/native/src/main.rs b/clients/native/src/main.rs index 21f5cfc601..a59fd48239 100644 --- a/clients/native/src/main.rs +++ b/clients/native/src/main.rs @@ -29,6 +29,7 @@ fn main() { .about("Implementation of the Nym Client") .subcommand(commands::init::command_args()) .subcommand(commands::run::command_args()) + .subcommand(commands::upgrade::command_args()) .get_matches(); execute(arg_matches); @@ -38,6 +39,7 @@ fn execute(matches: ArgMatches) { match matches.subcommand() { ("init", Some(m)) => commands::init::execute(m), ("run", Some(m)) => commands::run::execute(m), + ("upgrade", Some(m)) => commands::upgrade::execute(m), _ => println!("{}", usage()), } } diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index ceed6abfce..e81ba3a875 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -33,6 +33,7 @@ ordered-buffer = {path = "../../common/socks5/ordered-buffer"} socks5-requests = { path = "../../common/socks5/requests" } topology = { path = "../../common/topology" } proxy-helpers = { path = "../../common/socks5/proxy-helpers" } +version-checker = { path = "../../common/version-checker" } [dev-dependencies] tempfile = "3.1.0" \ No newline at end of file diff --git a/clients/socks5/src/client/config/mod.rs b/clients/socks5/src/client/config/mod.rs index 6779ade230..d49b5b7d1b 100644 --- a/clients/socks5/src/client/config/mod.rs +++ b/clients/socks5/src/client/config/mod.rs @@ -14,6 +14,7 @@ use crate::client::config::template::config_template; use client_core::config::Config as BaseConfig; +pub use client_core::config::MISSING_VALUE; use config::NymConfig; use nymsphinx::addressing::clients::Recipient; use serde::{Deserialize, Serialize}; diff --git a/clients/socks5/src/commands/mod.rs b/clients/socks5/src/commands/mod.rs index dabb25bdf8..4e72c17f40 100644 --- a/clients/socks5/src/commands/mod.rs +++ b/clients/socks5/src/commands/mod.rs @@ -15,8 +15,9 @@ use crate::client::config::Config; use clap::ArgMatches; -pub mod init; -pub mod run; +pub(crate) mod init; +pub(crate) mod run; +pub(crate) mod upgrade; pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config { if let Some(directory) = matches.value_of("directory") { diff --git a/clients/socks5/src/commands/upgrade.rs b/clients/socks5/src/commands/upgrade.rs new file mode 100644 index 0000000000..3e70b0b319 --- /dev/null +++ b/clients/socks5/src/commands/upgrade.rs @@ -0,0 +1,171 @@ +// Copyright 2020 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::client::config::{Config, MISSING_VALUE}; +use clap::{App, Arg, ArgMatches}; +use config::NymConfig; +use std::fmt::Display; +use std::process; +use version_checker::{parse_version, Version}; + +fn print_start_upgrade(from: D1, to: D2) { + println!( + "\n==================\nTrying to upgrade mixnode from {} to {} ...", + from, to + ); +} + +fn print_failed_upgrade(from: D1, to: D2) { + eprintln!( + "Upgrade from {} to {} failed!\n==================\n", + from, to + ); +} + +fn print_successful_upgrade(from: D1, to: D2) { + println!( + "Upgrade from {} to {} was successful!\n==================\n", + from, to + ); +} + +fn pre_090_upgrade(from: &str, mut config: Config) -> Config { + // this is not extracted to separate function as you only have to manually pass version + // if upgrading from pre090 version + let from = match from.strip_prefix("v") { + Some(stripped) => stripped, + None => from, + }; + + let from = match from.strip_prefix("V") { + Some(stripped) => stripped, + None => from, + }; + + let from_version = parse_version(from).expect("invalid version provided!"); + if from_version.major == 0 && from_version.minor < 8 { + // technically this could be implemented, but is there any point in that? + eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead"); + process::exit(1) + } + + if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 { + eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version"); + process::exit(1) + } + + // note: current is guaranteed to not have any `build` information suffix (nor pre-release + // information), as this was asserted at the beginning of this command) + // + // upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate + // step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0) + // this way we don't need to have all the crazy paths on how to upgrade from any version to any + // other version. We just upgrade one minor version at a time. + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + let to_version = if current.major == 0 && current.minor == 9 { + current + } else { + Version::new(0, 9, 0) + }; + + print_start_upgrade(&from_version, &to_version); + + config + .get_base_mut() + .set_custom_version(to_version.to_string().as_ref()); + + config.save_to_file(None).unwrap_or_else(|err| { + eprintln!("failed to overwrite config file! - {:?}", err); + print_failed_upgrade(&from_version, &to_version); + process::exit(1); + }); + + print_successful_upgrade(from_version, to_version); + + config +} + +pub fn command_args<'a, 'b>() -> App<'a, 'b> { + App::new("upgrade").about("Try to upgrade the mixnode") + .arg( + Arg::with_name("id") + .long("id") + .help("Id of the nym-socks5-client we want to upgrade") + .takes_value(true) + .required(true), + ) + // the rest of arguments depend on the upgrade path + .arg(Arg::with_name("current version") + .long("current-version") + .help("REQUIRED FOR PRE-0.9.0 UPGRADES. Self provided version of the nym-socks5-client if none is available in the config. NOTE: if provided incorrectly, results may be catastrophic.") + .takes_value(true) + ) +} + +pub fn execute(matches: &ArgMatches) { + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + + // technically this is not a correct way of checking it as a released version might contain valid build identifiers + // however, we are not using them ourselves at the moment and hence it should be fine. + // if we change our mind, we could easily tweak this code + if current.is_prerelease() || !current.build.is_empty() { + eprintln!( + "Trying to upgrade to a non-released version {}. This is not supported!", + current + ); + process::exit(1) + } + + let id = matches.value_of("id").unwrap(); + + let mut existing_config = Config::load_from_file(None, Some(id)).unwrap_or_else(|err| { + eprintln!("failed to load existing config file! - {:?}", err); + process::exit(1) + }); + + // versions fields were added in 0.9.0 + if existing_config.get_base().get_version() == MISSING_VALUE { + let self_reported_version = matches.value_of("current version").unwrap_or_else(|| { + eprintln!( + "trying to upgrade from pre v0.9.0 without providing current system version!" + ); + process::exit(1) + }); + + // upgrades up to 0.9.0 + existing_config = pre_090_upgrade(self_reported_version, existing_config); + } + + let config_version = + Version::parse(existing_config.get_base().get_version()).unwrap_or_else(|err| { + eprintln!("failed to parse node version! - {:?}", err); + process::exit(1) + }); + + if config_version.is_prerelease() || !config_version.build.is_empty() { + eprintln!( + "Trying to upgrade to from non-released version {}. This is not supported!", + current + ); + process::exit(1) + } + + // here be upgrade path to 0.10.0 and beyond based on version number from config + if config_version == current { + println!("You're using the most recent version!"); + } else { + eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue!", config_version, current); + process::exit(1) + } +} diff --git a/clients/socks5/src/main.rs b/clients/socks5/src/main.rs index 76bc756136..a04f8ec90d 100644 --- a/clients/socks5/src/main.rs +++ b/clients/socks5/src/main.rs @@ -29,6 +29,7 @@ fn main() { .about("A Socks5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address") .subcommand(commands::init::command_args()) .subcommand(commands::run::command_args()) + .subcommand(commands::upgrade::command_args()) .get_matches(); execute(arg_matches); @@ -38,6 +39,7 @@ fn execute(matches: ArgMatches) { match matches.subcommand() { ("init", Some(m)) => commands::init::execute(m), ("run", Some(m)) => commands::run::execute(m), + ("upgrade", Some(m)) => commands::upgrade::execute(m), _ => println!("{}", usage()), } } diff --git a/common/version-checker/src/lib.rs b/common/version-checker/src/lib.rs index 3503c89a7b..46aafc2c80 100644 --- a/common/version-checker/src/lib.rs +++ b/common/version-checker/src/lib.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use semver::Version; +use semver::SemVerError; +pub use semver::Version; /// Checks whether given `version` is compatible with a given semantic version requirement `req` /// according to major-minor semver rules. The semantic version requirement can be passed as a full, @@ -32,6 +33,10 @@ pub fn is_minor_version_compatible(version: &str, req: &str) -> bool { expected_version.major == req_version.major && expected_version.minor == req_version.minor } +pub fn parse_version(raw_version: &str) -> Result { + Version::parse(raw_version) +} + #[cfg(test)] mod tests { use super::*; diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 1c58b7c036..ea4a9ea0c7 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -31,6 +31,7 @@ mixnet-client = { path = "../common/client-libs/mixnet-client" } mixnode-common = { path = "../common/mixnode-common" } nymsphinx = { path = "../common/nymsphinx" } pemstore = { path = "../common/pemstore" } +version-checker = { path = "../common/version-checker" } [dependencies.tungstenite] version = "0.11" diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index 4a8c3eeff8..2fd55cffbb 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -15,8 +15,9 @@ use crate::config::Config; use clap::ArgMatches; -pub mod init; -pub mod run; +pub(crate) mod init; +pub(crate) mod run; +pub(crate) mod upgrade; pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config { let mut was_mix_host_overridden = false; diff --git a/gateway/src/commands/upgrade.rs b/gateway/src/commands/upgrade.rs new file mode 100644 index 0000000000..8085a7c8e3 --- /dev/null +++ b/gateway/src/commands/upgrade.rs @@ -0,0 +1,170 @@ +// Copyright 2020 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::config::{Config, MISSING_VALUE}; +use clap::{App, Arg, ArgMatches}; +use config::NymConfig; +use std::fmt::Display; +use std::process; +use version_checker::{parse_version, Version}; + +fn print_start_upgrade(from: D1, to: D2) { + println!( + "\n==================\nTrying to upgrade gateway from {} to {} ...", + from, to + ); +} + +fn print_failed_upgrade(from: D1, to: D2) { + eprintln!( + "Upgrade from {} to {} failed!\n==================\n", + from, to + ); +} + +fn print_successful_upgrade(from: D1, to: D2) { + println!( + "Upgrade from {} to {} was successful!\n==================\n", + from, to + ); +} + +fn pre_090_upgrade(from: &str, config: Config) -> Config { + // this is not extracted to separate function as you only have to manually pass version + // if upgrading from pre090 version + let from = match from.strip_prefix("v") { + Some(stripped) => stripped, + None => from, + }; + + let from = match from.strip_prefix("V") { + Some(stripped) => stripped, + None => from, + }; + + let from_version = parse_version(from).expect("invalid version provided!"); + if from_version.major == 0 && from_version.minor < 8 { + // technically this could be implemented, but is there any point in that? + eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead"); + process::exit(1) + } + + if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 { + eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version"); + process::exit(1) + } + + // note: current is guaranteed to not have any `build` information suffix (nor pre-release + // information), as this was asserted at the beginning of this command) + // + // upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate + // step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0) + // this way we don't need to have all the crazy paths on how to upgrade from any version to any + // other version. We just upgrade one minor version at a time. + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + let to_version = if current.major == 0 && current.minor == 9 { + current + } else { + Version::new(0, 9, 0) + }; + + print_start_upgrade(&from_version, &to_version); + + let upgraded_config = config.with_custom_version(to_version.to_string().as_ref()); + // TODO: THIS IS INCOMPLETE AS ONCE PRESENCE IS REMOVED IN 0.9.0 IT WILL ALSO NEED + // TO BE PURGED FROM CONFIG + + upgraded_config.save_to_file(None).unwrap_or_else(|err| { + eprintln!("failed to overwrite config file! - {:?}", err); + print_failed_upgrade(&from_version, &to_version); + process::exit(1); + }); + + print_successful_upgrade(from_version, to_version); + + upgraded_config +} + +pub fn command_args<'a, 'b>() -> App<'a, 'b> { + App::new("upgrade").about("Try to upgrade the gateway") + .arg( + Arg::with_name("id") + .long("id") + .help("Id of the nym-gateway we want to upgrade") + .takes_value(true) + .required(true), + ) + // the rest of arguments depend on the upgrade path + .arg(Arg::with_name("current version") + .long("current-version") + .help("REQUIRED FOR PRE-0.9.0 UPGRADES. Self provided version of the nym-gateway if none is available in the config. NOTE: if provided incorrectly, results may be catastrophic.") + .takes_value(true) + ) +} + +pub fn execute(matches: &ArgMatches) { + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + + // technically this is not a correct way of checking it as a released version might contain valid build identifiers + // however, we are not using them ourselves at the moment and hence it should be fine. + // if we change our mind, we could easily tweak this code + if current.is_prerelease() || !current.build.is_empty() { + eprintln!( + "Trying to upgrade to a non-released version {}. This is not supported!", + current + ); + process::exit(1) + } + + let id = matches.value_of("id").unwrap(); + + let mut existing_config = Config::load_from_file(None, Some(id)).unwrap_or_else(|err| { + eprintln!("failed to load existing config file! - {:?}", err); + process::exit(1) + }); + + // versions fields were added in 0.9.0 + if existing_config.get_version() == MISSING_VALUE { + let self_reported_version = matches.value_of("current version").unwrap_or_else(|| { + eprintln!( + "trying to upgrade from pre v0.9.0 without providing current system version!" + ); + process::exit(1) + }); + + // upgrades up to 0.9.0 + existing_config = pre_090_upgrade(self_reported_version, existing_config); + } + + let config_version = Version::parse(existing_config.get_version()).unwrap_or_else(|err| { + eprintln!("failed to parse node version! - {:?}", err); + process::exit(1) + }); + + if config_version.is_prerelease() || !config_version.build.is_empty() { + eprintln!( + "Trying to upgrade to from non-released version {}. This is not supported!", + current + ); + process::exit(1) + } + + // here be upgrade path to 0.10.0 and beyond based on version number from config + if config_version == current { + println!("You're using the most recent version!"); + } else { + eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue!", config_version, current); + process::exit(1) + } +} diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 276c5ae6df..cd59b82aa8 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -24,6 +24,8 @@ use std::time; pub mod persistence; mod template; +pub(crate) const MISSING_VALUE: &str = "MISSING VALUE"; + // 'GATEWAY' const DEFAULT_MIX_LISTENING_PORT: u16 = 1789; const DEFAULT_CLIENT_LISTENING_PORT: u16 = 9000; @@ -90,6 +92,10 @@ impl NymConfig for Config { } } +pub fn missing_string_value() -> String { + MISSING_VALUE.to_string() +} + impl Config { pub fn new>(id: S) -> Self { Config::default().with_id(id) @@ -322,6 +328,11 @@ impl Config { self } + pub fn with_custom_version(mut self, version: &str) -> Self { + self.gateway.version = version.to_string(); + self + } + // getters pub fn get_config_file_save_location(&self) -> PathBuf { self.config_directory().join(Self::config_file_name()) @@ -402,12 +413,17 @@ impl Config { pub fn get_cache_entry_ttl(&self) -> time::Duration { time::Duration::from_millis(self.debug.cache_entry_ttl) } + + pub fn get_version(&self) -> &str { + &self.gateway.version + } } #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] pub struct Gateway { /// Version of the gateway for which this configuration was created. + #[serde(default = "missing_string_value")] version: String, /// ID specifies the human readable ID of this particular gateway. diff --git a/gateway/src/main.rs b/gateway/src/main.rs index 3adbae7295..e9bdf86443 100644 --- a/gateway/src/main.rs +++ b/gateway/src/main.rs @@ -29,6 +29,7 @@ fn main() { .about("Implementation of the Nym Mixnet Gateway") .subcommand(commands::init::command_args()) .subcommand(commands::run::command_args()) + .subcommand(commands::upgrade::command_args()) .get_matches(); execute(arg_matches); @@ -38,6 +39,7 @@ fn execute(matches: ArgMatches) { match matches.subcommand() { ("init", Some(m)) => commands::init::execute(m), ("run", Some(m)) => commands::run::execute(m), + ("upgrade", Some(m)) => commands::upgrade::execute(m), _ => println!("{}", usage()), } } diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 13bae1ad74..d9e4c5bae9 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -28,6 +28,7 @@ mixnode-common = { path = "../common/mixnode-common" } nymsphinx = {path = "../common/nymsphinx" } pemstore = {path = "../common/pemstore"} topology = {path = "../common/topology"} +version-checker = { path = "../common/version-checker" } [dev-dependencies] tempfile = "3.1.0" \ No newline at end of file diff --git a/mixnode/src/commands/mod.rs b/mixnode/src/commands/mod.rs index d22c1215e1..ef5ec82a8e 100644 --- a/mixnode/src/commands/mod.rs +++ b/mixnode/src/commands/mod.rs @@ -16,8 +16,9 @@ use crate::config::Config; use clap::ArgMatches; use nymsphinx::params::DEFAULT_NUM_MIX_HOPS; -pub mod init; -pub mod run; +pub(crate) mod init; +pub(crate) mod run; +pub(crate) mod upgrade; pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config { let max_layer = DEFAULT_NUM_MIX_HOPS; diff --git a/mixnode/src/commands/upgrade.rs b/mixnode/src/commands/upgrade.rs new file mode 100644 index 0000000000..b074d2f1ba --- /dev/null +++ b/mixnode/src/commands/upgrade.rs @@ -0,0 +1,170 @@ +// Copyright 2020 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::config::{Config, MISSING_VALUE}; +use clap::{App, Arg, ArgMatches}; +use config::NymConfig; +use std::fmt::Display; +use std::process; +use version_checker::{parse_version, Version}; + +fn print_start_upgrade(from: D1, to: D2) { + println!( + "\n==================\nTrying to upgrade mixnode from {} to {} ...", + from, to + ); +} + +fn print_failed_upgrade(from: D1, to: D2) { + eprintln!( + "Upgrade from {} to {} failed!\n==================\n", + from, to + ); +} + +fn print_successful_upgrade(from: D1, to: D2) { + println!( + "Upgrade from {} to {} was successful!\n==================\n", + from, to + ); +} + +fn pre_090_upgrade(from: &str, config: Config) -> Config { + // this is not extracted to separate function as you only have to manually pass version + // if upgrading from pre090 version + let from = match from.strip_prefix("v") { + Some(stripped) => stripped, + None => from, + }; + + let from = match from.strip_prefix("V") { + Some(stripped) => stripped, + None => from, + }; + + let from_version = parse_version(from).expect("invalid version provided!"); + if from_version.major == 0 && from_version.minor < 8 { + // technically this could be implemented, but is there any point in that? + eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead"); + process::exit(1) + } + + if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 { + eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version"); + process::exit(1) + } + + // note: current is guaranteed to not have any `build` information suffix (nor pre-release + // information), as this was asserted at the beginning of this command) + // + // upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate + // step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0) + // this way we don't need to have all the crazy paths on how to upgrade from any version to any + // other version. We just upgrade one minor version at a time. + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + let to_version = if current.major == 0 && current.minor == 9 { + current + } else { + Version::new(0, 9, 0) + }; + + print_start_upgrade(&from_version, &to_version); + + let upgraded_config = config.with_custom_version(to_version.to_string().as_ref()); + // TODO: THIS IS INCOMPLETE AS ONCE PRESENCE IS REMOVED IN 0.9.0 IT WILL ALSO NEED + // TO BE PURGED FROM CONFIG + + upgraded_config.save_to_file(None).unwrap_or_else(|err| { + eprintln!("failed to overwrite config file! - {:?}", err); + print_failed_upgrade(&from_version, &to_version); + process::exit(1); + }); + + print_successful_upgrade(from_version, to_version); + + upgraded_config +} + +pub fn command_args<'a, 'b>() -> App<'a, 'b> { + App::new("upgrade").about("Try to upgrade the mixnode") + .arg( + Arg::with_name("id") + .long("id") + .help("Id of the nym-mixnode we want to upgrade") + .takes_value(true) + .required(true), + ) + // the rest of arguments depend on the upgrade path + .arg(Arg::with_name("current version") + .long("current-version") + .help("REQUIRED FOR PRE-0.9.0 UPGRADES. Self provided version of the nym-mixnode if none is available in the config. NOTE: if provided incorrectly, results may be catastrophic.") + .takes_value(true) + ) +} + +pub fn execute(matches: &ArgMatches) { + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + + // technically this is not a correct way of checking it as a released version might contain valid build identifiers + // however, we are not using them ourselves at the moment and hence it should be fine. + // if we change our mind, we could easily tweak this code + if current.is_prerelease() || !current.build.is_empty() { + eprintln!( + "Trying to upgrade to a non-released version {}. This is not supported!", + current + ); + process::exit(1) + } + + let id = matches.value_of("id").unwrap(); + + let mut existing_config = Config::load_from_file(None, Some(id)).unwrap_or_else(|err| { + eprintln!("failed to load existing config file! - {:?}", err); + process::exit(1) + }); + + // versions fields were added in 0.9.0 + if existing_config.get_version() == MISSING_VALUE { + let self_reported_version = matches.value_of("current version").unwrap_or_else(|| { + eprintln!( + "trying to upgrade from pre v0.9.0 without providing current system version!" + ); + process::exit(1) + }); + + // upgrades up to 0.9.0 + existing_config = pre_090_upgrade(self_reported_version, existing_config); + } + + let config_version = Version::parse(existing_config.get_version()).unwrap_or_else(|err| { + eprintln!("failed to parse node version! - {:?}", err); + process::exit(1) + }); + + if config_version.is_prerelease() || !config_version.build.is_empty() { + eprintln!( + "Trying to upgrade to from non-released version {}. This is not supported!", + current + ); + process::exit(1) + } + + // here be upgrade path to 0.10.0 and beyond based on version number from config + if config_version == current { + println!("You're using the most recent version!"); + } else { + eprintln!("Cannot perform upgrade from {} to {}. Please let the developers know about this issue!", config_version, current); + process::exit(1) + } +} diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index 0b088507e4..925d9b4c01 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -24,6 +24,8 @@ use std::time; pub mod persistence; mod template; +pub(crate) const MISSING_VALUE: &str = "MISSING VALUE"; + // 'MIXNODE' const DEFAULT_LISTENING_PORT: u16 = 1789; const DEFAULT_DIRECTORY_SERVER: &str = "https://directory.nymtech.net"; @@ -84,6 +86,10 @@ impl NymConfig for Config { } } +pub fn missing_string_value() -> String { + MISSING_VALUE.to_string() +} + impl Config { pub fn new>(id: S) -> Self { Config::default().with_id(id) @@ -198,6 +204,11 @@ impl Config { self } + pub fn with_custom_version(mut self, version: &str) -> Self { + self.mixnode.version = version.to_string(); + self + } + // getters pub fn get_config_file_save_location(&self) -> PathBuf { self.config_directory().join(Self::config_file_name()) @@ -262,12 +273,17 @@ impl Config { pub fn get_cache_entry_ttl(&self) -> time::Duration { time::Duration::from_millis(self.debug.cache_entry_ttl) } + + pub fn get_version(&self) -> &str { + &self.mixnode.version + } } #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] pub struct MixNode { /// Version of the mixnode for which this configuration was created. + #[serde(default = "missing_string_value")] version: String, /// ID specifies the human readable ID of this particular mixnode. diff --git a/mixnode/src/main.rs b/mixnode/src/main.rs index 7b5dc96631..31373f6fe7 100644 --- a/mixnode/src/main.rs +++ b/mixnode/src/main.rs @@ -29,6 +29,7 @@ fn main() { .about("Implementation of the Loopix-based Mixnode") .subcommand(commands::init::command_args()) .subcommand(commands::run::command_args()) + .subcommand(commands::upgrade::command_args()) .get_matches(); execute(arg_matches); @@ -38,6 +39,7 @@ fn execute(matches: ArgMatches) { match matches.subcommand() { ("init", Some(m)) => commands::init::execute(m), ("run", Some(m)) => commands::run::execute(m), + ("upgrade", Some(m)) => commands::upgrade::execute(m), _ => println!("{}", usage()), } } From 2f7b3eec089f2fa6d91e3efdd7ebbffcf32be8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 14 Oct 2020 13:28:20 +0100 Subject: [PATCH 5/7] Feature/mix ed25519 identity (#388) * Introduced identity keypair to mixnode * Updated upgrade 0.9.0 mix upgrade instructions * Printing failed upgrade notice when it failed * Moved printing upgrade start notice to beginning of function --- mixnode/src/commands/init.rs | 15 ++++- mixnode/src/commands/run.rs | 18 +++++- mixnode/src/commands/upgrade.rs | 62 ++++++++++++++------ mixnode/src/config/mod.rs | 53 ++++++++++++++++- mixnode/src/config/persistence/pathfinder.rs | 14 ++++- mixnode/src/config/template.rs | 6 ++ mixnode/src/node/mod.rs | 11 +++- 7 files changed, 152 insertions(+), 27 deletions(-) diff --git a/mixnode/src/commands/init.rs b/mixnode/src/commands/init.rs index 09421e8c17..e5e2936cb0 100644 --- a/mixnode/src/commands/init.rs +++ b/mixnode/src/commands/init.rs @@ -16,7 +16,7 @@ use crate::commands::override_config; use crate::config::persistence::pathfinder::MixNodePathfinder; use clap::{App, Arg, ArgMatches}; use config::NymConfig; -use crypto::asymmetric::encryption; +use crypto::asymmetric::{encryption, identity}; use directory_client::DirectoryClient; use log::*; use nymsphinx::params::DEFAULT_NUM_MIX_HOPS; @@ -142,8 +142,18 @@ pub fn execute(matches: &ArgMatches) { config = config.with_layer(layer); debug!("Choosing layer {}", config.get_layer()); + let identity_keys = identity::KeyPair::new(); let sphinx_keys = encryption::KeyPair::new(); let pathfinder = MixNodePathfinder::new_from_config(&config); + pemstore::store_keypair( + &identity_keys, + &pemstore::KeyPairPath::new( + pathfinder.private_identity_key().to_owned(), + pathfinder.public_identity_key().to_owned(), + ), + ) + .expect("Failed to save identity keys"); + pemstore::store_keypair( &sphinx_keys, &pemstore::KeyPairPath::new( @@ -152,7 +162,8 @@ pub fn execute(matches: &ArgMatches) { ), ) .expect("Failed to save sphinx keys"); - println!("Saved mixnet sphinx keypair"); + + println!("Saved mixnet identity and sphinx keypairs"); let config_save_location = config.get_config_file_save_location(); config .save_to_file(None) diff --git a/mixnode/src/commands/run.rs b/mixnode/src/commands/run.rs index 54e58b45d9..c6b5c4d566 100644 --- a/mixnode/src/commands/run.rs +++ b/mixnode/src/commands/run.rs @@ -17,7 +17,7 @@ use crate::config::{persistence::pathfinder::MixNodePathfinder, Config}; use crate::node::MixNode; use clap::{App, Arg, ArgMatches}; use config::NymConfig; -use crypto::asymmetric::encryption; +use crypto::asymmetric::{encryption, identity}; pub fn command_args<'a, 'b>() -> App<'a, 'b> { App::new("run") @@ -95,6 +95,19 @@ fn special_addresses() -> Vec<&'static str> { vec!["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"] } +fn load_identity_keys(pathfinder: &MixNodePathfinder) -> identity::KeyPair { + let identity_keypair: identity::KeyPair = pemstore::load_keypair(&pemstore::KeyPairPath::new( + pathfinder.private_identity_key().to_owned(), + pathfinder.public_identity_key().to_owned(), + )) + .expect("Failed to read stored identity key files"); + println!( + "Public identity key: {}\n", + identity_keypair.public_key().to_base58_string() + ); + identity_keypair +} + fn load_sphinx_keys(pathfinder: &MixNodePathfinder) -> encryption::KeyPair { let sphinx_keypair: encryption::KeyPair = pemstore::load_keypair(&pemstore::KeyPairPath::new( pathfinder.private_encryption_key().to_owned(), @@ -120,6 +133,7 @@ pub fn execute(matches: &ArgMatches) { config = override_config(config, matches); let pathfinder = MixNodePathfinder::new_from_config(&config); + let identity_keypair = load_identity_keys(&pathfinder); let sphinx_keypair = load_sphinx_keys(&pathfinder); let listening_ip_string = config.get_listening_address().ip().to_string(); @@ -145,5 +159,5 @@ pub fn execute(matches: &ArgMatches) { config.get_announce_address() ); - MixNode::new(config, sphinx_keypair).run(); + MixNode::new(config, identity_keypair, sphinx_keypair).run(); } diff --git a/mixnode/src/commands/upgrade.rs b/mixnode/src/commands/upgrade.rs index b074d2f1ba..511640a3e1 100644 --- a/mixnode/src/commands/upgrade.rs +++ b/mixnode/src/commands/upgrade.rs @@ -12,10 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::config::{Config, MISSING_VALUE}; +use crate::config::{missing_string_value, Config}; use clap::{App, Arg, ArgMatches}; use config::NymConfig; +use crypto::asymmetric::identity; use std::fmt::Display; +use std::path::PathBuf; use std::process; use version_checker::{parse_version, Version}; @@ -41,6 +43,22 @@ fn print_successful_upgrade(from: D1, to: D2) { } fn pre_090_upgrade(from: &str, config: Config) -> Config { + // note: current is guaranteed to not have any `build` information suffix (nor pre-release + // information), as this was asserted at the beginning of this command) + // + // upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate + // step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0) + // this way we don't need to have all the crazy paths on how to upgrade from any version to any + // other version. We just upgrade one minor version at a time. + let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); + let to_version = if current.major == 0 && current.minor == 9 { + current + } else { + Version::new(0, 9, 0) + }; + + print_start_upgrade(&from, &to_version); + // this is not extracted to separate function as you only have to manually pass version // if upgrading from pre090 version let from = match from.strip_prefix("v") { @@ -57,31 +75,41 @@ fn pre_090_upgrade(from: &str, config: Config) -> Config { if from_version.major == 0 && from_version.minor < 8 { // technically this could be implemented, but is there any point in that? eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead"); + print_failed_upgrade(&from_version, &to_version); process::exit(1) } if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 { eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version"); + print_failed_upgrade(&from_version, &to_version); process::exit(1) } - // note: current is guaranteed to not have any `build` information suffix (nor pre-release - // information), as this was asserted at the beginning of this command) - // - // upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate - // step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0) - // this way we don't need to have all the crazy paths on how to upgrade from any version to any - // other version. We just upgrade one minor version at a time. - let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); - let to_version = if current.major == 0 && current.minor == 9 { - current - } else { - Version::new(0, 9, 0) - }; + if config.get_private_identity_key_file() != missing_string_value::() + || config.get_public_identity_key_file() != missing_string_value::() + { + eprintln!("existing config seems to have specified identity keys which were only introduced in 0.9.0! Can't perform upgrade."); + print_failed_upgrade(&from_version, &to_version); + process::exit(1); + } - print_start_upgrade(&from_version, &to_version); + let mut upgraded_config = config.with_custom_version(to_version.to_string().as_ref()); + + println!("Generating new identity..."); + let identity_keys = identity::KeyPair::new(); + upgraded_config.set_default_identity_keypair_paths(); + + if let Err(err) = pemstore::store_keypair( + &identity_keys, + &pemstore::KeyPairPath::new( + upgraded_config.get_private_identity_key_file(), + upgraded_config.get_public_identity_key_file(), + ), + ) { + eprintln!("Failed to save new identity key files! - {}", err); + process::exit(1); + } - let upgraded_config = config.with_custom_version(to_version.to_string().as_ref()); // TODO: THIS IS INCOMPLETE AS ONCE PRESENCE IS REMOVED IN 0.9.0 IT WILL ALSO NEED // TO BE PURGED FROM CONFIG @@ -135,7 +163,7 @@ pub fn execute(matches: &ArgMatches) { }); // versions fields were added in 0.9.0 - if existing_config.get_version() == MISSING_VALUE { + if existing_config.get_version() == missing_string_value::() { let self_reported_version = matches.value_of("current version").unwrap_or_else(|| { eprintln!( "trying to upgrade from pre v0.9.0 without providing current system version!" diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index 925d9b4c01..6239fcdadf 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -86,8 +86,8 @@ impl NymConfig for Config { } } -pub fn missing_string_value() -> String { - MISSING_VALUE.to_string() +pub fn missing_string_value>() -> T { + MISSING_VALUE.to_string().into() } impl Config { @@ -98,6 +98,20 @@ impl Config { // builder methods pub fn with_id>(mut self, id: S) -> Self { let id = id.into(); + if self + .mixnode + .private_identity_key_file + .as_os_str() + .is_empty() + { + self.mixnode.private_identity_key_file = + self::MixNode::default_private_identity_key_file(&id); + } + if self.mixnode.public_identity_key_file.as_os_str().is_empty() { + self.mixnode.public_identity_key_file = + self::MixNode::default_public_identity_key_file(&id); + } + if self.mixnode.private_sphinx_key_file.as_os_str().is_empty() { self.mixnode.private_sphinx_key_file = self::MixNode::default_private_sphinx_key_file(&id); @@ -106,6 +120,7 @@ impl Config { self.mixnode.public_sphinx_key_file = self::MixNode::default_public_sphinx_key_file(&id); } + self.mixnode.id = id; self } @@ -218,6 +233,14 @@ impl Config { self.mixnode.location.clone() } + pub fn get_private_identity_key_file(&self) -> PathBuf { + self.mixnode.private_identity_key_file.clone() + } + + pub fn get_public_identity_key_file(&self) -> PathBuf { + self.mixnode.public_identity_key_file.clone() + } + pub fn get_private_sphinx_key_file(&self) -> PathBuf { self.mixnode.private_sphinx_key_file.clone() } @@ -277,6 +300,14 @@ impl Config { pub fn get_version(&self) -> &str { &self.mixnode.version } + + // upgrade-specific + pub(crate) fn set_default_identity_keypair_paths(&mut self) { + self.mixnode.private_identity_key_file = + self::MixNode::default_private_identity_key_file(&self.mixnode.id); + self.mixnode.public_identity_key_file = + self::MixNode::default_public_identity_key_file(&self.mixnode.id); + } } #[derive(Debug, Deserialize, PartialEq, Serialize)] @@ -309,6 +340,14 @@ pub struct MixNode { /// `listening_address`. announce_address: String, + /// Path to file containing private identity key. + #[serde(default = "missing_string_value")] + private_identity_key_file: PathBuf, + + /// Path to file containing public identity key. + #[serde(default = "missing_string_value")] + public_identity_key_file: PathBuf, + /// Path to file containing private sphinx key. private_sphinx_key_file: PathBuf, @@ -329,6 +368,14 @@ pub struct MixNode { } impl MixNode { + fn default_private_identity_key_file(id: &str) -> PathBuf { + Config::default_data_directory(Some(id)).join("private_identity.pem") + } + + fn default_public_identity_key_file(id: &str) -> PathBuf { + Config::default_data_directory(Some(id)).join("public_identity.pem") + } + fn default_private_sphinx_key_file(id: &str) -> PathBuf { Config::default_data_directory(Some(id)).join("private_sphinx.pem") } @@ -353,6 +400,8 @@ impl Default for MixNode { .parse() .unwrap(), announce_address: format!("127.0.0.1:{}", DEFAULT_LISTENING_PORT), + private_identity_key_file: Default::default(), + public_identity_key_file: Default::default(), private_sphinx_key_file: Default::default(), public_sphinx_key_file: Default::default(), presence_directory_server: DEFAULT_DIRECTORY_SERVER.to_string(), diff --git a/mixnode/src/config/persistence/pathfinder.rs b/mixnode/src/config/persistence/pathfinder.rs index 3d944c952f..ba9214b7a8 100644 --- a/mixnode/src/config/persistence/pathfinder.rs +++ b/mixnode/src/config/persistence/pathfinder.rs @@ -17,7 +17,8 @@ use std::path::{Path, PathBuf}; #[derive(Debug)] pub struct MixNodePathfinder { - config_dir: PathBuf, + identity_private_key: PathBuf, + identity_public_key: PathBuf, private_sphinx_key: PathBuf, public_sphinx_key: PathBuf, } @@ -25,12 +26,21 @@ pub struct MixNodePathfinder { impl MixNodePathfinder { pub fn new_from_config(config: &Config) -> Self { MixNodePathfinder { - config_dir: config.get_config_file_save_location(), + identity_private_key: config.get_private_identity_key_file(), + identity_public_key: config.get_public_identity_key_file(), private_sphinx_key: config.get_private_sphinx_key_file(), public_sphinx_key: config.get_public_sphinx_key_file(), } } + pub fn private_identity_key(&self) -> &Path { + &self.identity_private_key + } + + pub fn public_identity_key(&self) -> &Path { + &self.identity_public_key + } + pub fn private_encryption_key(&self) -> &Path { &self.private_sphinx_key } diff --git a/mixnode/src/config/template.rs b/mixnode/src/config/template.rs index ff0f1a1728..f2425a5373 100644 --- a/mixnode/src/config/template.rs +++ b/mixnode/src/config/template.rs @@ -42,6 +42,12 @@ layer = {{ mixnode.layer }} # Socket address to which this mixnode will bind to and will be listening for packets. listening_address = '{{ mixnode.listening_address }}' +# Path to file containing private identity key. +private_identity_key_file = '{{ mixnode.private_identity_key_file }}' + +# Path to file containing public identity key. +public_identity_key_file = '{{ mixnode.public_identity_key_file }}' + # Path to file containing private identity key. private_sphinx_key_file = '{{ mixnode.private_sphinx_key_file }}' diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index f6c6043af8..8f1fb7ccac 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -16,7 +16,7 @@ use crate::config::Config; use crate::node::listener::connection_handler::packet_processing::PacketProcessor; use crate::node::listener::connection_handler::ConnectionHandler; use crate::node::listener::Listener; -use crypto::asymmetric::encryption; +use crypto::asymmetric::{encryption, identity}; use directory_client::DirectoryClient; use log::*; use mixnet_client::forwarder::{MixForwardingSender, PacketForwarder}; @@ -30,13 +30,20 @@ mod presence; // the MixNode will live for whole duration of this program pub struct MixNode { config: Config, + #[allow(dead_code)] + identity_keypair: Arc, sphinx_keypair: Arc, } impl MixNode { - pub fn new(config: Config, sphinx_keypair: encryption::KeyPair) -> Self { + pub fn new( + config: Config, + identity_keypair: identity::KeyPair, + sphinx_keypair: encryption::KeyPair, + ) -> Self { MixNode { config, + identity_keypair: Arc::new(identity_keypair), sphinx_keypair: Arc::new(sphinx_keypair), } } From d940bc8f31aef731ccd11f8e7c939b3346892944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 14 Oct 2020 13:30:57 +0100 Subject: [PATCH 6/7] Feature/double init prevention (#386) * Updated NymConfig trait making id always obligatory. Also added extra default method implementations * Preventing init on mixnodes that were initialised before * Quotes before mix id * Preventing init on gateways that were initialised before * Preventing init on native clients that were initialised before * Preventing init on socks5 clients that were initialised before --- clients/client-core/src/config/mod.rs | 14 +++++----- clients/native/src/client/config/mod.rs | 4 --- clients/native/src/commands/init.rs | 8 ++++++ clients/socks5/src/client/config/mod.rs | 4 --- clients/socks5/src/commands/init.rs | 7 +++++ common/config/src/lib.rs | 34 +++++++++++++++++-------- gateway/src/commands/init.rs | 9 ++++++- gateway/src/config/mod.rs | 16 +++++------- mixnode/src/commands/init.rs | 10 +++++++- mixnode/src/config/mod.rs | 8 ++---- 10 files changed, 70 insertions(+), 44 deletions(-) diff --git a/clients/client-core/src/config/mod.rs b/clients/client-core/src/config/mod.rs index 5c865fa312..470bc20fad 100644 --- a/clients/client-core/src/config/mod.rs +++ b/clients/client-core/src/config/mod.rs @@ -360,31 +360,31 @@ impl Default for Client { impl Client { fn default_private_identity_key_file(id: &str) -> PathBuf { - T::default_data_directory(Some(id)).join("private_identity.pem") + T::default_data_directory(id).join("private_identity.pem") } fn default_public_identity_key_file(id: &str) -> PathBuf { - T::default_data_directory(Some(id)).join("public_identity.pem") + T::default_data_directory(id).join("public_identity.pem") } fn default_private_encryption_key_file(id: &str) -> PathBuf { - T::default_data_directory(Some(id)).join("private_encryption.pem") + T::default_data_directory(id).join("private_encryption.pem") } fn default_public_encryption_key_file(id: &str) -> PathBuf { - T::default_data_directory(Some(id)).join("public_encryption.pem") + T::default_data_directory(id).join("public_encryption.pem") } fn default_gateway_shared_key_file(id: &str) -> PathBuf { - T::default_data_directory(Some(id)).join("gateway_shared.pem") + T::default_data_directory(id).join("gateway_shared.pem") } fn default_ack_key_file(id: &str) -> PathBuf { - T::default_data_directory(Some(id)).join("ack_key.pem") + T::default_data_directory(id).join("ack_key.pem") } fn default_reply_encryption_key_store_path(id: &str) -> PathBuf { - T::default_data_directory(Some(id)).join("reply_key_store") + T::default_data_directory(id).join("reply_key_store") } } diff --git a/clients/native/src/client/config/mod.rs b/clients/native/src/client/config/mod.rs index d100ce72dd..c16dc1c6b0 100644 --- a/clients/native/src/client/config/mod.rs +++ b/clients/native/src/client/config/mod.rs @@ -55,10 +55,6 @@ impl NymConfig for Config { config_template() } - fn config_file_name() -> String { - "config.toml".to_string() - } - fn default_root_directory() -> PathBuf { dirs::home_dir() .expect("Failed to evaluate $HOME value") diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index c8f3edb707..ae28c4ae5f 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -25,6 +25,7 @@ use gateway_requests::registration::handshake::SharedKeys; use rand::rngs::OsRng; use rand::seq::SliceRandom; use std::convert::TryInto; +use std::process; use std::sync::Arc; use std::time::Duration; use topology::{gateway, NymTopology}; @@ -131,7 +132,14 @@ pub fn execute(matches: &ArgMatches) { println!("Initialising client..."); let id = matches.value_of("id").unwrap(); // required for now + + if Config::default_config_file_path(id).exists() { + eprintln!("Client \"{}\" was already initialised before! If you wanted to upgrade your client to most recent version, try `upgrade` command instead!", id); + process::exit(1); + } + let mut config = Config::new(id); + let mut rng = OsRng; // TODO: ideally that should be the last thing that's being done to config. diff --git a/clients/socks5/src/client/config/mod.rs b/clients/socks5/src/client/config/mod.rs index d49b5b7d1b..093588e2f3 100644 --- a/clients/socks5/src/client/config/mod.rs +++ b/clients/socks5/src/client/config/mod.rs @@ -38,10 +38,6 @@ impl NymConfig for Config { config_template() } - fn config_file_name() -> String { - "config.toml".to_string() - } - fn default_root_directory() -> PathBuf { dirs::home_dir() .expect("Failed to evaluate $HOME value") diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 66c8358adb..4fd6b7450f 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -24,6 +24,7 @@ use gateway_client::GatewayClient; use gateway_requests::registration::handshake::SharedKeys; use rand::{prelude::SliceRandom, rngs::OsRng}; use std::convert::TryInto; +use std::process; use std::sync::Arc; use std::time::Duration; use topology::{gateway, NymTopology}; @@ -134,7 +135,13 @@ pub fn execute(matches: &ArgMatches) { let id = matches.value_of("id").unwrap(); // required for now let provider_address = matches.value_of("provider").unwrap(); + if Config::default_config_file_path(id).exists() { + eprintln!("Socks5 client \"{}\" was already initialised before! If you wanted to upgrade your client to most recent version, try `upgrade` command instead!", id); + process::exit(1); + } + let mut config = Config::new(id, provider_address); + let mut rng = OsRng; // TODO: ideally that should be the last thing that's being done to config. diff --git a/common/config/src/lib.rs b/common/config/src/lib.rs index cde9302788..b6158d2672 100644 --- a/common/config/src/lib.rs +++ b/common/config/src/lib.rs @@ -21,21 +21,23 @@ use std::{fs, io}; pub trait NymConfig: Default + Serialize + DeserializeOwned { fn template() -> &'static str; - fn config_file_name() -> String; + fn config_file_name() -> String { + "config.toml".to_string() + } fn default_root_directory() -> PathBuf; // default, most probable, implementations; can be easily overridden where required - fn default_config_directory(id: Option<&str>) -> PathBuf { - Self::default_root_directory() - .join(id.unwrap_or("")) - .join("config") + fn default_config_directory(id: &str) -> PathBuf { + Self::default_root_directory().join(id).join("config") } - fn default_data_directory(id: Option<&str>) -> PathBuf { - Self::default_root_directory() - .join(id.unwrap_or("")) - .join("data") + fn default_data_directory(id: &str) -> PathBuf { + Self::default_root_directory().join(id).join("data") + } + + fn default_config_file_path(id: &str) -> PathBuf { + Self::default_config_directory(id).join(Self::config_file_name()) } fn root_directory(&self) -> PathBuf; @@ -66,10 +68,20 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned { ) } + // Hopefully should get simplified by https://github.com/nymtech/nym/issues/385 + // so that `custom_location` could be completely removed fn load_from_file(custom_location: Option, id: Option<&str>) -> io::Result { + if custom_location.is_none() && id.is_none() { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Both custom location and id are unspecified!", + )); + } + + // unwrap on id can't fail as we just checked whether at least one of custom location or id + // is not None let config_contents = fs::read_to_string( - custom_location - .unwrap_or_else(|| Self::default_config_directory(id).join("config.toml")), + custom_location.unwrap_or_else(|| Self::default_config_file_path(id.unwrap())), )?; toml::from_str(&config_contents) diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 7e469cc116..7bf60a61f0 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -14,9 +14,11 @@ use crate::commands::override_config; use crate::config::persistence::pathfinder::GatewayPathfinder; +use crate::config::Config; use clap::{App, Arg, ArgMatches}; use config::NymConfig; use crypto::asymmetric::{encryption, identity}; +use std::process; pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { App::new("init") @@ -116,7 +118,12 @@ pub fn execute(matches: &ArgMatches) { let id = matches.value_of("id").unwrap(); println!("Initialising gateway {}...", id); - let mut config = crate::config::Config::new(id); + if Config::default_config_file_path(id).exists() { + eprintln!("Gateway \"{}\" was already initialised before! If you wanted to upgrade your gateway to most recent version, try `upgrade` command instead!", id); + process::exit(1); + } + + let mut config = Config::new(id); config = override_config(config, matches); diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index cd59b82aa8..f7fae3f26f 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -62,10 +62,6 @@ impl NymConfig for Config { config_template() } - fn config_file_name() -> String { - "config.toml".to_string() - } - fn default_root_directory() -> PathBuf { dirs::home_dir() .expect("Failed to evaluate $HOME value") @@ -457,19 +453,19 @@ pub struct Gateway { impl Gateway { fn default_private_sphinx_key_file(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("private_sphinx.pem") + Config::default_data_directory(id).join("private_sphinx.pem") } fn default_public_sphinx_key_file(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("public_sphinx.pem") + Config::default_data_directory(id).join("public_sphinx.pem") } fn default_private_identity_key_file(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("private_identity.pem") + Config::default_data_directory(id).join("private_identity.pem") } fn default_public_identity_key_file(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("public_identity.pem") + Config::default_data_directory(id).join("public_identity.pem") } fn default_location() -> String { @@ -545,11 +541,11 @@ pub struct ClientsEndpoint { impl ClientsEndpoint { fn default_inboxes_directory(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("inboxes") + Config::default_data_directory(id).join("inboxes") } fn default_ledger_path(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("client_ledger.sled") + Config::default_data_directory(id).join("client_ledger.sled") } } diff --git a/mixnode/src/commands/init.rs b/mixnode/src/commands/init.rs index e5e2936cb0..01ada80235 100644 --- a/mixnode/src/commands/init.rs +++ b/mixnode/src/commands/init.rs @@ -14,6 +14,7 @@ use crate::commands::override_config; use crate::config::persistence::pathfinder::MixNodePathfinder; +use crate::config::Config; use clap::{App, Arg, ArgMatches}; use config::NymConfig; use crypto::asymmetric::{encryption, identity}; @@ -21,6 +22,7 @@ use directory_client::DirectoryClient; use log::*; use nymsphinx::params::DEFAULT_NUM_MIX_HOPS; use std::convert::TryInto; +use std::process; use tokio::runtime::Runtime; use topology::NymTopology; @@ -134,7 +136,13 @@ pub fn execute(matches: &ArgMatches) { rt.block_on(async { let id = matches.value_of("id").unwrap(); println!("Initialising mixnode {}...", id); - let mut config = crate::config::Config::new(id); + + if Config::default_config_file_path(id).exists() { + eprintln!("Mixnode \"{}\" was already initialised before! If you wanted to upgrade your node to most recent version, try `upgrade` command instead!", id); + process::exit(1); + } + + let mut config = Config::new(id); config = override_config(config, matches); let layer = choose_layer(matches, config.get_presence_directory_server()).await; // TODO: I really don't like how we override config and are presumably done with it diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index 6239fcdadf..2390ce0033 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -56,10 +56,6 @@ impl NymConfig for Config { config_template() } - fn config_file_name() -> String { - "config.toml".to_string() - } - fn default_root_directory() -> PathBuf { dirs::home_dir() .expect("Failed to evaluate $HOME value") @@ -377,11 +373,11 @@ impl MixNode { } fn default_private_sphinx_key_file(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("private_sphinx.pem") + Config::default_data_directory(id).join("private_sphinx.pem") } fn default_public_sphinx_key_file(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("public_sphinx.pem") + Config::default_data_directory(id).join("public_sphinx.pem") } fn default_location() -> String { From 2585efc540e27e732bce7b60c4b4d67a4c93293e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 14 Oct 2020 17:25:12 +0100 Subject: [PATCH 7/7] Feature/duration cleanup (#391) * Mixnode using Duration for time intervals + human readable config fields for them * Removed old comment * Native client using Duration for time intervals + human readable config fields for them * Socks5 client using Duration for time intervals + human readable config fields for them * Gateway using Duration for time intervals + human readable config fields for them * Config compatibility with 0.8.0 debug values * Fixed previous merge issue --- Cargo.lock | 21 ++- clients/client-core/Cargo.toml | 1 + clients/client-core/src/config/mod.rs | 163 +++++++++++++------ clients/native/src/client/config/template.rs | 8 +- clients/socks5/src/client/config/template.rs | 8 +- gateway/Cargo.toml | 1 + gateway/src/config/mod.rs | 118 +++++++++++--- mixnode/Cargo.toml | 1 + mixnode/src/config/mod.rs | 150 ++++++++++++----- 9 files changed, 350 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae3ec06761..a45ec99dd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -360,6 +360,7 @@ dependencies = [ "futures 0.3.5", "gateway-client", "gateway-requests", + "humantime-serde", "log", "nonexhaustive-delayqueue", "nymsphinx", @@ -711,7 +712,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" dependencies = [ "atty", - "humantime", + "humantime 1.3.0", "log", "regex", "termcolor", @@ -1096,6 +1097,22 @@ dependencies = [ "quick-error 1.2.3", ] +[[package]] +name = "humantime" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a" + +[[package]] +name = "humantime-serde" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac34a56cfd4acddb469cc7fff187ed5ac36f498ba085caf8bbc725e3ff474058" +dependencies = [ + "humantime 2.0.1", + "serde", +] + [[package]] name = "hyper" version = "0.13.7" @@ -1588,6 +1605,7 @@ dependencies = [ "dotenv", "futures 0.3.5", "gateway-requests", + "humantime-serde", "log", "mixnet-client", "mixnode-common", @@ -1618,6 +1636,7 @@ dependencies = [ "dirs 2.0.2", "dotenv", "futures 0.3.5", + "humantime-serde", "log", "mixnet-client", "mixnode-common", diff --git a/clients/client-core/Cargo.toml b/clients/client-core/Cargo.toml index 2c2a962773..bde319e468 100644 --- a/clients/client-core/Cargo.toml +++ b/clients/client-core/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" [dependencies] dirs = "2.0.2" futures = "0.3.1" +humantime-serde = "1.0.1" log = "0.4" rand = { version = "0.7.3", features = ["wasm-bindgen"] } serde = { version = "1.0.104", features = ["derive"] } diff --git a/clients/client-core/src/config/mod.rs b/clients/client-core/src/config/mod.rs index 470bc20fad..f7509f3dfc 100644 --- a/clients/client-core/src/config/mod.rs +++ b/clients/client-core/src/config/mod.rs @@ -13,10 +13,12 @@ // limitations under the License. use config::NymConfig; -use serde::{Deserialize, Serialize}; +use serde::{ + de::{self, IntoDeserializer, Visitor}, + Deserialize, Deserializer, Serialize, +}; use std::marker::PhantomData; use std::path::PathBuf; -use std::time; use std::time::Duration; pub mod persistence; @@ -26,21 +28,66 @@ pub const MISSING_VALUE: &str = "MISSING VALUE"; // 'CLIENT' const DEFAULT_DIRECTORY_SERVER: &str = "https://directory.nymtech.net"; // 'DEBUG' -// where applicable, the below are defined in milliseconds const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5; -// all delays are in milliseconds -const DEFAULT_ACK_WAIT_ADDITION: u64 = 1_500; -const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: u64 = 1000; -const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: u64 = 100; -const DEFAULT_AVERAGE_PACKET_DELAY: u64 = 100; -const DEFAULT_TOPOLOGY_REFRESH_RATE: u64 = 30_000; -const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: u64 = 5_000; -const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: u64 = 1_500; +const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500); +const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(1000); +const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(100); +const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(100); +const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_millis(30_000); +const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000); +const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_millis(1_500); const DEFAULT_VPN_KEY_REUSE_LIMIT: usize = 1000; const ZERO_DELAY: Duration = Duration::from_nanos(0); +// custom function is defined to deserialize based on whether field contains a pre 0.9.0 +// u64 interpreted as milliseconds or proper duration introduced in 0.9.0 +// +// TODO: when we get to refactoring down the line, this code can just be removed +// and all Duration fields could just have #[serde(with = "humantime_serde")] instead +// reason for that is that we don't expect anyone to be upgrading from pre 0.9.0 when we have, +// for argument sake, 0.11.0 out +fn deserialize_duration<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + struct DurationVisitor; + + impl<'de> Visitor<'de> for DurationVisitor { + type Value = Duration; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("u64 or a duration") + } + + fn visit_i64(self, value: i64) -> Result + where + E: de::Error, + { + self.visit_u64(value as u64) + } + + fn visit_u64(self, value: u64) -> Result + where + E: de::Error, + { + Ok(Duration::from_millis(Deserialize::deserialize( + value.into_deserializer(), + )?)) + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + humantime_serde::deserialize(value.into_deserializer()) + } + } + + deserializer.deserialize_any(DurationVisitor) +} + pub fn missing_string_value() -> String { MISSING_VALUE.to_string() } @@ -133,9 +180,9 @@ impl Config { } pub fn set_high_default_traffic_volume(&mut self) { - self.debug.average_packet_delay = 10; - self.debug.loop_cover_traffic_average_delay = 20; // 50 cover messages / s - self.debug.message_sending_average_delay = 5; // 200 "real" messages / s + self.debug.average_packet_delay = Duration::from_millis(10); + self.debug.loop_cover_traffic_average_delay = Duration::from_millis(100); // 10 cover messages / s + self.debug.message_sending_average_delay = Duration::from_millis(5); // 200 "real" messages / s } pub fn set_vpn_mode(&mut self, vpn_mode: bool) { @@ -199,19 +246,19 @@ impl Config { } // Debug getters - pub fn get_average_packet_delay(&self) -> time::Duration { + pub fn get_average_packet_delay(&self) -> Duration { if self.client.vpn_mode { ZERO_DELAY } else { - time::Duration::from_millis(self.debug.average_packet_delay) + self.debug.average_packet_delay } } - pub fn get_average_ack_delay(&self) -> time::Duration { + pub fn get_average_ack_delay(&self) -> Duration { if self.client.vpn_mode { ZERO_DELAY } else { - time::Duration::from_millis(self.debug.average_ack_delay) + self.debug.average_ack_delay } } @@ -219,32 +266,32 @@ impl Config { self.debug.ack_wait_multiplier } - pub fn get_ack_wait_addition(&self) -> time::Duration { - time::Duration::from_millis(self.debug.ack_wait_addition) + pub fn get_ack_wait_addition(&self) -> Duration { + self.debug.ack_wait_addition } - pub fn get_loop_cover_traffic_average_delay(&self) -> time::Duration { - time::Duration::from_millis(self.debug.loop_cover_traffic_average_delay) + pub fn get_loop_cover_traffic_average_delay(&self) -> Duration { + self.debug.loop_cover_traffic_average_delay } - pub fn get_message_sending_average_delay(&self) -> time::Duration { + pub fn get_message_sending_average_delay(&self) -> Duration { if self.client.vpn_mode { ZERO_DELAY } else { - time::Duration::from_millis(self.debug.message_sending_average_delay) + self.debug.message_sending_average_delay } } - pub fn get_gateway_response_timeout(&self) -> time::Duration { - time::Duration::from_millis(self.debug.gateway_response_timeout) + pub fn get_gateway_response_timeout(&self) -> Duration { + self.debug.gateway_response_timeout } - pub fn get_topology_refresh_rate(&self) -> time::Duration { - time::Duration::from_millis(self.debug.topology_refresh_rate) + pub fn get_topology_refresh_rate(&self) -> Duration { + self.debug.topology_refresh_rate } - pub fn get_topology_resolution_timeout(&self) -> time::Duration { - time::Duration::from_millis(self.debug.topology_resolution_timeout) + pub fn get_topology_resolution_timeout(&self) -> Duration { + self.debug.topology_resolution_timeout } pub fn get_vpn_mode(&self) -> bool { @@ -405,15 +452,21 @@ pub struct Debug { /// sent packet is going to be delayed at any given mix node. /// So for a packet going through three mix nodes, on average, it will take three times this value /// until the packet reaches its destination. - /// The provided value is interpreted as milliseconds. - average_packet_delay: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + average_packet_delay: Duration, /// The parameter of Poisson distribution determining how long, on average, /// sent acknowledgement is going to be delayed at any given mix node. /// So for an ack going through three mix nodes, on average, it will take three times this value /// until the packet reaches its destination. - /// The provided value is interpreted as milliseconds. - average_ack_delay: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + average_ack_delay: Duration, /// Value multiplied with the expected round trip time of an acknowledgement packet before /// it is assumed it was lost and retransmission of the data packet happens. @@ -423,36 +476,54 @@ pub struct Debug { /// Value added to the expected round trip time of an acknowledgement packet before /// it is assumed it was lost and retransmission of the data packet happens. /// In an ideal network with 0 latency, this value would have been 0. - /// The provided value is interpreted as milliseconds. - ack_wait_addition: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + ack_wait_addition: Duration, /// The parameter of Poisson distribution determining how long, on average, /// it is going to take for another loop cover traffic message to be sent. - /// The provided value is interpreted as milliseconds. - loop_cover_traffic_average_delay: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + loop_cover_traffic_average_delay: Duration, /// The parameter of Poisson distribution determining how long, on average, /// it is going to take another 'real traffic stream' message to be sent. /// If no real packets are available and cover traffic is enabled, /// a loop cover message is sent instead in order to preserve the rate. - /// The provided value is interpreted as milliseconds. - message_sending_average_delay: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + message_sending_average_delay: Duration, /// How long we're willing to wait for a response to a message sent to the gateway, /// before giving up on it. - /// The provided value is interpreted as milliseconds. - gateway_response_timeout: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + gateway_response_timeout: Duration, /// The uniform delay every which clients are querying the directory server /// to try to obtain a compatible network topology to send sphinx packets through. - /// The provided value is interpreted as milliseconds. - topology_refresh_rate: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + topology_refresh_rate: Duration, /// During topology refresh, test packets are sent through every single possible network /// path. This timeout determines waiting period until it is decided that the packet /// did not reach its destination. - /// The provided value is interpreted as milliseconds. - topology_resolution_timeout: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + topology_resolution_timeout: Duration, /// If the mode of the client is set to VPN it specifies number of packets created with the /// same initial secret until it gets rotated. diff --git a/clients/native/src/client/config/template.rs b/clients/native/src/client/config/template.rs index 72b3531126..d3d7d6063b 100644 --- a/clients/native/src/client/config/template.rs +++ b/clients/native/src/client/config/template.rs @@ -101,10 +101,10 @@ listening_port = {{ socket.listening_port }} [debug] -average_packet_delay = {{ debug.average_packet_delay }} -average_ack_delay = {{ debug.average_ack_delay }} -loop_cover_traffic_average_delay = {{ debug.loop_cover_traffic_average_delay }} -message_sending_average_delay = {{ debug.message_sending_average_delay }} +average_packet_delay = '{{ debug.average_packet_delay }}' +average_ack_delay = '{{ debug.average_ack_delay }}' +loop_cover_traffic_average_delay = '{{ debug.loop_cover_traffic_average_delay }}' +message_sending_average_delay = '{{ debug.message_sending_average_delay }}' "# } diff --git a/clients/socks5/src/client/config/template.rs b/clients/socks5/src/client/config/template.rs index c0af36207a..a02fc8d1c6 100644 --- a/clients/socks5/src/client/config/template.rs +++ b/clients/socks5/src/client/config/template.rs @@ -100,10 +100,10 @@ listening_port = {{ socks5.listening_port }} [debug] -average_packet_delay = {{ debug.average_packet_delay }} -average_ack_delay = {{ debug.average_ack_delay }} -loop_cover_traffic_average_delay = {{ debug.loop_cover_traffic_average_delay }} -message_sending_average_delay = {{ debug.message_sending_average_delay }} +average_packet_delay = '{{ debug.average_packet_delay }}' +average_ack_delay = '{{ debug.average_ack_delay }}' +loop_cover_traffic_average_delay = '{{ debug.loop_cover_traffic_average_delay }}' +message_sending_average_delay = '{{ debug.message_sending_average_delay }}' "# } diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index ea4a9ea0c7..2c4cc774ea 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -13,6 +13,7 @@ dirs = "2.0.2" dashmap = "4.0.0-rc6" dotenv = "0.15.0" futures = "0.3" +humantime-serde = "1.0.1" log = "0.4" pretty_env_logger = "0.3" rand = "0.7" diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index f7fae3f26f..85664042a5 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -15,11 +15,14 @@ use crate::config::template::config_template; use config::NymConfig; use log::*; -use serde::{Deserialize, Serialize}; +use serde::{ + de::{self, IntoDeserializer, Visitor}, + Deserialize, Deserializer, Serialize, +}; use std::net::{IpAddr, SocketAddr}; use std::path::PathBuf; use std::str::FromStr; -use std::time; +use std::time::Duration; pub mod persistence; mod template; @@ -33,11 +36,11 @@ const DEFAULT_DIRECTORY_SERVER: &str = "https://directory.nymtech.net"; // 'DEBUG' // where applicable, the below are defined in milliseconds -const DEFAULT_PRESENCE_SENDING_DELAY: u64 = 10_000; // 10s -const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: u64 = 10_000; // 10s -const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: u64 = 300_000; // 5min -const DEFAULT_INITIAL_CONNECTION_TIMEOUT: u64 = 1_500; // 1.5s -const DEFAULT_CACHE_ENTRY_TTL: u64 = 30_000; +const DEFAULT_PRESENCE_SENDING_DELAY: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000); +const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500); +const DEFAULT_CACHE_ENTRY_TTL: Duration = Duration::from_millis(30_000); const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16; const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: u16 = 5; @@ -88,6 +91,53 @@ impl NymConfig for Config { } } +// custom function is defined to deserialize based on whether field contains a pre 0.9.0 +// u64 interpreted as milliseconds or proper duration introduced in 0.9.0 +// +// TODO: when we get to refactoring down the line, this code can just be removed +// and all Duration fields could just have #[serde(with = "humantime_serde")] instead +// reason for that is that we don't expect anyone to be upgrading from pre 0.9.0 when we have, +// for argument sake, 0.11.0 out +fn deserialize_duration<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + struct DurationVisitor; + + impl<'de> Visitor<'de> for DurationVisitor { + type Value = Duration; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("u64 or a duration") + } + + fn visit_i64(self, value: i64) -> Result + where + E: de::Error, + { + self.visit_u64(value as u64) + } + + fn visit_u64(self, value: u64) -> Result + where + E: de::Error, + { + Ok(Duration::from_millis(Deserialize::deserialize( + value.into_deserializer(), + )?)) + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + humantime_serde::deserialize(value.into_deserializer()) + } + } + + deserializer.deserialize_any(DurationVisitor) +} + pub fn missing_string_value() -> String { MISSING_VALUE.to_string() } @@ -358,8 +408,8 @@ impl Config { self.gateway.presence_directory_server.clone() } - pub fn get_presence_sending_delay(&self) -> time::Duration { - time::Duration::from_millis(self.debug.presence_sending_delay) + pub fn get_presence_sending_delay(&self) -> Duration { + self.debug.presence_sending_delay } pub fn get_mix_listening_address(&self) -> SocketAddr { @@ -386,16 +436,16 @@ impl Config { self.clients_endpoint.ledger_path.clone() } - pub fn get_packet_forwarding_initial_backoff(&self) -> time::Duration { - time::Duration::from_millis(self.debug.packet_forwarding_initial_backoff) + pub fn get_packet_forwarding_initial_backoff(&self) -> Duration { + self.debug.packet_forwarding_initial_backoff } - pub fn get_packet_forwarding_maximum_backoff(&self) -> time::Duration { - time::Duration::from_millis(self.debug.packet_forwarding_maximum_backoff) + pub fn get_packet_forwarding_maximum_backoff(&self) -> Duration { + self.debug.packet_forwarding_maximum_backoff } - pub fn get_initial_connection_timeout(&self) -> time::Duration { - time::Duration::from_millis(self.debug.initial_connection_timeout) + pub fn get_initial_connection_timeout(&self) -> Duration { + self.debug.initial_connection_timeout } pub fn get_message_retrieval_limit(&self) -> u16 { @@ -406,8 +456,8 @@ impl Config { self.debug.stored_messages_filename_length } - pub fn get_cache_entry_ttl(&self) -> time::Duration { - time::Duration::from_millis(self.debug.cache_entry_ttl) + pub fn get_cache_entry_ttl(&self) -> Duration { + self.debug.cache_entry_ttl } pub fn get_version(&self) -> &str { @@ -577,20 +627,33 @@ impl Default for Logging { pub struct Debug { /// Initial value of an exponential backoff to reconnect to dropped TCP connection when /// forwarding sphinx packets. - /// The provided value is interpreted as milliseconds. - packet_forwarding_initial_backoff: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + packet_forwarding_initial_backoff: Duration, /// Maximum value of an exponential backoff to reconnect to dropped TCP connection when /// forwarding sphinx packets. - /// The provided value is interpreted as milliseconds. - packet_forwarding_maximum_backoff: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + packet_forwarding_maximum_backoff: Duration, /// Timeout for establishing initial connection when trying to forward a sphinx packet. - /// The provider value is interpreted as milliseconds. - initial_connection_timeout: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + initial_connection_timeout: Duration, /// Delay between each subsequent presence data being sent. - presence_sending_delay: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + presence_sending_delay: Duration, /// Length of filenames for new client messages. stored_messages_filename_length: u16, @@ -601,8 +664,11 @@ pub struct Debug { message_retrieval_limit: u16, /// Duration for which a cached vpn processing result is going to get stored for. - /// The provided value is interpreted as milliseconds. - cache_entry_ttl: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + cache_entry_ttl: Duration, } impl Default for Debug { diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index d9e4c5bae9..2a7f3f137c 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -13,6 +13,7 @@ curve25519-dalek = "2.0.0" dirs = "2.0.2" dotenv = "0.15.0" futures = "0.3.1" +humantime-serde = "1.0.1" log = "0.4" pretty_env_logger = "0.3" serde = { version = "1.0.104", features = ["derive"] } diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index 2390ce0033..fc3775485a 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -15,11 +15,14 @@ use crate::config::template::config_template; use config::NymConfig; use log::*; -use serde::{Deserialize, Serialize}; +use serde::{ + de::{self, IntoDeserializer, Visitor}, + Deserialize, Deserializer, Serialize, +}; use std::net::{IpAddr, SocketAddr}; use std::path::PathBuf; use std::str::FromStr; -use std::time; +use std::time::Duration; pub mod persistence; mod template; @@ -31,14 +34,13 @@ const DEFAULT_LISTENING_PORT: u16 = 1789; const DEFAULT_DIRECTORY_SERVER: &str = "https://directory.nymtech.net"; // 'DEBUG' -// where applicable, the below are defined in milliseconds -const DEFAULT_PRESENCE_SENDING_DELAY: u64 = 10_000; // 10s -const DEFAULT_METRICS_SENDING_DELAY: u64 = 5_000; // 10s -const DEFAULT_METRICS_RUNNING_STATS_LOGGING_DELAY: u64 = 60_000; // 1min -const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: u64 = 10_000; // 10s -const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: u64 = 300_000; // 5min -const DEFAULT_INITIAL_CONNECTION_TIMEOUT: u64 = 1_500; // 1.5s -const DEFAULT_CACHE_ENTRY_TTL: u64 = 30_000; +const DEFAULT_PRESENCE_SENDING_DELAY: Duration = Duration::from_millis(10_000); +const DEFAULT_METRICS_SENDING_DELAY: Duration = Duration::from_millis(5_000); +const DEFAULT_METRICS_RUNNING_STATS_LOGGING_DELAY: Duration = Duration::from_millis(60_000); +const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000); +const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500); +const DEFAULT_CACHE_ENTRY_TTL: Duration = Duration::from_millis(30_000); #[derive(Debug, Default, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] @@ -82,6 +84,53 @@ impl NymConfig for Config { } } +// custom function is defined to deserialize based on whether field contains a pre 0.9.0 +// u64 interpreted as milliseconds or proper duration introduced in 0.9.0 +// +// TODO: when we get to refactoring down the line, this code can just be removed +// and all Duration fields could just have #[serde(with = "humantime_serde")] instead +// reason for that is that we don't expect anyone to be upgrading from pre 0.9.0 when we have, +// for argument sake, 0.11.0 out +fn deserialize_duration<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + struct DurationVisitor; + + impl<'de> Visitor<'de> for DurationVisitor { + type Value = Duration; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("u64 or a duration") + } + + fn visit_i64(self, value: i64) -> Result + where + E: de::Error, + { + self.visit_u64(value as u64) + } + + fn visit_u64(self, value: u64) -> Result + where + E: de::Error, + { + Ok(Duration::from_millis(Deserialize::deserialize( + value.into_deserializer(), + )?)) + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + humantime_serde::deserialize(value.into_deserializer()) + } + } + + deserializer.deserialize_any(DurationVisitor) +} + pub fn missing_string_value>() -> T { MISSING_VALUE.to_string().into() } @@ -249,20 +298,20 @@ impl Config { self.mixnode.presence_directory_server.clone() } - pub fn get_presence_sending_delay(&self) -> time::Duration { - time::Duration::from_millis(self.debug.presence_sending_delay) + pub fn get_presence_sending_delay(&self) -> Duration { + self.debug.presence_sending_delay } pub fn get_metrics_directory_server(&self) -> String { self.mixnode.metrics_directory_server.clone() } - pub fn get_metrics_sending_delay(&self) -> time::Duration { - time::Duration::from_millis(self.debug.metrics_sending_delay) + pub fn get_metrics_sending_delay(&self) -> Duration { + self.debug.metrics_sending_delay } - pub fn get_metrics_running_stats_logging_delay(&self) -> time::Duration { - time::Duration::from_millis(self.debug.metrics_running_stats_logging_delay) + pub fn get_metrics_running_stats_logging_delay(&self) -> Duration { + self.debug.metrics_running_stats_logging_delay } pub fn get_layer(&self) -> u64 { @@ -277,20 +326,20 @@ impl Config { self.mixnode.announce_address.clone() } - pub fn get_packet_forwarding_initial_backoff(&self) -> time::Duration { - time::Duration::from_millis(self.debug.packet_forwarding_initial_backoff) + pub fn get_packet_forwarding_initial_backoff(&self) -> Duration { + self.debug.packet_forwarding_initial_backoff } - pub fn get_packet_forwarding_maximum_backoff(&self) -> time::Duration { - time::Duration::from_millis(self.debug.packet_forwarding_maximum_backoff) + pub fn get_packet_forwarding_maximum_backoff(&self) -> Duration { + self.debug.packet_forwarding_maximum_backoff } - pub fn get_initial_connection_timeout(&self) -> time::Duration { - time::Duration::from_millis(self.debug.initial_connection_timeout) + pub fn get_initial_connection_timeout(&self) -> Duration { + self.debug.initial_connection_timeout } - pub fn get_cache_entry_ttl(&self) -> time::Duration { - time::Duration::from_millis(self.debug.cache_entry_ttl) + pub fn get_cache_entry_ttl(&self) -> Duration { + self.debug.cache_entry_ttl } pub fn get_version(&self) -> &str { @@ -365,11 +414,11 @@ pub struct MixNode { impl MixNode { fn default_private_identity_key_file(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("private_identity.pem") + Config::default_data_directory(id).join("private_identity.pem") } fn default_public_identity_key_file(id: &str) -> PathBuf { - Config::default_data_directory(Some(id)).join("public_identity.pem") + Config::default_data_directory(id).join("public_identity.pem") } fn default_private_sphinx_key_file(id: &str) -> PathBuf { @@ -421,34 +470,55 @@ impl Default for Logging { #[serde(default, deny_unknown_fields)] pub struct Debug { /// Delay between each subsequent presence data being sent. - /// The provided value is interpreted as milliseconds. - presence_sending_delay: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + presence_sending_delay: Duration, /// Delay between each subsequent metrics data being sent. - /// The provided value is interpreted as milliseconds. - metrics_sending_delay: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + metrics_sending_delay: Duration, /// Delay between each subsequent running metrics statistics being logged. - /// The provided value is interpreted as milliseconds. - metrics_running_stats_logging_delay: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + metrics_running_stats_logging_delay: Duration, /// Initial value of an exponential backoff to reconnect to dropped TCP connection when /// forwarding sphinx packets. - /// The provided value is interpreted as milliseconds. - packet_forwarding_initial_backoff: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + packet_forwarding_initial_backoff: Duration, /// Maximum value of an exponential backoff to reconnect to dropped TCP connection when /// forwarding sphinx packets. - /// The provided value is interpreted as milliseconds. - packet_forwarding_maximum_backoff: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + packet_forwarding_maximum_backoff: Duration, /// Timeout for establishing initial connection when trying to forward a sphinx packet. - /// The provider value is interpreted as milliseconds. - initial_connection_timeout: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + initial_connection_timeout: Duration, /// Duration for which a cached vpn processing result is going to get stored for. - /// The provided value is interpreted as milliseconds. - cache_entry_ttl: u64, + #[serde( + deserialize_with = "deserialize_duration", + serialize_with = "humantime_serde::serialize" + )] + cache_entry_ttl: Duration, } impl Default for Debug {