From 15c7a270ebd06cc47800a538c54aba2c6d4be1f9 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Sat, 9 Feb 2019 21:14:27 +0000 Subject: [PATCH 01/28] Windows Compatibility Fixes #1 (#2535) * initial changes for windows build and unit/integration tests * rustfmt * wallet+store tests * rustfmt * fix linux daemonize * better encapsulate file rename * rustfmt * remove daemonize commands * rustfmt * remove server start/stop commands * add ability to drop pmmr backend files explicitly for txhashset unzip * rustfmt * fix pmmr tests * rustfmt --- Cargo.lock | 1143 ++++++++++++---------- Cargo.toml | 7 +- chain/src/chain.rs | 8 + chain/src/txhashset/txhashset.rs | 11 +- core/Cargo.toml | 2 +- core/src/core/pmmr/backend.rs | 3 + core/tests/vec_backend.rs | 2 + src/bin/cmd/server.rs | 22 +- src/bin/grin.yml | 4 - store/Cargo.toml | 2 +- store/src/lmdb.rs | 18 +- store/src/pmmr.rs | 23 +- store/src/types.rs | 88 +- store/tests/pmmr.rs | 1168 ++++++++++++----------- util/src/zip.rs | 10 +- wallet/src/test_framework/testclient.rs | 4 + wallet/tests/restore.rs | 18 +- 17 files changed, 1415 insertions(+), 1118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4df8657a..68d4a9f42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,11 @@ +[[package]] +name = "MacTypes-sys" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "adler32" version = "1.0.3" @@ -8,7 +16,7 @@ name = "aho-corasick" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -26,7 +34,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arc-swap" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -40,7 +48,7 @@ dependencies = [ [[package]] name = "array-macro" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -59,7 +67,7 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -70,30 +78,36 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -101,7 +115,7 @@ name = "base64" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -144,7 +158,7 @@ name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -174,7 +188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -185,7 +199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -193,13 +207,13 @@ name = "bytes" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.25" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -222,8 +236,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -232,7 +246,7 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -270,7 +284,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -278,7 +292,7 @@ name = "core-foundation-sys" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -299,21 +313,21 @@ dependencies = [ [[package]] name = "croaring" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "croaring-sys 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "croaring-sys 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "croaring-sys" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -321,6 +335,21 @@ name = "crossbeam" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-channel" version = "0.2.6" @@ -329,17 +358,26 @@ dependencies = [ "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -347,9 +385,22 @@ name = "crossbeam-epoch" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -362,10 +413,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crossbeam-utils" -version = "0.6.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -382,7 +434,7 @@ name = "csv" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -411,14 +463,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "enum-map 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "enumset 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "enumset 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ncurses 5.97.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ncurses 5.98.0 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -427,11 +479,25 @@ dependencies = [ ] [[package]] -name = "daemonize" -version = "0.3.0" +name = "cursive" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-map 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "enumset 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pancurses 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -452,7 +518,7 @@ name = "dirs" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -474,7 +540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "encoding_rs" -version = "0.8.13" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -485,18 +551,18 @@ name = "enum-map" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "array-macro 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "enum-map-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reexport-proc-macro 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "array-macro 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "enum-map-derive 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "reexport-proc-macro 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "enum-map-derive" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -510,7 +576,7 @@ dependencies = [ [[package]] name = "enumset" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "enumset_derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -522,9 +588,9 @@ name = "enumset_derive" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -541,21 +607,21 @@ dependencies = [ [[package]] name = "failure" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -570,8 +636,8 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -580,9 +646,9 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -603,6 +669,11 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -628,7 +699,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -650,8 +721,8 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -670,10 +741,10 @@ dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cursive 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "cursive 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "grin_api 1.0.1", "grin_chain 1.0.1", @@ -690,8 +761,8 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -700,8 +771,8 @@ dependencies = [ name = "grin_api" version = "1.0.1" dependencies = [ - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "grin_chain 1.0.1", "grin_core 1.0.1", @@ -709,21 +780,21 @@ dependencies = [ "grin_pool 1.0.1", "grin_store 1.0.1", "grin_util 1.0.1", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -732,12 +803,12 @@ name = "grin_chain" version = "1.0.1" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "croaring 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "croaring 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "grin_core 1.0.1", "grin_keychain 1.0.1", "grin_store 1.0.1", @@ -745,9 +816,9 @@ dependencies = [ "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -761,9 +832,9 @@ dependencies = [ "grin_util 1.0.1", "grin_wallet 1.0.1", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -772,23 +843,23 @@ name = "grin_core" version = "1.0.1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "croaring 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "croaring 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "grin_keychain 1.0.1", "grin_util 1.0.1", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -798,18 +869,18 @@ name = "grin_keychain" version = "1.0.1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "grin_util 1.0.1", "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "ripemd160 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -830,9 +901,9 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -847,9 +918,9 @@ dependencies = [ "grin_store 1.0.1", "grin_util 1.0.1", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -859,11 +930,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -883,56 +954,56 @@ dependencies = [ "grin_store 1.0.1", "grin_util 1.0.1", "grin_wallet 1.0.1", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-staticfile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "grin_store" version = "1.0.1" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "croaring 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "croaring 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "grin_core 1.0.1", "grin_util 1.0.1", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "grin_util" version = "1.0.1" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "grin_secp256k1zkp 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log4rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "zip 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -943,10 +1014,10 @@ name = "grin_wallet" version = "1.0.1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "grin_api 1.0.1", "grin_chain 1.0.1", @@ -954,14 +1025,14 @@ dependencies = [ "grin_keychain 1.0.1", "grin_store 1.0.1", "grin_util 1.0.1", - "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "prettytable-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -972,19 +1043,19 @@ dependencies = [ [[package]] name = "h2" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -998,7 +1069,7 @@ dependencies = [ [[package]] name = "http" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1026,27 +1097,27 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.17" +version = "0.12.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1057,13 +1128,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ct-logs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1075,8 +1146,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1088,9 +1159,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1100,7 +1171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1113,7 +1184,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1137,9 +1208,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1163,7 +1234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.44" +version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1172,17 +1243,17 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libgit2-sys" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1193,7 +1264,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1201,7 +1272,7 @@ name = "libloading" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1210,8 +1281,8 @@ name = "libz-sys" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1242,7 +1313,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "liblmdb-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "supercow 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1270,7 +1341,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1289,13 +1360,13 @@ dependencies = [ "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log-mdc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", "thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1325,17 +1396,16 @@ name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1343,7 +1413,7 @@ name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1354,7 +1424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mime" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1365,9 +1435,9 @@ name = "mime_guess" version = "2.0.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1376,13 +1446,13 @@ name = "miniz-sys" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz_oxide" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1390,13 +1460,13 @@ dependencies = [ [[package]] name = "miniz_oxide_c_api" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1409,11 +1479,11 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1423,7 +1493,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1444,11 +1514,11 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallstr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "terminfo 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1458,7 +1528,7 @@ name = "msdos_time" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1468,24 +1538,24 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ncurses" -version = "5.97.0" +version = "5.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1495,7 +1565,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1506,7 +1576,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1518,9 +1588,9 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1539,10 +1609,11 @@ dependencies = [ [[package]] name = "nom" -version = "4.1.1" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1563,7 +1634,7 @@ name = "num" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1578,13 +1649,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-bigint" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1641,7 +1712,7 @@ name = "num-rational" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1661,10 +1732,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1674,15 +1745,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.15" +version = "0.10.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1692,11 +1763,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.39" +version = "0.9.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1717,6 +1788,18 @@ dependencies = [ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pancurses" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ncurses 5.98.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pdcurses-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot" version = "0.6.4" @@ -1726,15 +1809,36 @@ dependencies = [ "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1744,15 +1848,24 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pdcurses-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -1765,33 +1878,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "phf" -version = "0.7.23" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_codegen" -version = "0.7.23" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_generator" -version = "0.7.23" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_shared" -version = "0.7.23" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1840,7 +1953,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1861,82 +1974,83 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1944,7 +2058,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1952,7 +2066,30 @@ name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1960,21 +2097,29 @@ name = "rand_pcg" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_xorshift" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.43" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1982,7 +2127,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1991,14 +2136,14 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "reexport-proc-macro" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2007,15 +2152,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2036,23 +2181,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2060,9 +2205,9 @@ name = "ring" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2082,13 +2227,13 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2140,7 +2285,7 @@ name = "same-file" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2178,22 +2323,23 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2216,7 +2362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.81" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2225,27 +2371,27 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.81" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.33" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2255,7 +2401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2266,7 +2412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2283,11 +2429,11 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arc-swap 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2297,7 +2443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "slab" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2305,12 +2451,12 @@ name = "smallstr" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2323,7 +2469,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "string" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2341,18 +2487,18 @@ name = "syn" version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.22" +version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2361,9 +2507,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2373,8 +2519,8 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2384,9 +2530,9 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2396,7 +2542,7 @@ name = "term" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2406,7 +2552,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2424,9 +2570,9 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2434,8 +2580,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2452,8 +2598,8 @@ name = "thread-id" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2467,11 +2613,11 @@ dependencies = [ [[package]] name = "time" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2485,15 +2631,15 @@ dependencies = [ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2503,7 +2649,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2518,10 +2664,10 @@ dependencies = [ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2530,30 +2676,31 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2563,19 +2710,19 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2584,7 +2731,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2609,40 +2756,43 @@ dependencies = [ [[package]] name = "tokio-tcp" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2655,25 +2805,25 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2681,7 +2831,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2738,8 +2888,11 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "unicode-segmentation" @@ -2798,16 +2951,16 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "uuid" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2837,7 +2990,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2873,7 +3026,7 @@ name = "which" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2902,7 +3055,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2919,7 +3072,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winreg" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2936,7 +3097,7 @@ name = "xattr" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2969,23 +3130,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] +"checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" -"checksum arc-swap 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5c5ed110e2537bdd3f5b9091707a8a5556a72ac49bbd7302ae0b28fdccb3246c" +"checksum arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" -"checksum array-macro 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8b1b1a00de235e9f2cc0e650423dc249d875c116a5934188c08fdd0c02d840ef" +"checksum array-macro 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c4ff37a25fb442a1fecfd399be0dde685558bca30fb998420532889a36852d2" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f" -"checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" @@ -2997,9 +3160,9 @@ dependencies = [ "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum built 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61f5aae2fa15b68fbcf0cbab64e659a55d10e9bacc55d3470ef77ae73030d755" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" @@ -3011,41 +3174,45 @@ dependencies = [ "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" -"checksum croaring 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a2c82431f150237fc25ef9ece26ccbcc8325118f44a538b48449a7639cb6e9cf" -"checksum croaring-sys 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d36e44ca368664098be5d03576da36edd3e2c728df553f13f89cb25fbc3792c5" +"checksum croaring 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b350ece8a9ba71eeb9c068a98a86dc420ca5c1d6bd4e1627a4581e9c843c38" +"checksum croaring-sys 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "546b00f33bdf591bce6410a8dca65047d126b1d5a9189190d085aa8c493d43a7" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" "checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827" -"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" -"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971" "checksum csv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef22b37c7a51c564a365892c012dc0271221fdcc64c69b19ba4d6fa8bd96d9c" "checksum ct-logs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95a4bf5107667e12bf6ce31a3a5066d67acc88942b6742117a41198734aaccaa" "checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" +"checksum cursive 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad36e47ece323d806b1daa3c87c7eb2aae54ef15e6554e27fe3dbdacf6b515fc" "checksum cursive 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1df013f020cf1e66c456c9af584ae660590b8147186fd66b941604f85145b880" -"checksum daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4093d27eb267d617f03c2ee25d4c3ca525b89a76154001954a11984508ffbde5" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" "checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd" -"checksum encoding_rs 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1a8fa54e6689eb2549c4efed8d00d7f3b2b994a064555b0e8df4ae3764bcc4be" +"checksum encoding_rs 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)" = "fd251508d65030820f3a4317af2248180db337fdb25d89967956242580277813" "checksum enum-map 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "caa1769f019df7ccd8f9a741d2d608309688d0f1bd8a8747c14ac993660c761c" -"checksum enum-map-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f915c8ef505ce27b6fa51515463938aa2e9135081fefc93aef786539a646a365" +"checksum enum-map-derive 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "153f6e8a8b2868e2fedf921b165f30229edcccb74d6a9bb1ccf0480ef61cd07e" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" -"checksum enumset 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "410e0c8f67e79dcc08cb844c629e2845e9846b464e059b7f3c9d5311b4151d8d" +"checksum enumset 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "55da7777fd68a7213fa1d8f56ec3063141e44650c7fe7ae329ab69a0e77ecf00" "checksum enumset_derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24300e54ac8ddea74e337f0309c71df4a8c1d7a7fd48a287ef0af8354fadb788" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" -"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" "checksum flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2291c165c8e703ee54ef3055ad6188e3d51108e2ded18e9f2476e774fc5ad3d4" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" @@ -3055,13 +3222,13 @@ dependencies = [ "checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum grin_secp256k1zkp 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "223095ed6108a42855ab2ce368d2056cfd384705f81c494f6d88ab3383161562" -"checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0" +"checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" "checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" -"checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab" +"checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c49a75385d35ff5e9202755f09beb0b878a05c4c363fcc52b23eeb5dcb6782cc" +"checksum hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f1ebec079129e43af5e234ef36ee3d7e6085687d145b7ea653b262d16c6b65f1" "checksum hyper-rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68f2aa6b1681795bf4da8063f718cd23145aa0c9a5143d9787b345aa60d38ee4" "checksum hyper-staticfile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4080cb44b9c1e4c6dfd6f7ee85a9c3439777ec9c59df32f944836d3de58ac35e" "checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" @@ -3074,9 +3241,9 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" -"checksum libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4916b5addc78ec36cc309acfcdf0b9f9d97ab7b84083118b248709c5b7029356" +"checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" "checksum liblmdb-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" @@ -3093,31 +3260,31 @@ dependencies = [ "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" +"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "0a907b83e7b9e987032439a387e187119cddafc92d5c2aaeb1d92580a793f630" +"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" -"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" -"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" +"checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" +"checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mortal 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26153280e6a955881f761354b130aa7838f9983836f3de438ac0a8f22cfab1ff" "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" -"checksum ncurses 5.97.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee821144e7fe6fd1d1c04b8001d92d783ae471a71d60ab506e6c608b83a85ae6" +"checksum ncurses 5.98.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ddf9a2b0b4526dc8c5a57c859b0f4415b7b3258c487aaa11e07fbde2877744d" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" "checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" -"checksum nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c349f68f25f596b9f44cf0e7c69752a5c633b0550c3ff849518bfba0233774a" +"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" "checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" -"checksum num-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "10b8423ea72ec64751198856a853e07b37087cfc9b53a87ecb19bff67b6d1320" +"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" "checksum num-complex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" "checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" @@ -3126,54 +3293,61 @@ dependencies = [ "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" "checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" -"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613" +"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106" +"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" "checksum ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0015e9e8e28ee20c581cfbfe47c650cedeb9ed0721090e0b7ebb10b9cdbcc2" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum pancurses 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d3058bc37c433096b2ac7afef1c5cdfae49ede0a4ffec3dfc1df1df0959d0ff0" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum pbkdf2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0c09cddfbfc98de7f76931acf44460972edb4023eb14d0c6d4018800e552d8e0" +"checksum pdcurses-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90e12bfe55b7080fdfa0742f7a22ce7d5d1da250ca064ae6b81c843a2084fa2a" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "cec29da322b242f4c3098852c77a0ca261c9c01b806cae85a5572a1eb94db9a6" -"checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad" -"checksum phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "03dc191feb9b08b0dc1330d6549b795b9d81aec19efe6b4a45aec8d4caee0c4b" -"checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93" +"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum prettytable-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5511ca4c805aa35f0abff6be7923231d664408b60c09f44ef715f2bce106cd9e" "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" -"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "080723c6145e37503a2224f801f252e14ac5531cb450f4502698542d188cb3c0" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26" -"checksum reexport-proc-macro 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "438fe63770eda15baf98e30b4d27ada49b932866307fa04fec24d9043fe63324" +"checksum reexport-proc-macro 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b90ec417f693152463d468b6d06ccc45ae3833f0538ef9e1cc154cf09eb1f575" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" -"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ab52e462d1e15891441aeefadff68bdea005174328ce3da0a314f2ad313ec837" "checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" "checksum ripemd160 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "482aa56cc68aaeccdaaff1cc5a72c247da8bbad3beb174ca5741f274c22883fb" "checksum rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37473170aedbe66ffa3ad3726939ba677d83c646ad4fd99e5b4bc38712f45ec" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -3186,29 +3360,29 @@ dependencies = [ "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb8f61f9e6eadd062a71c380043d28036304a4706b3c4dd001ff3387ed00745a" -"checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0" -"checksum security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab01dfbe5756785b5b4d46e0289e5a18071dfa9a7c2b24213ea00b9ef9b665bf" +"checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" +"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c91eb5b0190ae87b4e2e39cbba6e3bed3ac6186935fe265f0426156c4c49961b" +"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" "checksum serde-value 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7a663f873dedc4eac1a559d4c6bc0d0b2c34dc5ac4702e105014b8281489e44f" -"checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" -"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" "checksum serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0887a8e097a69559b56aa2526bf7aff7c3048cf627dff781f0b56a6001534593" "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" -"checksum signal-hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8941ae94fa73d0f73b422774b3a40a7195cecd88d1c090f4b37ade7dc795ab66" +"checksum signal-hook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f272d1b7586bec132ed427f532dd418d8beca1ca7f2caf7df35569b1415a4b4" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallstr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6aa65bb4d5b2bbc90d36af64e29802f788aa614783fa1d0df011800ddcec6e8e" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98998cced76115b1da46f63388b909d118a37ae0be0f82ad35773d4a4bc9d18d" +"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum supercow 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" +"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" @@ -3220,23 +3394,23 @@ dependencies = [ "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6e93c78d23cc61aa245a8acd2c4a79c4d7fa7fb5c3ca90d5737029f043a84895" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" -"checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75" -"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" -"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" +"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" +"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" "checksum tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05746ae87dca83a2016b4f5dba5b237b897dd12fd324f60afe282112f16969a" "checksum tokio-rustls 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "208d62fa3e015426e3c64039d9d20adf054a3c9b4d9445560f1c41c75bef3eab" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" -"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912" -"checksum tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "56c5556262383032878afad66943926a1d1f0967f17e94bd7764ceceb3b70e7f" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99ce87382f6c1a24b513a72c048b2c8efe66cb5161c9061d00bee510f08dc168" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" @@ -3246,7 +3420,7 @@ dependencies = [ "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" @@ -3256,7 +3430,7 @@ dependencies = [ "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" -"checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6" +"checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" @@ -3270,9 +3444,10 @@ dependencies = [ "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" "checksum xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12ea8eda4b1eb72f02d148402e23832d56a33f55d8c1b2d5bcdde91d79d47cb1" diff --git a/Cargo.toml b/Cargo.toml index 40b80c2af..4bfd7d810 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,9 +25,7 @@ chrono = "0.4.4" clap = { version = "2.31", features = ["yaml"] } rpassword = "2.0.0" ctrlc = { version = "3.1", features = ["termination"] } -cursive = "0.9.0" humansize = "1.1.0" -daemonize = "0.3" serde = "1" serde_json = "1" log = "0.4" @@ -45,6 +43,11 @@ grin_servers = { path = "./servers", version = "1.0.1" } grin_util = { path = "./util", version = "1.0.1" } grin_wallet = { path = "./wallet", version = "1.0.1" } +[target.'cfg(windows)'.dependencies] +cursive = { version = "0.10.0", default-features = false, features = ["pancurses-backend"] } +[target.'cfg(unix)'.dependencies] +cursive = "0.9.0" + [build-dependencies] built = "0.3" reqwest = "0.9" diff --git a/chain/src/chain.rs b/chain/src/chain.rs index d518baec2..33504d544 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -857,6 +857,14 @@ impl Chain { } let header = self.get_block_header(&h)?; + + { + let mut txhashset_ref = self.txhashset.write(); + // Drop file handles in underlying txhashset + txhashset_ref.release_backend_files(); + } + + // Rewrite hashset txhashset::zip_write(self.db_root.clone(), txhashset_data, &header)?; let mut txhashset = diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index cbcf2d657..3520ebb2c 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -18,7 +18,7 @@ use crate::core::core::committed::Committed; use crate::core::core::hash::{Hash, Hashed}; use crate::core::core::merkle_proof::MerkleProof; -use crate::core::core::pmmr::{self, ReadonlyPMMR, RewindablePMMR, PMMR}; +use crate::core::core::pmmr::{self, Backend, ReadonlyPMMR, RewindablePMMR, PMMR}; use crate::core::core::{ Block, BlockHeader, Input, Output, OutputIdentifier, TxKernel, TxKernelEntry, }; @@ -153,6 +153,15 @@ impl TxHashSet { }) } + /// Close all backend file handles + pub fn release_backend_files(&mut self) { + self.header_pmmr_h.backend.release_files(); + self.sync_pmmr_h.backend.release_files(); + self.output_pmmr_h.backend.release_files(); + self.rproof_pmmr_h.backend.release_files(); + self.kernel_pmmr_h.backend.release_files(); + } + /// Check if an output is unspent. /// We look in the index to find the output MMR pos. /// Then we check the entry in the output MMR and confirm the hash matches. diff --git a/core/Cargo.toml b/core/Cargo.toml index 3b1a407c1..071ca1047 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] blake2-rfc = "0.2" byteorder = "1" -croaring = "=0.3" +croaring = "=0.3.8" enum_primitive = "0.1" failure = "0.1" failure_derive = "0.1" diff --git a/core/src/core/pmmr/backend.rs b/core/src/core/pmmr/backend.rs index 4f6789d93..e4e0e9d27 100644 --- a/core/src/core/pmmr/backend.rs +++ b/core/src/core/pmmr/backend.rs @@ -62,6 +62,9 @@ pub trait Backend { /// fastest way to to be able to allow direct access to the file fn get_data_file_path(&self) -> &Path; + /// Release underlying datafiles and locks + fn release_files(&mut self); + /// Also a bit of a hack... /// Saves a snapshot of the rewound utxo file with the block hash as /// filename suffix. We need this when sending a txhashset zip file to a diff --git a/core/tests/vec_backend.rs b/core/tests/vec_backend.rs index 675d5b05e..25143260b 100644 --- a/core/tests/vec_backend.rs +++ b/core/tests/vec_backend.rs @@ -122,6 +122,8 @@ impl Backend for VecBackend { Path::new("") } + fn release_files(&mut self) {} + fn dump_stats(&self) {} } diff --git a/src/bin/cmd/server.rs b/src/bin/cmd/server.rs index 7f9c325d4..ea9c4ad0b 100644 --- a/src/bin/cmd/server.rs +++ b/src/bin/cmd/server.rs @@ -13,6 +13,7 @@ // limitations under the License. /// Grin server commands processing +#[cfg(not(target_os = "windows"))] use std::env::current_dir; use std::process::exit; use std::sync::atomic::{AtomicBool, Ordering}; @@ -22,7 +23,6 @@ use std::time::Duration; use clap::ArgMatches; use ctrlc; -use daemonize::Daemonize; use crate::config::GlobalConfig; use crate::core::global; @@ -31,7 +31,7 @@ use crate::servers; use crate::tui::ui; /// wrap below to allow UI to clean up on stop -fn start_server(config: servers::ServerConfig) { +pub fn start_server(config: servers::ServerConfig) { start_server_tui(config); // Just kill process for now, otherwise the process // hangs around until sigint because the API server @@ -157,29 +157,11 @@ pub fn server_command( }); }*/ - // start the server in the different run modes (interactive or daemon) if let Some(a) = server_args { match a.subcommand() { ("run", _) => { start_server(server_config); } - ("start", _) => { - let daemonize = Daemonize::new() - .pid_file("/tmp/grin.pid") - .chown_pid_file(true) - .working_directory(current_dir().unwrap()) - .privileged_action(move || { - start_server(server_config.clone()); - loop { - thread::sleep(Duration::from_secs(60)); - } - }); - match daemonize.start() { - Ok(_) => info!("Grin server successfully started."), - Err(e) => error!("Error starting: {}", e), - } - } - ("stop", _) => println!("TODO. Just 'kill $pid' for now. Maybe /tmp/grin.pid is $pid"), ("", _) => { println!("Subcommand required, use 'grin help server' for details"); } diff --git a/src/bin/grin.yml b/src/bin/grin.yml index 1b1f08c6c..c64b665bf 100644 --- a/src/bin/grin.yml +++ b/src/bin/grin.yml @@ -44,10 +44,6 @@ subcommands: subcommands: - config: about: Generate a configuration grin-server.toml file in the current directory - - start: - about: Start the Grin server as a daemon - - stop: - about: Stop the Grin server daemon - run: about: Run the Grin server in this console - client: diff --git a/store/Cargo.toml b/store/Cargo.toml index 08fb61a45..2c663da3e 100644 --- a/store/Cargo.toml +++ b/store/Cargo.toml @@ -11,7 +11,7 @@ edition = "2018" [dependencies] byteorder = "1" -croaring = "=0.3" +croaring = "=0.3.8" env_logger = "0.5" libc = "0.2" failure = "0.1" diff --git a/store/src/lmdb.rs b/store/src/lmdb.rs index 128d95fc3..9cc5b32ef 100644 --- a/store/src/lmdb.rs +++ b/store/src/lmdb.rs @@ -73,11 +73,19 @@ pub fn new_named_env(path: String, name: String, max_readers: Option) -> lm env_builder.set_maxdbs(8).unwrap(); // half a TB should give us plenty room, will be an issue on 32 bits // (which we don't support anyway) - env_builder - .set_mapsize(549_755_813_888) - .unwrap_or_else(|e| { - panic!("Unable to allocate LMDB space: {:?}", e); - }); + + #[cfg(not(target_os = "windows"))] + env_builder.set_mapsize(5_368_709_120).unwrap_or_else(|e| { + panic!("Unable to allocate LMDB space: {:?}", e); + }); + //TODO: This is temporary to support (beta) windows support + //Windows allocates the entire file at once, so this needs to + //be changed to allocate as little as possible and increase as needed + #[cfg(target_os = "windows")] + env_builder.set_mapsize(524_288_000).unwrap_or_else(|e| { + panic!("Unable to allocate LMDB space: {:?}", e); + }); + if let Some(max_readers) = max_readers { env_builder .set_maxreaders(max_readers) diff --git a/store/src/pmmr.rs b/store/src/pmmr.rs index c6cf6b6c2..4fc031d43 100644 --- a/store/src/pmmr.rs +++ b/store/src/pmmr.rs @@ -152,6 +152,12 @@ impl Backend for PMMRBackend { self.data_file.path() } + /// Release underlying data files + fn release_files(&mut self) { + self.data_file.release(); + self.hash_file.release(); + } + fn snapshot(&self, header: &BlockHeader) -> Result<(), String> { self.leaf_set .snapshot(header) @@ -208,8 +214,8 @@ impl PMMRBackend { Ok(PMMRBackend { data_dir: data_dir.to_path_buf(), prunable, - hash_file, - data_file, + hash_file: hash_file, + data_file: data_file, leaf_set, prune_list, }) @@ -334,20 +340,11 @@ impl PMMRBackend { } self.prune_list.flush()?; } - // 4. Rename the compact copy of hash file and reopen it. - fs::rename( - tmp_prune_file_hash.clone(), - self.data_dir.join(PMMR_HASH_FILE), - )?; - self.hash_file = DataFile::open(self.data_dir.join(PMMR_HASH_FILE))?; + self.hash_file.replace(Path::new(&tmp_prune_file_hash))?; // 5. Rename the compact copy of the data file and reopen it. - fs::rename( - tmp_prune_file_data.clone(), - self.data_dir.join(PMMR_DATA_FILE), - )?; - self.data_file = DataFile::open(self.data_dir.join(PMMR_DATA_FILE))?; + self.data_file.replace(Path::new(&tmp_prune_file_data))?; // 6. Write the leaf_set to disk. // Optimize the bitmap storage in the process. diff --git a/store/src/types.rs b/store/src/types.rs index d53f81b1c..379749a31 100644 --- a/store/src/types.rs +++ b/store/src/types.rs @@ -101,6 +101,17 @@ where self.file.path() } + /// Replace underlying file with another, deleting original + pub fn replace(&mut self, with: &Path) -> io::Result<()> { + self.file.replace(with)?; + Ok(()) + } + + /// Drop underlying file handles + pub fn release(&mut self) { + self.file.release(); + } + /// Write the file out to disk, pruning removed elements. pub fn save_prune(&self, target: &str, prune_offs: &[u64], prune_cb: F) -> io::Result<()> where @@ -125,7 +136,7 @@ where /// latter by truncating the underlying file and re-creating the mmap. pub struct AppendOnlyFile { path: PathBuf, - file: File, + file: Option, mmap: Option, buffer_start: usize, buffer: Vec, @@ -135,28 +146,36 @@ pub struct AppendOnlyFile { impl AppendOnlyFile { /// Open a file (existing or not) as append-only, backed by a mmap. pub fn open>(path: P) -> io::Result { - let file = OpenOptions::new() - .read(true) - .append(true) - .create(true) - .open(&path)?; let mut aof = AppendOnlyFile { - file, + file: None, path: path.as_ref().to_path_buf(), mmap: None, buffer_start: 0, buffer: vec![], buffer_start_bak: 0, }; - // If we have a non-empty file then mmap it. - let sz = aof.size(); - if sz > 0 { - aof.buffer_start = sz as usize; - aof.mmap = Some(unsafe { memmap::Mmap::map(&aof.file)? }); - } + aof.init()?; Ok(aof) } + /// (Re)init an underlying file and its associated memmap + pub fn init(&mut self) -> io::Result<()> { + self.file = Some( + OpenOptions::new() + .read(true) + .append(true) + .create(true) + .open(self.path.clone())?, + ); + // If we have a non-empty file then mmap it. + let sz = self.size(); + if sz > 0 { + self.buffer_start = sz as usize; + self.mmap = Some(unsafe { memmap::Mmap::map(&self.file.as_ref().unwrap())? }); + } + Ok(()) + } + /// Append data to the file. Until the append-only file is synced, data is /// only written to memory. pub fn append(&mut self, bytes: &mut [u8]) { @@ -193,21 +212,37 @@ impl AppendOnlyFile { pub fn flush(&mut self) -> io::Result<()> { if self.buffer_start_bak > 0 { // Flushing a rewound state, we need to truncate via set_len() before applying. - self.file.set_len(self.buffer_start as u64)?; + // Drop and recreate, or windows throws an access error + self.mmap = None; + self.file = None; + { + let file = OpenOptions::new() + .read(true) + .create(true) + .write(true) + .open(&self.path)?; + file.set_len(self.buffer_start as u64)?; + } + let file = OpenOptions::new() + .read(true) + .create(true) + .append(true) + .open(&self.path)?; + self.file = Some(file); self.buffer_start_bak = 0; } self.buffer_start += self.buffer.len(); - self.file.write_all(&self.buffer[..])?; - self.file.sync_all()?; + self.file.as_mut().unwrap().write_all(&self.buffer[..])?; + self.file.as_mut().unwrap().sync_all()?; self.buffer = vec![]; // Note: file must be non-empty to memory map it - if self.file.metadata()?.len() == 0 { + if self.file.as_ref().unwrap().metadata()?.len() == 0 { self.mmap = None; } else { - self.mmap = Some(unsafe { memmap::Mmap::map(&self.file)? }); + self.mmap = Some(unsafe { memmap::Mmap::map(&self.file.as_ref().unwrap())? }); } Ok(()) @@ -313,6 +348,23 @@ impl AppendOnlyFile { } } + /// Replace the underlying file with another file + /// deleting the original + pub fn replace(&mut self, with: &Path) -> io::Result<()> { + self.mmap = None; + self.file = None; + fs::remove_file(&self.path)?; + fs::rename(with, &self.path)?; + self.init()?; + Ok(()) + } + + /// Release underlying file handles + pub fn release(&mut self) { + self.mmap = None; + self.file = None; + } + /// Current size of the file in bytes. pub fn size(&self) -> u64 { fs::metadata(&self.path).map(|md| md.len()).unwrap_or(0) diff --git a/store/tests/pmmr.rs b/store/tests/pmmr.rs index 28e9d82bc..26d75ec7f 100644 --- a/store/tests/pmmr.rs +++ b/store/tests/pmmr.rs @@ -30,46 +30,48 @@ use crate::store::types::prune_noop; #[test] fn pmmr_append() { let (data_dir, elems) = setup("append"); - let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); - - // adding first set of 4 elements and sync - let mut mmr_size = load(0, &elems[0..4], &mut backend); - backend.sync().unwrap(); - - // adding the rest and sync again - mmr_size = load(mmr_size, &elems[4..9], &mut backend); - backend.sync().unwrap(); - - // check the resulting backend store and the computation of the root - let node_hash = elems[0].hash_with_index(0); - assert_eq!(backend.get_hash(1).unwrap(), node_hash); - - // 0010012001001230 - - let pos_0 = elems[0].hash_with_index(0); - let pos_1 = elems[1].hash_with_index(1); - let pos_2 = (pos_0, pos_1).hash_with_index(2); - - let pos_3 = elems[2].hash_with_index(3); - let pos_4 = elems[3].hash_with_index(4); - let pos_5 = (pos_3, pos_4).hash_with_index(5); - let pos_6 = (pos_2, pos_5).hash_with_index(6); - - let pos_7 = elems[4].hash_with_index(7); - let pos_8 = elems[5].hash_with_index(8); - let pos_9 = (pos_7, pos_8).hash_with_index(9); - - let pos_10 = elems[6].hash_with_index(10); - let pos_11 = elems[7].hash_with_index(11); - let pos_12 = (pos_10, pos_11).hash_with_index(12); - let pos_13 = (pos_9, pos_12).hash_with_index(13); - let pos_14 = (pos_6, pos_13).hash_with_index(14); - - let pos_15 = elems[8].hash_with_index(15); - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(pmmr.root(), (pos_14, pos_15).hash_with_index(16)); + let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); + + // adding first set of 4 elements and sync + let mut mmr_size = load(0, &elems[0..4], &mut backend); + backend.sync().unwrap(); + + // adding the rest and sync again + mmr_size = load(mmr_size, &elems[4..9], &mut backend); + backend.sync().unwrap(); + + // check the resulting backend store and the computation of the root + let node_hash = elems[0].hash_with_index(0); + assert_eq!(backend.get_hash(1).unwrap(), node_hash); + + // 0010012001001230 + + let pos_0 = elems[0].hash_with_index(0); + let pos_1 = elems[1].hash_with_index(1); + let pos_2 = (pos_0, pos_1).hash_with_index(2); + + let pos_3 = elems[2].hash_with_index(3); + let pos_4 = elems[3].hash_with_index(4); + let pos_5 = (pos_3, pos_4).hash_with_index(5); + let pos_6 = (pos_2, pos_5).hash_with_index(6); + + let pos_7 = elems[4].hash_with_index(7); + let pos_8 = elems[5].hash_with_index(8); + let pos_9 = (pos_7, pos_8).hash_with_index(9); + + let pos_10 = elems[6].hash_with_index(10); + let pos_11 = elems[7].hash_with_index(11); + let pos_12 = (pos_10, pos_11).hash_with_index(12); + let pos_13 = (pos_9, pos_12).hash_with_index(13); + let pos_14 = (pos_6, pos_13).hash_with_index(14); + + let pos_15 = elems[8].hash_with_index(15); + + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(pmmr.root(), (pos_14, pos_15).hash_with_index(16)); + } } teardown(data_dir); @@ -80,69 +82,71 @@ fn pmmr_compact_leaf_sibling() { let (data_dir, elems) = setup("compact_leaf_sibling"); // setup the mmr store with all elements - let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); - let mmr_size = load(0, &elems[..], &mut backend); - backend.sync().unwrap(); - - // On far left of the MMR - - // pos 1 and 2 are leaves (and siblings) - // the parent is pos 3 - - let (pos_1_hash, pos_2_hash, pos_3_hash) = { - let pmmr = PMMR::at(&mut backend, mmr_size); - ( - pmmr.get_hash(1).unwrap(), - pmmr.get_hash(2).unwrap(), - pmmr.get_hash(3).unwrap(), - ) - }; - - // prune pos 1 { - let mut pmmr = PMMR::at(&mut backend, mmr_size); - pmmr.prune(1).unwrap(); + let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); + let mmr_size = load(0, &elems[..], &mut backend); + backend.sync().unwrap(); - // prune pos 8 as well to push the remove list past the cutoff - pmmr.prune(8).unwrap(); + // On far left of the MMR - + // pos 1 and 2 are leaves (and siblings) + // the parent is pos 3 + + let (pos_1_hash, pos_2_hash, pos_3_hash) = { + let pmmr = PMMR::at(&mut backend, mmr_size); + ( + pmmr.get_hash(1).unwrap(), + pmmr.get_hash(2).unwrap(), + pmmr.get_hash(3).unwrap(), + ) + }; + + // prune pos 1 + { + let mut pmmr = PMMR::at(&mut backend, mmr_size); + pmmr.prune(1).unwrap(); + + // prune pos 8 as well to push the remove list past the cutoff + pmmr.prune(8).unwrap(); + } + backend.sync().unwrap(); + + // // check pos 1, 2, 3 are in the state we expect after pruning + { + let pmmr = PMMR::at(&mut backend, mmr_size); + + // check that pos 1 is "removed" + assert_eq!(pmmr.get_hash(1), None); + + // check that pos 2 and 3 are unchanged + assert_eq!(pmmr.get_hash(2).unwrap(), pos_2_hash); + assert_eq!(pmmr.get_hash(3).unwrap(), pos_3_hash); + } + + // check we can still retrieve the "removed" element at pos 1 + // from the backend hash file. + assert_eq!(backend.get_from_file(1).unwrap(), pos_1_hash); + + // aggressively compact the PMMR files + backend + .check_compact(1, &Bitmap::create(), &prune_noop) + .unwrap(); + + // check pos 1, 2, 3 are in the state we expect after compacting + { + let pmmr = PMMR::at(&mut backend, mmr_size); + + // check that pos 1 is "removed" + assert_eq!(pmmr.get_hash(1), None); + + // check that pos 2 and 3 are unchanged + assert_eq!(pmmr.get_hash(2).unwrap(), pos_2_hash); + assert_eq!(pmmr.get_hash(3).unwrap(), pos_3_hash); + } + + // Check we can still retrieve the "removed" hash at pos 1 from the hash file. + // It should still be available even after pruning and compacting. + assert_eq!(backend.get_from_file(1).unwrap(), pos_1_hash); } - backend.sync().unwrap(); - - // // check pos 1, 2, 3 are in the state we expect after pruning - { - let pmmr = PMMR::at(&mut backend, mmr_size); - - // check that pos 1 is "removed" - assert_eq!(pmmr.get_hash(1), None); - - // check that pos 2 and 3 are unchanged - assert_eq!(pmmr.get_hash(2).unwrap(), pos_2_hash); - assert_eq!(pmmr.get_hash(3).unwrap(), pos_3_hash); - } - - // check we can still retrieve the "removed" element at pos 1 - // from the backend hash file. - assert_eq!(backend.get_from_file(1).unwrap(), pos_1_hash); - - // aggressively compact the PMMR files - backend - .check_compact(1, &Bitmap::create(), &prune_noop) - .unwrap(); - - // check pos 1, 2, 3 are in the state we expect after compacting - { - let pmmr = PMMR::at(&mut backend, mmr_size); - - // check that pos 1 is "removed" - assert_eq!(pmmr.get_hash(1), None); - - // check that pos 2 and 3 are unchanged - assert_eq!(pmmr.get_hash(2).unwrap(), pos_2_hash); - assert_eq!(pmmr.get_hash(3).unwrap(), pos_3_hash); - } - - // Check we can still retrieve the "removed" hash at pos 1 from the hash file. - // It should still be available even after pruning and compacting. - assert_eq!(backend.get_from_file(1).unwrap(), pos_1_hash); teardown(data_dir); } @@ -152,46 +156,48 @@ fn pmmr_prune_compact() { let (data_dir, elems) = setup("prune_compact"); // setup the mmr store with all elements - let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); - let mmr_size = load(0, &elems[..], &mut backend); - backend.sync().unwrap(); - - // save the root - let root = { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.root() - }; - - // pruning some choice nodes { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(1).unwrap(); - pmmr.prune(4).unwrap(); - pmmr.prune(5).unwrap(); - } - backend.sync().unwrap(); + let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); + let mmr_size = load(0, &elems[..], &mut backend); + backend.sync().unwrap(); - // check the root and stored data - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); - // check we can still retrieve same element from leaf index 2 - assert_eq!(pmmr.get_data(2).unwrap(), TestElem(2)); - // and the same for leaf index 7 - assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); - } + // save the root + let root = { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.root() + }; - // compact - backend - .check_compact(2, &Bitmap::create(), &prune_noop) - .unwrap(); + // pruning some choice nodes + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(1).unwrap(); + pmmr.prune(4).unwrap(); + pmmr.prune(5).unwrap(); + } + backend.sync().unwrap(); - // recheck the root and stored data - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); - assert_eq!(pmmr.get_data(2).unwrap(), TestElem(2)); - assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); + // check the root and stored data + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(root, pmmr.root()); + // check we can still retrieve same element from leaf index 2 + assert_eq!(pmmr.get_data(2).unwrap(), TestElem(2)); + // and the same for leaf index 7 + assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); + } + + // compact + backend + .check_compact(2, &Bitmap::create(), &prune_noop) + .unwrap(); + + // recheck the root and stored data + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(root, pmmr.root()); + assert_eq!(pmmr.get_data(2).unwrap(), TestElem(2)); + assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); + } } teardown(data_dir); @@ -202,94 +208,97 @@ fn pmmr_reload() { let (data_dir, elems) = setup("reload"); // set everything up with an initial backend - let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); - - let mmr_size = load(0, &elems[..], &mut backend); - - // retrieve entries from the hash file for comparison later - let pos_3_hash = backend.get_hash(3).unwrap(); - let pos_4_hash = backend.get_hash(4).unwrap(); - let pos_5_hash = backend.get_hash(5).unwrap(); - - // save the root - let root = { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.root() - }; - - { - backend.sync().unwrap(); - - // prune a node so we have prune data - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(1).unwrap(); - } - backend.sync().unwrap(); - - // now check and compact the backend - backend - .check_compact(1, &Bitmap::create(), &prune_noop) - .unwrap(); - backend.sync().unwrap(); - - // prune another node to force compact to actually do something - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(4).unwrap(); - pmmr.prune(2).unwrap(); - } - backend.sync().unwrap(); - - backend - .check_compact(4, &Bitmap::create(), &prune_noop) - .unwrap(); - backend.sync().unwrap(); - - assert_eq!(backend.unpruned_size(), mmr_size); - - // prune some more to get rm log data - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(5).unwrap(); - } - backend.sync().unwrap(); - assert_eq!(backend.unpruned_size(), mmr_size); - } - - // create a new backend referencing the data files - // and check everything still works as expected { let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); - assert_eq!(backend.unpruned_size(), mmr_size); - { + + let mmr_size = load(0, &elems[..], &mut backend); + + // retrieve entries from the hash file for comparison later + let pos_3_hash = backend.get_hash(3).unwrap(); + let pos_4_hash = backend.get_hash(4).unwrap(); + let pos_5_hash = backend.get_hash(5).unwrap(); + + // save the root + let root = { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); + pmmr.root() + }; + + { + backend.sync().unwrap(); + + // prune a node so we have prune data + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(1).unwrap(); + } + backend.sync().unwrap(); + + // now check and compact the backend + backend + .check_compact(1, &Bitmap::create(), &prune_noop) + .unwrap(); + backend.sync().unwrap(); + + // prune another node to force compact to actually do something + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(4).unwrap(); + pmmr.prune(2).unwrap(); + } + backend.sync().unwrap(); + + backend + .check_compact(4, &Bitmap::create(), &prune_noop) + .unwrap(); + backend.sync().unwrap(); + + assert_eq!(backend.unpruned_size(), mmr_size); + + // prune some more to get rm log data + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(5).unwrap(); + } + backend.sync().unwrap(); + assert_eq!(backend.unpruned_size(), mmr_size); } - // pos 1 and pos 2 are both removed (via parent pos 3 in prune list) - assert_eq!(backend.get_hash(1), None); - assert_eq!(backend.get_hash(2), None); + // create a new backend referencing the data files + // and check everything still works as expected + { + let mut backend = + store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); + assert_eq!(backend.unpruned_size(), mmr_size); + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(root, pmmr.root()); + } - // pos 3 is "removed" but we keep the hash around for root of pruned subtree - assert_eq!(backend.get_hash(3), Some(pos_3_hash)); + // pos 1 and pos 2 are both removed (via parent pos 3 in prune list) + assert_eq!(backend.get_hash(1), None); + assert_eq!(backend.get_hash(2), None); - // pos 4 is removed (via prune list) - assert_eq!(backend.get_hash(4), None); - // pos 5 is removed (via leaf_set) - assert_eq!(backend.get_hash(5), None); + // pos 3 is "removed" but we keep the hash around for root of pruned subtree + assert_eq!(backend.get_hash(3), Some(pos_3_hash)); - // now check contents of the hash file - // pos 1 and pos 2 are no longer in the hash file - assert_eq!(backend.get_from_file(1), None); - assert_eq!(backend.get_from_file(2), None); + // pos 4 is removed (via prune list) + assert_eq!(backend.get_hash(4), None); + // pos 5 is removed (via leaf_set) + assert_eq!(backend.get_hash(5), None); - // pos 3 is still in there - assert_eq!(backend.get_from_file(3), Some(pos_3_hash)); + // now check contents of the hash file + // pos 1 and pos 2 are no longer in the hash file + assert_eq!(backend.get_from_file(1), None); + assert_eq!(backend.get_from_file(2), None); - // pos 4 and pos 5 are also still in there - assert_eq!(backend.get_from_file(4), Some(pos_4_hash)); - assert_eq!(backend.get_from_file(5), Some(pos_5_hash)); + // pos 3 is still in there + assert_eq!(backend.get_from_file(3), Some(pos_3_hash)); + + // pos 4 and pos 5 are also still in there + assert_eq!(backend.get_from_file(4), Some(pos_4_hash)); + assert_eq!(backend.get_from_file(5), Some(pos_5_hash)); + } } teardown(data_dir); @@ -298,126 +307,130 @@ fn pmmr_reload() { #[test] fn pmmr_rewind() { let (data_dir, elems) = setup("rewind"); - let mut backend = store::pmmr::PMMRBackend::new(data_dir.clone(), true, None).unwrap(); - - // adding elements and keeping the corresponding root - let mut mmr_size = load(0, &elems[0..4], &mut backend); - backend.sync().unwrap(); - let root1 = { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.root() - }; - - mmr_size = load(mmr_size, &elems[4..6], &mut backend); - backend.sync().unwrap(); - let root2 = { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(pmmr.unpruned_size(), 10); - pmmr.root() - }; - - mmr_size = load(mmr_size, &elems[6..9], &mut backend); - backend.sync().unwrap(); - let root3 = { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(pmmr.unpruned_size(), 16); - pmmr.root() - }; - - // prune the first 4 elements (leaves at pos 1, 2, 4, 5) { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(1).unwrap(); - pmmr.prune(2).unwrap(); - pmmr.prune(4).unwrap(); - pmmr.prune(5).unwrap(); + let mut backend = store::pmmr::PMMRBackend::new(data_dir.clone(), true, None).unwrap(); + + // adding elements and keeping the corresponding root + let mut mmr_size = load(0, &elems[0..4], &mut backend); + backend.sync().unwrap(); + let root1 = { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.root() + }; + + mmr_size = load(mmr_size, &elems[4..6], &mut backend); + backend.sync().unwrap(); + let root2 = { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(pmmr.unpruned_size(), 10); + pmmr.root() + }; + + mmr_size = load(mmr_size, &elems[6..9], &mut backend); + backend.sync().unwrap(); + let root3 = { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(pmmr.unpruned_size(), 16); + pmmr.root() + }; + + // prune the first 4 elements (leaves at pos 1, 2, 4, 5) + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(1).unwrap(); + pmmr.prune(2).unwrap(); + pmmr.prune(4).unwrap(); + pmmr.prune(5).unwrap(); + } + backend.sync().unwrap(); + + println!("before compacting - "); + for x in 1..17 { + println!("pos {}, {:?}", x, backend.get_from_file(x)); + } + + // and compact the MMR to remove the pruned elements + backend + .check_compact(6, &Bitmap::create(), &prune_noop) + .unwrap(); + backend.sync().unwrap(); + + println!("after compacting - "); + for x in 1..17 { + println!("pos {}, {:?}", x, backend.get_from_file(x)); + } + + println!("root1 {:?}, root2 {:?}, root3 {:?}", root1, root2, root3); + + // rewind and check the roots still match + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.rewind(9, &Bitmap::of(&vec![11, 12, 16])).unwrap(); + assert_eq!(pmmr.unpruned_size(), 10); + + // assert_eq!(pmmr.root(), root2); + } + println!("after rewinding - "); + for x in 1..17 { + println!("pos {}, {:?}", x, backend.get_from_file(x)); + } + + println!("doing a sync after rewinding"); + if let Err(e) = backend.sync() { + panic!("Err: {:?}", e); + } + + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 10); + assert_eq!(pmmr.root(), root2); + } + + // Also check the data file looks correct. + // pos 1, 2, 4, 5 are all leaves but these have been pruned. + for pos in vec![1, 2, 4, 5] { + assert_eq!(backend.get_data(pos), None); + } + // pos 3, 6, 7 are non-leaves so we have no data for these + for pos in vec![3, 6, 7] { + assert_eq!(backend.get_data(pos), None); + } + + // pos 8 and 9 are both leaves and should be unaffected by prior pruning + + for x in 1..16 { + println!("data at {}, {:?}", x, backend.get_data(x)); + } + + assert_eq!(backend.get_data(8), Some(elems[4])); + assert_eq!(backend.get_hash(8), Some(elems[4].hash_with_index(7))); + + assert_eq!(backend.get_data(9), Some(elems[5])); + assert_eq!(backend.get_hash(9), Some(elems[5].hash_with_index(8))); + + assert_eq!(backend.data_size(), 2); + + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 10); + pmmr.rewind(5, &Bitmap::create()).unwrap(); + assert_eq!(pmmr.root(), root1); + } + backend.sync().unwrap(); + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 7); + assert_eq!(pmmr.root(), root1); + } + + // also check the data file looks correct + // everything up to and including pos 7 should be pruned from the data file + // but we have rewound to pos 5 so everything after that should be None + for pos in 1..10 { + assert_eq!(backend.get_data(pos), None); + } + + // check we have no data in the backend after + // pruning, compacting and rewinding + assert_eq!(backend.data_size(), 0); } - backend.sync().unwrap(); - - println!("before compacting - "); - for x in 1..17 { - println!("pos {}, {:?}", x, backend.get_from_file(x)); - } - - // and compact the MMR to remove the pruned elements - backend - .check_compact(6, &Bitmap::create(), &prune_noop) - .unwrap(); - backend.sync().unwrap(); - - println!("after compacting - "); - for x in 1..17 { - println!("pos {}, {:?}", x, backend.get_from_file(x)); - } - - println!("root1 {:?}, root2 {:?}, root3 {:?}", root1, root2, root3); - - // rewind and check the roots still match - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.rewind(9, &Bitmap::of(&vec![11, 12, 16])).unwrap(); - assert_eq!(pmmr.unpruned_size(), 10); - - // assert_eq!(pmmr.root(), root2); - } - println!("after rewinding - "); - for x in 1..17 { - println!("pos {}, {:?}", x, backend.get_from_file(x)); - } - - println!("doing a sync after rewinding"); - backend.sync().unwrap(); - - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 10); - assert_eq!(pmmr.root(), root2); - } - - // Also check the data file looks correct. - // pos 1, 2, 4, 5 are all leaves but these have been pruned. - for pos in vec![1, 2, 4, 5] { - assert_eq!(backend.get_data(pos), None); - } - // pos 3, 6, 7 are non-leaves so we have no data for these - for pos in vec![3, 6, 7] { - assert_eq!(backend.get_data(pos), None); - } - - // pos 8 and 9 are both leaves and should be unaffected by prior pruning - - for x in 1..16 { - println!("data at {}, {:?}", x, backend.get_data(x)); - } - - assert_eq!(backend.get_data(8), Some(elems[4])); - assert_eq!(backend.get_hash(8), Some(elems[4].hash_with_index(7))); - - assert_eq!(backend.get_data(9), Some(elems[5])); - assert_eq!(backend.get_hash(9), Some(elems[5].hash_with_index(8))); - - assert_eq!(backend.data_size(), 2); - - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 10); - pmmr.rewind(5, &Bitmap::create()).unwrap(); - assert_eq!(pmmr.root(), root1); - } - backend.sync().unwrap(); - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 7); - assert_eq!(pmmr.root(), root1); - } - - // also check the data file looks correct - // everything up to and including pos 7 should be pruned from the data file - // but we have rewound to pos 5 so everything after that should be None - for pos in 1..10 { - assert_eq!(backend.get_data(pos), None); - } - - // check we have no data in the backend after - // pruning, compacting and rewinding - assert_eq!(backend.data_size(), 0); teardown(data_dir); } @@ -425,216 +438,238 @@ fn pmmr_rewind() { #[test] fn pmmr_compact_single_leaves() { let (data_dir, elems) = setup("compact_single_leaves"); - let mut backend = store::pmmr::PMMRBackend::new(data_dir.clone(), true, None).unwrap(); - let mmr_size = load(0, &elems[0..5], &mut backend); - backend.sync().unwrap(); - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(1).unwrap(); - pmmr.prune(4).unwrap(); + let mut backend = store::pmmr::PMMRBackend::new(data_dir.clone(), true, None).unwrap(); + let mmr_size = load(0, &elems[0..5], &mut backend); + backend.sync().unwrap(); + + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(1).unwrap(); + pmmr.prune(4).unwrap(); + } + + backend.sync().unwrap(); + + // compact + backend + .check_compact(2, &Bitmap::create(), &prune_noop) + .unwrap(); + + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(2).unwrap(); + pmmr.prune(5).unwrap(); + } + + backend.sync().unwrap(); + + // compact + backend + .check_compact(2, &Bitmap::create(), &prune_noop) + .unwrap(); } - backend.sync().unwrap(); - - // compact - backend - .check_compact(2, &Bitmap::create(), &prune_noop) - .unwrap(); - - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(2).unwrap(); - pmmr.prune(5).unwrap(); - } - - backend.sync().unwrap(); - - // compact - backend - .check_compact(2, &Bitmap::create(), &prune_noop) - .unwrap(); - teardown(data_dir); } #[test] fn pmmr_compact_entire_peak() { let (data_dir, elems) = setup("compact_entire_peak"); - let mut backend = store::pmmr::PMMRBackend::new(data_dir.clone(), true, None).unwrap(); - let mmr_size = load(0, &elems[0..5], &mut backend); - backend.sync().unwrap(); - - let pos_7_hash = backend.get_hash(7).unwrap(); - - let pos_8 = backend.get_data(8).unwrap(); - let pos_8_hash = backend.get_hash(8).unwrap(); - - // prune all leaves under the peak at pos 7 { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(1).unwrap(); - pmmr.prune(2).unwrap(); - pmmr.prune(4).unwrap(); - pmmr.prune(5).unwrap(); + let mut backend = store::pmmr::PMMRBackend::new(data_dir.clone(), true, None).unwrap(); + let mmr_size = load(0, &elems[0..5], &mut backend); + backend.sync().unwrap(); + + let pos_7_hash = backend.get_hash(7).unwrap(); + + let pos_8 = backend.get_data(8).unwrap(); + let pos_8_hash = backend.get_hash(8).unwrap(); + + // prune all leaves under the peak at pos 7 + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(1).unwrap(); + pmmr.prune(2).unwrap(); + pmmr.prune(4).unwrap(); + pmmr.prune(5).unwrap(); + } + + backend.sync().unwrap(); + + // compact + backend + .check_compact(2, &Bitmap::create(), &prune_noop) + .unwrap(); + + // now check we have pruned up to and including the peak at pos 7 + // hash still available in underlying hash file + assert_eq!(backend.get_hash(7), Some(pos_7_hash)); + assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); + + // now check we still have subsequent hash and data where we expect + assert_eq!(backend.get_data(8), Some(pos_8)); + assert_eq!(backend.get_hash(8), Some(pos_8_hash)); + assert_eq!(backend.get_from_file(8), Some(pos_8_hash)); } - backend.sync().unwrap(); - - // compact - backend - .check_compact(2, &Bitmap::create(), &prune_noop) - .unwrap(); - - // now check we have pruned up to and including the peak at pos 7 - // hash still available in underlying hash file - assert_eq!(backend.get_hash(7), Some(pos_7_hash)); - assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); - - // now check we still have subsequent hash and data where we expect - assert_eq!(backend.get_data(8), Some(pos_8)); - assert_eq!(backend.get_hash(8), Some(pos_8_hash)); - assert_eq!(backend.get_from_file(8), Some(pos_8_hash)); - teardown(data_dir); } #[test] fn pmmr_compact_horizon() { let (data_dir, elems) = setup("compact_horizon"); - let mut backend = store::pmmr::PMMRBackend::new(data_dir.clone(), true, None).unwrap(); - let mmr_size = load(0, &elems[..], &mut backend); - backend.sync().unwrap(); - - // 0010012001001230 - // 9 leaves - assert_eq!(backend.data_size(), 19); - assert_eq!(backend.hash_size(), 35); - - let pos_1_hash = backend.get_hash(1).unwrap(); - let pos_2_hash = backend.get_hash(2).unwrap(); - let pos_3_hash = backend.get_hash(3).unwrap(); - let pos_6_hash = backend.get_hash(6).unwrap(); - let pos_7_hash = backend.get_hash(7).unwrap(); - - let pos_8 = backend.get_data(8).unwrap(); - let pos_8_hash = backend.get_hash(8).unwrap(); - - let pos_11 = backend.get_data(11).unwrap(); - let pos_11_hash = backend.get_hash(11).unwrap(); - { - // pruning some choice nodes + let pos_1_hash; + let pos_2_hash; + let pos_3_hash; + let pos_6_hash; + let pos_7_hash; + + let pos_8; + let pos_8_hash; + + let pos_11; + let pos_11_hash; + + let mmr_size; { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(4).unwrap(); - pmmr.prune(5).unwrap(); - pmmr.prune(1).unwrap(); - pmmr.prune(2).unwrap(); + let mut backend = store::pmmr::PMMRBackend::new(data_dir.clone(), true, None).unwrap(); + mmr_size = load(0, &elems[..], &mut backend); + backend.sync().unwrap(); + + // 0010012001001230 + // 9 leaves + assert_eq!(backend.data_size(), 19); + assert_eq!(backend.hash_size(), 35); + + pos_1_hash = backend.get_hash(1).unwrap(); + pos_2_hash = backend.get_hash(2).unwrap(); + pos_3_hash = backend.get_hash(3).unwrap(); + pos_6_hash = backend.get_hash(6).unwrap(); + pos_7_hash = backend.get_hash(7).unwrap(); + + pos_8 = backend.get_data(8).unwrap(); + pos_8_hash = backend.get_hash(8).unwrap(); + + pos_11 = backend.get_data(11).unwrap(); + pos_11_hash = backend.get_hash(11).unwrap(); + + // pruning some choice nodes + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(4).unwrap(); + pmmr.prune(5).unwrap(); + pmmr.prune(1).unwrap(); + pmmr.prune(2).unwrap(); + } + backend.sync().unwrap(); + + // check we can read hashes and data correctly after pruning + { + // assert_eq!(backend.get_hash(3), None); + assert_eq!(backend.get_from_file(3), Some(pos_3_hash)); + + // assert_eq!(backend.get_hash(6), None); + assert_eq!(backend.get_from_file(6), Some(pos_6_hash)); + + // assert_eq!(backend.get_hash(7), None); + assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); + + assert_eq!(backend.get_hash(8), Some(pos_8_hash)); + assert_eq!(backend.get_data(8), Some(pos_8)); + assert_eq!(backend.get_from_file(8), Some(pos_8_hash)); + + assert_eq!(backend.get_hash(11), Some(pos_11_hash)); + assert_eq!(backend.get_data(11), Some(pos_11)); + assert_eq!(backend.get_from_file(11), Some(pos_11_hash)); + } + + // compact + backend + .check_compact(4, &Bitmap::of(&vec![1, 2]), &prune_noop) + .unwrap(); + backend.sync().unwrap(); + + // check we can read a hash by pos correctly after compaction + { + assert_eq!(backend.get_hash(1), None); + assert_eq!(backend.get_from_file(1), Some(pos_1_hash)); + + assert_eq!(backend.get_hash(2), None); + assert_eq!(backend.get_from_file(2), Some(pos_2_hash)); + + assert_eq!(backend.get_hash(3), Some(pos_3_hash)); + + assert_eq!(backend.get_hash(4), None); + assert_eq!(backend.get_hash(5), None); + assert_eq!(backend.get_hash(6), Some(pos_6_hash)); + + assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); + + assert_eq!(backend.get_hash(8), Some(pos_8_hash)); + assert_eq!(backend.get_from_file(8), Some(pos_8_hash)); + } } - backend.sync().unwrap(); - // check we can read hashes and data correctly after pruning + // recheck stored data { - // assert_eq!(backend.get_hash(3), None); - assert_eq!(backend.get_from_file(3), Some(pos_3_hash)); + // recreate backend + let backend = + store::pmmr::PMMRBackend::::new(data_dir.to_string(), true, None) + .unwrap(); - // assert_eq!(backend.get_hash(6), None); - assert_eq!(backend.get_from_file(6), Some(pos_6_hash)); + assert_eq!(backend.data_size(), 19); + assert_eq!(backend.hash_size(), 35); - // assert_eq!(backend.get_hash(7), None); + // check we can read a hash by pos correctly from recreated backend + assert_eq!(backend.get_hash(7), Some(pos_7_hash)); assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); assert_eq!(backend.get_hash(8), Some(pos_8_hash)); - assert_eq!(backend.get_data(8), Some(pos_8)); assert_eq!(backend.get_from_file(8), Some(pos_8_hash)); + } + + { + let mut backend = + store::pmmr::PMMRBackend::::new(data_dir.to_string(), true, None) + .unwrap(); + + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + + pmmr.prune(8).unwrap(); + pmmr.prune(9).unwrap(); + } + + // compact some more + backend + .check_compact(9, &Bitmap::create(), &prune_noop) + .unwrap(); + } + + // recheck stored data + { + // recreate backend + let backend = + store::pmmr::PMMRBackend::::new(data_dir.to_string(), true, None) + .unwrap(); + + // 0010012001001230 + + assert_eq!(backend.data_size(), 13); + assert_eq!(backend.hash_size(), 27); + + // check we can read a hash by pos correctly from recreated backend + // get_hash() and get_from_file() should return the same value + // and we only store leaves in the leaf_set so pos 7 still has a hash in there + assert_eq!(backend.get_hash(7), Some(pos_7_hash)); + assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); assert_eq!(backend.get_hash(11), Some(pos_11_hash)); assert_eq!(backend.get_data(11), Some(pos_11)); assert_eq!(backend.get_from_file(11), Some(pos_11_hash)); } - - // compact - backend - .check_compact(4, &Bitmap::of(&vec![1, 2]), &prune_noop) - .unwrap(); - backend.sync().unwrap(); - - // check we can read a hash by pos correctly after compaction - { - assert_eq!(backend.get_hash(1), None); - assert_eq!(backend.get_from_file(1), Some(pos_1_hash)); - - assert_eq!(backend.get_hash(2), None); - assert_eq!(backend.get_from_file(2), Some(pos_2_hash)); - - assert_eq!(backend.get_hash(3), Some(pos_3_hash)); - - assert_eq!(backend.get_hash(4), None); - assert_eq!(backend.get_hash(5), None); - assert_eq!(backend.get_hash(6), Some(pos_6_hash)); - - assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); - - assert_eq!(backend.get_hash(8), Some(pos_8_hash)); - assert_eq!(backend.get_from_file(8), Some(pos_8_hash)); - } - } - - // recheck stored data - { - // recreate backend - let backend = - store::pmmr::PMMRBackend::::new(data_dir.to_string(), true, None).unwrap(); - - assert_eq!(backend.data_size(), 19); - assert_eq!(backend.hash_size(), 35); - - // check we can read a hash by pos correctly from recreated backend - assert_eq!(backend.get_hash(7), Some(pos_7_hash)); - assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); - - assert_eq!(backend.get_hash(8), Some(pos_8_hash)); - assert_eq!(backend.get_from_file(8), Some(pos_8_hash)); - } - - { - let mut backend = - store::pmmr::PMMRBackend::::new(data_dir.to_string(), true, None).unwrap(); - - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - - pmmr.prune(8).unwrap(); - pmmr.prune(9).unwrap(); - } - - // compact some more - backend - .check_compact(9, &Bitmap::create(), &prune_noop) - .unwrap(); - } - - // recheck stored data - { - // recreate backend - let backend = - store::pmmr::PMMRBackend::::new(data_dir.to_string(), true, None).unwrap(); - - // 0010012001001230 - - assert_eq!(backend.data_size(), 13); - assert_eq!(backend.hash_size(), 27); - - // check we can read a hash by pos correctly from recreated backend - // get_hash() and get_from_file() should return the same value - // and we only store leaves in the leaf_set so pos 7 still has a hash in there - assert_eq!(backend.get_hash(7), Some(pos_7_hash)); - assert_eq!(backend.get_from_file(7), Some(pos_7_hash)); - - assert_eq!(backend.get_hash(11), Some(pos_11_hash)); - assert_eq!(backend.get_data(11), Some(pos_11)); - assert_eq!(backend.get_from_file(11), Some(pos_11_hash)); } teardown(data_dir); @@ -645,72 +680,75 @@ fn compact_twice() { let (data_dir, elems) = setup("compact_twice"); // setup the mmr store with all elements - let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); - let mmr_size = load(0, &elems[..], &mut backend); - backend.sync().unwrap(); - - // save the root - let root = { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.root() - }; - - // pruning some choice nodes + // Scoped to allow Windows to teardown { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(1).unwrap(); - pmmr.prune(2).unwrap(); - pmmr.prune(4).unwrap(); - } - backend.sync().unwrap(); + let mut backend = store::pmmr::PMMRBackend::new(data_dir.to_string(), true, None).unwrap(); + let mmr_size = load(0, &elems[..], &mut backend); + backend.sync().unwrap(); - // check the root and stored data - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); - assert_eq!(pmmr.get_data(5).unwrap(), TestElem(4)); - assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); - } + // save the root + let root = { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.root() + }; - // compact - backend - .check_compact(2, &Bitmap::create(), &prune_noop) - .unwrap(); + // pruning some choice nodes + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(1).unwrap(); + pmmr.prune(2).unwrap(); + pmmr.prune(4).unwrap(); + } + backend.sync().unwrap(); - // recheck the root and stored data - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); - assert_eq!(pmmr.get_data(5).unwrap(), TestElem(4)); - assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); - } + // check the root and stored data + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(root, pmmr.root()); + assert_eq!(pmmr.get_data(5).unwrap(), TestElem(4)); + assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); + } - // now prune some more nodes - { - let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.prune(5).unwrap(); - pmmr.prune(8).unwrap(); - pmmr.prune(9).unwrap(); - } - backend.sync().unwrap(); + // compact + backend + .check_compact(2, &Bitmap::create(), &prune_noop) + .unwrap(); - // recheck the root and stored data - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); - assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); - } + // recheck the root and stored data + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(root, pmmr.root()); + assert_eq!(pmmr.get_data(5).unwrap(), TestElem(4)); + assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); + } - // compact - backend - .check_compact(2, &Bitmap::create(), &prune_noop) - .unwrap(); + // now prune some more nodes + { + let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + pmmr.prune(5).unwrap(); + pmmr.prune(8).unwrap(); + pmmr.prune(9).unwrap(); + } + backend.sync().unwrap(); - // recheck the root and stored data - { - let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); - assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); + // recheck the root and stored data + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(root, pmmr.root()); + assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); + } + + // compact + backend + .check_compact(2, &Bitmap::create(), &prune_noop) + .unwrap(); + + // recheck the root and stored data + { + let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); + assert_eq!(root, pmmr.root()); + assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); + } } teardown(data_dir); diff --git a/util/src/zip.rs b/util/src/zip.rs index 1f31aec89..52531bd59 100644 --- a/util/src/zip.rs +++ b/util/src/zip.rs @@ -80,7 +80,15 @@ where fs::create_dir_all(&p)?; } } - let mut outfile = fs::File::create(&file_path)?; + //let mut outfile = fs::File::create(&file_path)?; + let res = fs::File::create(&file_path); + let mut outfile = match res { + Err(e) => { + error!("{:?}", e); + return Err(zip::result::ZipError::Io(e)); + } + Ok(r) => r, + }; io::copy(&mut file, &mut outfile)?; } diff --git a/wallet/src/test_framework/testclient.rs b/wallet/src/test_framework/testclient.rs index 5e34a2d39..e99b6055a 100644 --- a/wallet/src/test_framework/testclient.rs +++ b/wallet/src/test_framework/testclient.rs @@ -137,6 +137,10 @@ where self.wallets.insert(addr.to_owned(), (tx, wallet)); } + pub fn stop(&mut self) { + self.running.store(false, Ordering::Relaxed); + } + /// Run the incoming message queue and respond more or less /// synchronously pub fn run(&mut self) -> Result<(), libwallet::Error> { diff --git a/wallet/tests/restore.rs b/wallet/tests/restore.rs index 05731bf7e..c16d47ba3 100644 --- a/wallet/tests/restore.rs +++ b/wallet/tests/restore.rs @@ -26,6 +26,7 @@ use grin_keychain as keychain; use grin_util as util; use grin_wallet as wallet; use std::fs; +use std::sync::atomic::Ordering; use std::thread; use std::time::Duration; @@ -54,6 +55,7 @@ fn restore_wallet(base_dir: &str, wallet_dir: &str) -> Result<(), libwallet::Err wallet_proxy.add_wallet(wallet_dir, client.get_send_instance(), wallet.clone()); // Set the wallet proxy listener running + let wp_running = wallet_proxy.running.clone(); thread::spawn(move || { if let Err(e) = wallet_proxy.run() { error!("Wallet Proxy error: {}", e); @@ -67,6 +69,9 @@ fn restore_wallet(base_dir: &str, wallet_dir: &str) -> Result<(), libwallet::Err Ok(()) })?; + wp_running.store(false, Ordering::Relaxed); + //thread::sleep(Duration::from_millis(1000)); + Ok(()) } @@ -108,6 +113,7 @@ fn compare_wallet_restore( } // Set the wallet proxy listener running + let wp_running = wallet_proxy.running.clone(); thread::spawn(move || { if let Err(e) = wallet_proxy.run() { error!("Wallet Proxy error: {}", e); @@ -164,6 +170,9 @@ fn compare_wallet_restore( dest_accts.as_ref().unwrap().len() ); + wp_running.store(false, Ordering::Relaxed); + //thread::sleep(Duration::from_millis(1000)); + Ok(()) } @@ -208,6 +217,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { wallet_proxy.add_wallet("wallet3", client3.get_send_instance(), wallet3.clone()); // Set the wallet proxy listener running + let wp_running = wallet_proxy.running.clone(); thread::spawn(move || { if let Err(e) = wallet_proxy.run() { error!("Wallet Proxy error: {}", e); @@ -327,17 +337,19 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { Ok(()) })?; + wp_running.store(false, Ordering::Relaxed); + Ok(()) } fn perform_restore(test_dir: &str) -> Result<(), libwallet::Error> { - restore_wallet(test_dir, "wallet1")?; + restore_wallet(&format!("{}_r1", test_dir), "wallet1")?; compare_wallet_restore( test_dir, "wallet1", &ExtKeychain::derive_key_id(2, 0, 0, 0, 0), )?; - restore_wallet(test_dir, "wallet2")?; + restore_wallet(&format!("{}_r2", test_dir), "wallet2")?; compare_wallet_restore( test_dir, "wallet2", @@ -353,7 +365,7 @@ fn perform_restore(test_dir: &str) -> Result<(), libwallet::Error> { "wallet2", &ExtKeychain::derive_key_id(2, 2, 0, 0, 0), )?; - restore_wallet(test_dir, "wallet3")?; + restore_wallet(&format!("{}_r3", test_dir), "wallet3")?; compare_wallet_restore( test_dir, "wallet3", From 200f87b8bcf111a64bba43c7b3c0fde4522ab786 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Sun, 10 Feb 2019 12:55:35 +0000 Subject: [PATCH 02/28] Windows TUI Fix (#2555) * switch pancurses backend to win32 * revert changes to restore test --- Cargo.lock | 1 + Cargo.toml | 3 +++ wallet/tests/restore.rs | 7 ++++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68d4a9f42..b0d760be8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -759,6 +759,7 @@ dependencies = [ "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "linefeed 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pancurses 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 4bfd7d810..f1a0769a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,9 @@ grin_wallet = { path = "./wallet", version = "1.0.1" } [target.'cfg(windows)'.dependencies] cursive = { version = "0.10.0", default-features = false, features = ["pancurses-backend"] } +[target.'cfg(windows)'.dependencies.pancurses] +version = "0.16.0" +features = ["win32"] [target.'cfg(unix)'.dependencies] cursive = "0.9.0" diff --git a/wallet/tests/restore.rs b/wallet/tests/restore.rs index c16d47ba3..9f15a72bd 100644 --- a/wallet/tests/restore.rs +++ b/wallet/tests/restore.rs @@ -45,6 +45,7 @@ fn restore_wallet(base_dir: &str, wallet_dir: &str) -> Result<(), libwallet::Err let dest_dir = format!("{}/{}_restore", base_dir, wallet_dir); fs::create_dir_all(dest_dir.clone())?; let dest_seed = format!("{}/wallet.seed", dest_dir); + println!("Source: {}, Dest: {}", source_seed, dest_seed); fs::copy(source_seed, dest_seed)?; let mut wallet_proxy: WalletProxy = WalletProxy::new(base_dir); @@ -343,13 +344,13 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { } fn perform_restore(test_dir: &str) -> Result<(), libwallet::Error> { - restore_wallet(&format!("{}_r1", test_dir), "wallet1")?; + restore_wallet(test_dir, "wallet1")?; compare_wallet_restore( test_dir, "wallet1", &ExtKeychain::derive_key_id(2, 0, 0, 0, 0), )?; - restore_wallet(&format!("{}_r2", test_dir), "wallet2")?; + restore_wallet(test_dir, "wallet2")?; compare_wallet_restore( test_dir, "wallet2", @@ -365,7 +366,7 @@ fn perform_restore(test_dir: &str) -> Result<(), libwallet::Error> { "wallet2", &ExtKeychain::derive_key_id(2, 2, 0, 0, 0), )?; - restore_wallet(&format!("{}_r3", test_dir), "wallet3")?; + restore_wallet(test_dir, "wallet3")?; compare_wallet_restore( test_dir, "wallet3", From 3b74a9ba3f77fd0e20234614b16040d9bfccbae7 Mon Sep 17 00:00:00 2001 From: Mark Renten <42224876+rentenmark@users.noreply.github.com> Date: Mon, 11 Feb 2019 13:54:21 -0500 Subject: [PATCH 03/28] Add content disposition for OK responses (#2545) --- api/src/handlers/chain_api.rs | 4 ++-- api/src/handlers/peers_api.rs | 2 +- wallet/src/controller.rs | 23 +++++++++++++++++------ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/api/src/handlers/chain_api.rs b/api/src/handlers/chain_api.rs index 910838671..af269d71f 100644 --- a/api/src/handlers/chain_api.rs +++ b/api/src/handlers/chain_api.rs @@ -56,7 +56,7 @@ pub struct ChainValidationHandler { impl Handler for ChainValidationHandler { fn get(&self, _req: Request) -> ResponseFuture { match w(&self.chain).validate(true) { - Ok(_) => response(StatusCode::OK, ""), + Ok(_) => response(StatusCode::OK, "{}"), Err(e) => response( StatusCode::INTERNAL_SERVER_ERROR, format!("validate failed: {}", e), @@ -75,7 +75,7 @@ pub struct ChainCompactHandler { impl Handler for ChainCompactHandler { fn post(&self, _req: Request) -> ResponseFuture { match w(&self.chain).compact() { - Ok(_) => response(StatusCode::OK, ""), + Ok(_) => response(StatusCode::OK, "{}"), Err(e) => response( StatusCode::INTERNAL_SERVER_ERROR, format!("compact failed: {}", e), diff --git a/api/src/handlers/peers_api.rs b/api/src/handlers/peers_api.rs index b42a92f1b..31494a17c 100644 --- a/api/src/handlers/peers_api.rs +++ b/api/src/handlers/peers_api.rs @@ -97,6 +97,6 @@ impl Handler for PeerHandler { _ => return response(StatusCode::BAD_REQUEST, "invalid command"), }; - response(StatusCode::OK, "") + response(StatusCode::OK, "{}") } } diff --git a/wallet/src/controller.rs b/wallet/src/controller.rs index 9bd584932..1bbf1a268 100644 --- a/wallet/src/controller.rs +++ b/wallet/src/controller.rs @@ -487,11 +487,11 @@ where ), "cancel_tx" => Box::new( self.cancel_tx(req, api) - .and_then(|_| ok(response(StatusCode::OK, ""))), + .and_then(|_| ok(response(StatusCode::OK, "{}"))), ), "post_tx" => Box::new( self.post_tx(req, api) - .and_then(|_| ok(response(StatusCode::OK, ""))), + .and_then(|_| ok(response(StatusCode::OK, "{}"))), ), _ => Box::new(err(ErrorKind::GenericError( "Unknown error handling post request".to_owned(), @@ -677,20 +677,31 @@ fn create_ok_response(json: &str) -> Response { "access-control-allow-headers", "Content-Type, Authorization", ) + .header(hyper::header::CONTENT_TYPE, "application/json") .body(json.to_string().into()) .unwrap() } +/// Build a new hyper Response with the status code and body provided. +/// +/// Whenever the status code is `StatusCode::OK` the text parameter should be +/// valid JSON as the content type header will be set to `application/json' fn response>(status: StatusCode, text: T) -> Response { - Response::builder() + let mut builder = &mut Response::builder(); + + builder = builder .status(status) .header("access-control-allow-origin", "*") .header( "access-control-allow-headers", "Content-Type, Authorization", - ) - .body(text.into()) - .unwrap() + ); + + if status == StatusCode::OK { + builder = builder.header(hyper::header::CONTENT_TYPE, "application/json"); + } + + builder.body(text.into()).unwrap() } fn parse_params(req: &Request) -> HashMap> { From 5987bcde196fad78ebf956099339aa23852e2086 Mon Sep 17 00:00:00 2001 From: Gary Yu Date: Tue, 12 Feb 2019 21:39:43 +0800 Subject: [PATCH 04/28] add repost method into wallet owner api (#2553) * add repost method into wallet owner api * rustfmt --- doc/api/wallet_owner_api.md | 45 +++++++++++++++++++ wallet/src/controller.rs | 86 +++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/doc/api/wallet_owner_api.md b/doc/api/wallet_owner_api.md index ab0d92b07..70562de08 100644 --- a/doc/api/wallet_owner_api.md +++ b/doc/api/wallet_owner_api.md @@ -12,6 +12,7 @@ 1. [POST Finalize Tx](#post-finalize-tx) 1. [POST Cancel Tx](#post-cancel-tx) 1. [POST Post Tx](#post-post-tx) + 1. [POST Repost Tx](#post-repost-tx) 1. [POST Issue Burn Tx](#post-issue-burn-tx) 1. [Adding Foreign API Endpoints](#add-foreign-api-endpoints) @@ -641,6 +642,50 @@ Push new transaction to the connected node transaction pool. Add `?fluff` at the }, }); ``` +### POST Repost Tx + +Repost a `sending` transaction to the connected node transaction pool with a given transaction id. Add `?fluff` at the end of the URL to bypass Dandelion relay . This could be used for retry posting when a `sending` transaction is created but somehow failed on posting. + +* **URL** + + * /v1/wallet/owner/repost?id=x + * /v1/wallet/owner/repost?tx_id=x + * /v1/wallet/owner/repost?fluff&tx_id=x + +* **Method:** + + `POST` + +* **URL Params** + + **Required:** + * `id=[number]` the transaction id + * `tx_id=[string]`the transaction slate id + +* **Data Params** + + None + +* **Success Response:** + + * **Code:** 200 + +* **Error Response:** + + * **Code:** 400 + +* **Sample Call:** + + ```javascript + $.ajax({ + url: "/v1/wallet/owner/repost?id=3", + dataType: "json", + type : "POST", + success : function(r) { + console.log(r); + } + }); + ``` ### POST Issue Burn Tx diff --git a/wallet/src/controller.rs b/wallet/src/controller.rs index 1bbf1a268..94cb82614 100644 --- a/wallet/src/controller.rs +++ b/wallet/src/controller.rs @@ -40,6 +40,7 @@ use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::Arc; use url::form_urlencoded; +use uuid::Uuid; /// Instantiate wallet Owner API for a single-use (command line) call /// Return a function containing a loaded API context to call @@ -467,6 +468,87 @@ where )) } + pub fn repost( + &self, + req: Request, + api: APIOwner, + ) -> Box + Send> { + let params = parse_params(&req); + let mut id_int: Option = None; + let mut tx_uuid: Option = None; + + if let Some(id_string) = params.get("id") { + match id_string[0].parse() { + Ok(id) => id_int = Some(id), + Err(e) => { + error!("repost: could not parse id: {}", e); + return Box::new(err(ErrorKind::GenericError( + "repost: cannot repost transaction. Could not parse id in request." + .to_owned(), + ) + .into())); + } + } + } else if let Some(tx_id_string) = params.get("tx_id") { + match tx_id_string[0].parse() { + Ok(tx_id) => tx_uuid = Some(tx_id), + Err(e) => { + error!("repost: could not parse tx_id: {}", e); + return Box::new(err(ErrorKind::GenericError( + "repost: cannot repost transaction. Could not parse tx_id in request." + .to_owned(), + ) + .into())); + } + } + } else { + return Box::new(err(ErrorKind::GenericError( + "repost: Cannot repost transaction. Missing id or tx_id param in request." + .to_owned(), + ) + .into())); + } + + let res = api.retrieve_txs(true, id_int, tx_uuid); + if let Err(e) = res { + return Box::new(err(ErrorKind::GenericError(format!( + "repost: cannot repost transaction. retrieve_txs failed, err: {:?}", + e + )) + .into())); + } + let (_, txs) = res.unwrap(); + let res = api.get_stored_tx(&txs[0]); + if let Err(e) = res { + return Box::new(err(ErrorKind::GenericError(format!( + "repost: cannot repost transaction. get_stored_tx failed, err: {:?}", + e + )) + .into())); + } + let stored_tx = res.unwrap(); + if stored_tx.is_none() { + error!( + "Transaction with id {:?}/{:?} does not have transaction data. Not reposting.", + id_int, tx_uuid, + ); + return Box::new(err(ErrorKind::GenericError( + "repost: Cannot repost transaction. Missing id or tx_id param in request." + .to_owned(), + ) + .into())); + } + + let fluff = params.get("fluff").is_some(); + Box::new(match api.post_tx(&stored_tx.unwrap(), fluff) { + Ok(_) => ok(()), + Err(e) => { + error!("repost: failed with error: {}", e); + err(e) + } + }) + } + fn handle_post_request(&self, req: Request) -> WalletResponseFuture { let api = APIOwner::new(self.wallet.clone()); match req @@ -493,6 +575,10 @@ where self.post_tx(req, api) .and_then(|_| ok(response(StatusCode::OK, "{}"))), ), + "repost" => Box::new( + self.repost(req, api) + .and_then(|_| ok(response(StatusCode::OK, ""))), + ), _ => Box::new(err(ErrorKind::GenericError( "Unknown error handling post request".to_owned(), ) From 1d0c04cf0b2bbf03bdb8c593970c561bdfa74dba Mon Sep 17 00:00:00 2001 From: Ivan Sorokin Date: Tue, 12 Feb 2019 14:45:43 +0100 Subject: [PATCH 05/28] Add ability to compare selection strategies (#2516) Before tx creation user can estimate fee and locked amount with different selection strategies by providing `-e` flag for `wallet send` command. --- src/bin/cmd/wallet_args.rs | 22 +++- src/bin/grin.yml | 4 + wallet/src/command.rs | 132 ++++++++++++--------- wallet/src/display.rs | 43 +++++++ wallet/src/libwallet/api.rs | 68 +++++++++++ wallet/src/libwallet/internal/selection.rs | 57 +++++++-- wallet/src/libwallet/internal/tx.rs | 46 +++++++ wallet/tests/transaction.rs | 27 +++++ 8 files changed, 331 insertions(+), 68 deletions(-) diff --git a/src/bin/cmd/wallet_args.rs b/src/bin/cmd/wallet_args.rs index 80197deae..4ae2f19d2 100644 --- a/src/bin/cmd/wallet_args.rs +++ b/src/bin/cmd/wallet_args.rs @@ -349,6 +349,9 @@ pub fn parse_send_args(args: &ArgMatches) -> Result Result "default", } } else { - parse_required(args, "dest")? + if !estimate_selection_strategies { + parse_required(args, "dest")? + } else { + "" + } } }; - if method == "http" && !dest.starts_with("http://") && !dest.starts_with("https://") { + if !estimate_selection_strategies + && method == "http" + && !dest.starts_with("http://") + && !dest.starts_with("https://") + { let msg = format!( "HTTP Destination should start with http://: or https://: {}", dest, @@ -386,6 +397,7 @@ pub fn parse_send_args(args: &ArgMatches) -> Result { let a = arg_parse!(parse_send_args(&args)); - command::send(inst_wallet(), a) + command::send( + inst_wallet(), + a, + wallet_config.dark_background_color_scheme.unwrap_or(true), + ) } ("receive", Some(args)) => { let a = arg_parse!(parse_receive_args(&args)); diff --git a/src/bin/grin.yml b/src/bin/grin.yml index c64b665bf..94a18e0a1 100644 --- a/src/bin/grin.yml +++ b/src/bin/grin.yml @@ -157,6 +157,10 @@ subcommands: - smallest default_value: all takes_value: true + - estimate_selection_strategies: + help: Estimates all possible Coin/Output selection strategies. + short: e + long: estimate-selection - change_outputs: help: Number of change outputs to generate (mainly for testing) short: o diff --git a/wallet/src/command.rs b/wallet/src/command.rs index 35e51959f..593a042e8 100644 --- a/wallet/src/command.rs +++ b/wallet/src/command.rs @@ -200,6 +200,7 @@ pub struct SendArgs { pub message: Option, pub minimum_confirmations: u64, pub selection_strategy: String, + pub estimate_selection_strategies: bool, pub method: String, pub dest: String, pub change_outputs: usize, @@ -210,68 +211,89 @@ pub struct SendArgs { pub fn send( wallet: Arc>>, args: SendArgs, + dark_scheme: bool, ) -> Result<(), Error> { controller::owner_single_use(wallet.clone(), |api| { - let result = api.initiate_tx( - None, - args.amount, - args.minimum_confirmations, - args.max_outputs, - args.change_outputs, - args.selection_strategy == "all", - args.message.clone(), - ); - let (mut slate, lock_fn) = match result { - Ok(s) => { - info!( - "Tx created: {} grin to {} (strategy '{}')", - core::amount_to_hr_string(args.amount, false), - args.dest, - args.selection_strategy, - ); - s - } - Err(e) => { - info!("Tx not created: {}", e); - return Err(e); - } - }; - let adapter = match args.method.as_str() { - "http" => HTTPWalletCommAdapter::new(), - "file" => FileWalletCommAdapter::new(), - "keybase" => KeybaseWalletCommAdapter::new(), - "self" => NullWalletCommAdapter::new(), - _ => NullWalletCommAdapter::new(), - }; - if adapter.supports_sync() { - slate = adapter.send_tx_sync(&args.dest, &slate)?; - api.tx_lock_outputs(&slate, lock_fn)?; - if args.method == "self" { - controller::foreign_single_use(wallet, |api| { - api.receive_tx(&mut slate, Some(&args.dest), None)?; - Ok(()) - })?; - } - if let Err(e) = api.verify_slate_messages(&slate) { - error!("Error validating participant messages: {}", e); - return Err(e); - } - api.finalize_tx(&mut slate)?; + if args.estimate_selection_strategies { + let strategies = vec!["smallest", "all"] + .into_iter() + .map(|strategy| { + let (total, fee) = api + .estimate_initiate_tx( + None, + args.amount, + args.minimum_confirmations, + args.max_outputs, + args.change_outputs, + strategy == "all", + ) + .unwrap(); + (strategy, total, fee) + }) + .collect(); + display::estimate(args.amount, strategies, dark_scheme); } else { - adapter.send_tx_async(&args.dest, &slate)?; - api.tx_lock_outputs(&slate, lock_fn)?; - } - if adapter.supports_sync() { - let result = api.post_tx(&slate.tx, args.fluff); - match result { - Ok(_) => { - info!("Tx sent ok",); - return Ok(()); + let result = api.initiate_tx( + None, + args.amount, + args.minimum_confirmations, + args.max_outputs, + args.change_outputs, + args.selection_strategy == "all", + args.message.clone(), + ); + let (mut slate, lock_fn) = match result { + Ok(s) => { + info!( + "Tx created: {} grin to {} (strategy '{}')", + core::amount_to_hr_string(args.amount, false), + args.dest, + args.selection_strategy, + ); + s } Err(e) => { - error!("Tx sent fail: {}", e); + info!("Tx not created: {}", e); return Err(e); } + }; + let adapter = match args.method.as_str() { + "http" => HTTPWalletCommAdapter::new(), + "file" => FileWalletCommAdapter::new(), + "keybase" => KeybaseWalletCommAdapter::new(), + "self" => NullWalletCommAdapter::new(), + _ => NullWalletCommAdapter::new(), + }; + if adapter.supports_sync() { + slate = adapter.send_tx_sync(&args.dest, &slate)?; + api.tx_lock_outputs(&slate, lock_fn)?; + if args.method == "self" { + controller::foreign_single_use(wallet, |api| { + api.receive_tx(&mut slate, Some(&args.dest), None)?; + Ok(()) + })?; + } + if let Err(e) = api.verify_slate_messages(&slate) { + error!("Error validating participant messages: {}", e); + return Err(e); + } + api.finalize_tx(&mut slate)?; + } else { + adapter.send_tx_async(&args.dest, &slate)?; + api.tx_lock_outputs(&slate, lock_fn)?; + } + if adapter.supports_sync() { + let result = api.post_tx(&slate.tx, args.fluff); + match result { + Ok(_) => { + info!("Tx sent ok",); + return Ok(()); + } + Err(e) => { + error!("Tx sent fail: {}", e); + return Err(e); + } + } } } Ok(()) diff --git a/wallet/src/display.rs b/wallet/src/display.rs index 73d0bf2d5..041494fba 100644 --- a/wallet/src/display.rs +++ b/wallet/src/display.rs @@ -338,6 +338,49 @@ pub fn info( ); } } + +/// Display summary info in a pretty way +pub fn estimate( + amount: u64, + strategies: Vec<( + &str, // strategy + u64, // total amount to be locked + u64, // fee + )>, + dark_background_color_scheme: bool, +) { + println!( + "\nEstimation for sending {}:\n", + amount_to_hr_string(amount, false) + ); + + let mut table = table!(); + + table.set_titles(row![ + bMG->"Selection strategy", + bMG->"Fee", + bMG->"Will be locked", + ]); + + for (strategy, total, fee) in strategies { + if dark_background_color_scheme { + table.add_row(row![ + bFC->strategy, + FR->amount_to_hr_string(fee, false), + FY->amount_to_hr_string(total, false), + ]); + } else { + table.add_row(row![ + bFD->strategy, + FR->amount_to_hr_string(fee, false), + FY->amount_to_hr_string(total, false), + ]); + } + } + table.printstd(); + println!(); +} + /// Display list of wallet accounts in a pretty way pub fn accounts(acct_mappings: Vec) { println!("\n____ Wallet Accounts ____\n",); diff --git a/wallet/src/libwallet/api.rs b/wallet/src/libwallet/api.rs index 5302e1f19..a615f2bcf 100644 --- a/wallet/src/libwallet/api.rs +++ b/wallet/src/libwallet/api.rs @@ -671,6 +671,74 @@ where Ok((slate, lock_fn)) } + /// Estimates the amount to be locked and fee for the transaction without creating one + /// + /// # Arguments + /// * `src_acct_name` - The human readable account name from which to draw outputs + /// for the transaction, overriding whatever the active account is as set via the + /// [`set_active_account`](struct.APIOwner.html#method.set_active_account) method. + /// If None, the transaction will use the active account. + /// * `amount` - The amount to send, in nanogrins. (`1 G = 1_000_000_000nG`) + /// * `minimum_confirmations` - The minimum number of confirmations an output + /// should have in order to be included in the transaction. + /// * `max_outputs` - By default, the wallet selects as many inputs as possible in a + /// transaction, to reduce the Output set and the fees. The wallet will attempt to spend + /// include up to `max_outputs` in a transaction, however if this is not enough to cover + /// the whole amount, the wallet will include more outputs. This parameter should be considered + /// a soft limit. + /// * `num_change_outputs` - The target number of change outputs to create in the transaction. + /// The actual number created will be `num_change_outputs` + whatever remainder is needed. + /// * `selection_strategy_is_use_all` - If `true`, attempt to use up as many outputs as + /// possible to create the transaction, up the 'soft limit' of `max_outputs`. This helps + /// to reduce the size of the UTXO set and the amount of data stored in the wallet, and + /// minimizes fees. This will generally result in many inputs and a large change output(s), + /// usually much larger than the amount being sent. If `false`, the transaction will include + /// as many outputs as are needed to meet the amount, (and no more) starting with the smallest + /// value outputs. + /// + /// # Returns + /// * a result containing: + /// * (total, fee) - A tuple: + /// * Total amount to be locked. + /// * Transaction fee + pub fn estimate_initiate_tx( + &mut self, + src_acct_name: Option<&str>, + amount: u64, + minimum_confirmations: u64, + max_outputs: usize, + num_change_outputs: usize, + selection_strategy_is_use_all: bool, + ) -> Result< + ( + u64, // total + u64, // fee + ), + Error, + > { + let mut w = self.wallet.lock(); + w.open_with_credentials()?; + let parent_key_id = match src_acct_name { + Some(d) => { + let pm = w.get_acct_path(d.to_owned())?; + match pm { + Some(p) => p.path, + None => w.parent_key_id(), + } + } + None => w.parent_key_id(), + }; + tx::estimate_send_tx( + &mut *w, + amount, + minimum_confirmations, + max_outputs, + num_change_outputs, + selection_strategy_is_use_all, + &parent_key_id, + ) + } + /// Lock outputs associated with a given slate/transaction pub fn tx_lock_outputs( &mut self, diff --git a/wallet/src/libwallet/internal/selection.rs b/wallet/src/libwallet/internal/selection.rs index c9e4b3d27..b02cd896b 100644 --- a/wallet/src/libwallet/internal/selection.rs +++ b/wallet/src/libwallet/internal/selection.rs @@ -242,6 +242,52 @@ pub fn select_send_tx( ), Error, > +where + T: WalletBackend, + C: NodeClient, + K: Keychain, +{ + let (coins, _total, amount, fee) = select_coins_and_fee( + wallet, + amount, + current_height, + minimum_confirmations, + max_outputs, + change_outputs, + selection_strategy_is_use_all, + &parent_key_id, + )?; + + // build transaction skeleton with inputs and change + let (mut parts, change_amounts_derivations) = + inputs_and_change(&coins, wallet, amount, fee, change_outputs)?; + + // This is more proof of concept than anything but here we set lock_height + // on tx being sent (based on current chain height via api). + parts.push(build::with_lock_height(lock_height)); + + Ok((parts, coins, change_amounts_derivations, fee)) +} + +/// Select outputs and calculating fee. +pub fn select_coins_and_fee( + wallet: &mut T, + amount: u64, + current_height: u64, + minimum_confirmations: u64, + max_outputs: usize, + change_outputs: usize, + selection_strategy_is_use_all: bool, + parent_key_id: &Identifier, +) -> Result< + ( + Vec, + u64, // total + u64, // amount + u64, // fee + ), + Error, +> where T: WalletBackend, C: NodeClient, @@ -325,16 +371,7 @@ where amount_with_fee = amount + fee; } } - - // build transaction skeleton with inputs and change - let (mut parts, change_amounts_derivations) = - inputs_and_change(&coins, wallet, amount, fee, change_outputs)?; - - // This is more proof of concept than anything but here we set lock_height - // on tx being sent (based on current chain height via api). - parts.push(build::with_lock_height(lock_height)); - - Ok((parts, coins, change_amounts_derivations, fee)) + Ok((coins, total, amount, fee)) } /// Selects inputs and change for a transaction diff --git a/wallet/src/libwallet/internal/tx.rs b/wallet/src/libwallet/internal/tx.rs index 459885d4c..683a369f4 100644 --- a/wallet/src/libwallet/internal/tx.rs +++ b/wallet/src/libwallet/internal/tx.rs @@ -42,6 +42,52 @@ where Ok(slate) } +/// Estimates locked amount and fee for the transaction without creating one +pub fn estimate_send_tx( + wallet: &mut T, + amount: u64, + minimum_confirmations: u64, + max_outputs: usize, + num_change_outputs: usize, + selection_strategy_is_use_all: bool, + parent_key_id: &Identifier, +) -> Result< + ( + u64, // total + u64, // fee + ), + Error, +> +where + T: WalletBackend, + C: NodeClient, + K: Keychain, +{ + // Get lock height + let current_height = wallet.w2n_client().get_chain_height()?; + // ensure outputs we're selecting are up to date + updater::refresh_outputs(wallet, parent_key_id, false)?; + + // Sender selects outputs into a new slate and save our corresponding keys in + // a transaction context. The secret key in our transaction context will be + // randomly selected. This returns the public slate, and a closure that locks + // our inputs and outputs once we're convinced the transaction exchange went + // according to plan + // This function is just a big helper to do all of that, in theory + // this process can be split up in any way + let (_coins, total, _amount, fee) = selection::select_coins_and_fee( + wallet, + amount, + current_height, + minimum_confirmations, + max_outputs, + num_change_outputs, + selection_strategy_is_use_all, + parent_key_id, + )?; + Ok((total, fee)) +} + /// Add inputs to the slate (effectively becoming the sender) pub fn add_inputs_to_slate( wallet: &mut T, diff --git a/wallet/tests/transaction.rs b/wallet/tests/transaction.rs index 3d0302646..ac22461f7 100644 --- a/wallet/tests/transaction.rs +++ b/wallet/tests/transaction.rs @@ -226,6 +226,33 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { Ok(()) })?; + // Estimate fee and locked amount for a transaction + wallet::controller::owner_single_use(wallet1.clone(), |sender_api| { + let (total, fee) = sender_api.estimate_initiate_tx( + None, + amount * 2, // amount + 2, // minimum confirmations + 500, // max outputs + 1, // num change outputs + true, // select all outputs + )?; + assert_eq!(total, 600_000_000_000); + assert_eq!(fee, 4_000_000); + + let (total, fee) = sender_api.estimate_initiate_tx( + None, + amount * 2, // amount + 2, // minimum confirmations + 500, // max outputs + 1, // num change outputs + false, // select the smallest amount of outputs + )?; + assert_eq!(total, 180_000_000_000); + assert_eq!(fee, 6_000_000); + + Ok(()) + })?; + // Send another transaction, but don't post to chain immediately and use // the stored transaction instead wallet::controller::owner_single_use(wallet1.clone(), |sender_api| { From aa4f44b79abefd50e1959e17e900e6fe3d996c93 Mon Sep 17 00:00:00 2001 From: Ivan Sorokin Date: Wed, 13 Feb 2019 00:06:25 +0100 Subject: [PATCH 06/28] fix: wallet coin selection respects max_block_weight (#2546) * fix #2510: wallet coin selection respects max_block_weight Deprecate "soft" max_outputs limit and introduce "hard" max_outputs limit based on max_block_weight. * Fix tests --- servers/tests/framework.rs | 2 - servers/tests/simulnet.rs | 1 - src/bin/cmd/wallet_args.rs | 4 -- wallet/src/command.rs | 3 -- wallet/src/controller.rs | 1 - wallet/src/libwallet/api.rs | 19 +------- wallet/src/libwallet/internal/selection.rs | 51 ++++++++-------------- wallet/src/libwallet/internal/tx.rs | 4 -- wallet/src/libwallet/types.rs | 2 - wallet/src/test_framework/mod.rs | 1 - wallet/tests/accounts.rs | 1 - wallet/tests/check.rs | 1 - wallet/tests/file.rs | 1 - wallet/tests/repost.rs | 2 - wallet/tests/restore.rs | 4 -- wallet/tests/self_send.rs | 1 - wallet/tests/transaction.rs | 23 +++++++--- 17 files changed, 39 insertions(+), 82 deletions(-) diff --git a/servers/tests/framework.rs b/servers/tests/framework.rs index 6ae39835e..d0bc36d71 100644 --- a/servers/tests/framework.rs +++ b/servers/tests/framework.rs @@ -378,7 +378,6 @@ impl LocalServerContainer { let client_n = HTTPNodeClient::new(&config.check_node_api_http_addr, None); let client_w = HTTPWalletCommAdapter::new(); - let max_outputs = 500; let change_outputs = 1; let mut wallet = LMDBBackend::new(config.clone(), "", client_n) @@ -389,7 +388,6 @@ impl LocalServerContainer { None, amount, minimum_confirmations, - max_outputs, change_outputs, selection_strategy == "all", None, diff --git a/servers/tests/simulnet.rs b/servers/tests/simulnet.rs index 214549c34..424ab0f02 100644 --- a/servers/tests/simulnet.rs +++ b/servers/tests/simulnet.rs @@ -963,7 +963,6 @@ fn replicate_tx_fluff_failure() { let (mut slate, lock_fn) = api.initiate_tx( None, amount, // amount 2, // minimum confirmations - 500, // max outputs 1000, // num change outputs true, // select all outputs None, diff --git a/src/bin/cmd/wallet_args.rs b/src/bin/cmd/wallet_args.rs index 4ae2f19d2..c6fe2b492 100644 --- a/src/bin/cmd/wallet_args.rs +++ b/src/bin/cmd/wallet_args.rs @@ -389,9 +389,6 @@ pub fn parse_send_args(args: &ArgMatches) -> Result Result, amount: u64, minimum_confirmations: u64, - max_outputs: usize, num_change_outputs: usize, selection_strategy_is_use_all: bool, message: Option, @@ -651,7 +644,6 @@ where &mut *w, &mut slate, minimum_confirmations, - max_outputs, num_change_outputs, selection_strategy_is_use_all, &parent_key_id, @@ -681,15 +673,10 @@ where /// * `amount` - The amount to send, in nanogrins. (`1 G = 1_000_000_000nG`) /// * `minimum_confirmations` - The minimum number of confirmations an output /// should have in order to be included in the transaction. - /// * `max_outputs` - By default, the wallet selects as many inputs as possible in a - /// transaction, to reduce the Output set and the fees. The wallet will attempt to spend - /// include up to `max_outputs` in a transaction, however if this is not enough to cover - /// the whole amount, the wallet will include more outputs. This parameter should be considered - /// a soft limit. /// * `num_change_outputs` - The target number of change outputs to create in the transaction. /// The actual number created will be `num_change_outputs` + whatever remainder is needed. /// * `selection_strategy_is_use_all` - If `true`, attempt to use up as many outputs as - /// possible to create the transaction, up the 'soft limit' of `max_outputs`. This helps + /// possible to estimate the transaction. This helps /// to reduce the size of the UTXO set and the amount of data stored in the wallet, and /// minimizes fees. This will generally result in many inputs and a large change output(s), /// usually much larger than the amount being sent. If `false`, the transaction will include @@ -706,7 +693,6 @@ where src_acct_name: Option<&str>, amount: u64, minimum_confirmations: u64, - max_outputs: usize, num_change_outputs: usize, selection_strategy_is_use_all: bool, ) -> Result< @@ -732,7 +718,6 @@ where &mut *w, amount, minimum_confirmations, - max_outputs, num_change_outputs, selection_strategy_is_use_all, &parent_key_id, diff --git a/wallet/src/libwallet/internal/selection.rs b/wallet/src/libwallet/internal/selection.rs index b02cd896b..ab76c9443 100644 --- a/wallet/src/libwallet/internal/selection.rs +++ b/wallet/src/libwallet/internal/selection.rs @@ -16,11 +16,13 @@ use crate::core::core::{amount_to_hr_string, Transaction}; use crate::core::libtx::{build, tx_fee}; +use crate::core::{consensus, global}; use crate::keychain::{Identifier, Keychain}; use crate::libwallet::error::{Error, ErrorKind}; use crate::libwallet::internal::keys; use crate::libwallet::slate::Slate; use crate::libwallet::types::*; +use std::cmp::min; use std::collections::HashMap; use std::marker::PhantomData; @@ -33,7 +35,6 @@ pub fn build_send_tx( wallet: &mut T, slate: &mut Slate, minimum_confirmations: u64, - max_outputs: usize, change_outputs: usize, selection_strategy_is_use_all: bool, parent_key_id: Identifier, @@ -49,7 +50,6 @@ where slate.height, minimum_confirmations, slate.lock_height, - max_outputs, change_outputs, selection_strategy_is_use_all, &parent_key_id, @@ -220,6 +220,16 @@ where Ok((key_id, context, Box::new(wallet_add_fn))) } +/// Calculate maximal amount of inputs in transaction given amount of outputs +fn calculate_max_inputs_in_block(num_outputs: usize) -> usize { + let coinbase_weight = consensus::BLOCK_OUTPUT_WEIGHT + consensus::BLOCK_KERNEL_WEIGHT; + global::max_block_weight().saturating_sub( + coinbase_weight + + consensus::BLOCK_OUTPUT_WEIGHT.saturating_mul(num_outputs) + + consensus::BLOCK_KERNEL_WEIGHT, + ) / consensus::BLOCK_INPUT_WEIGHT +} + /// Builds a transaction to send to someone from the HD seed associated with the /// wallet and the amount to send. Handles reading through the wallet data file, /// selecting outputs to spend and building the change. @@ -229,7 +239,6 @@ pub fn select_send_tx( current_height: u64, minimum_confirmations: u64, lock_height: u64, - max_outputs: usize, change_outputs: usize, selection_strategy_is_use_all: bool, parent_key_id: &Identifier, @@ -252,7 +261,6 @@ where amount, current_height, minimum_confirmations, - max_outputs, change_outputs, selection_strategy_is_use_all, &parent_key_id, @@ -275,7 +283,6 @@ pub fn select_coins_and_fee( amount: u64, current_height: u64, minimum_confirmations: u64, - max_outputs: usize, change_outputs: usize, selection_strategy_is_use_all: bool, parent_key_id: &Identifier, @@ -299,7 +306,7 @@ where amount, current_height, minimum_confirmations, - max_outputs, + calculate_max_inputs_in_block(change_outputs), selection_strategy_is_use_all, parent_key_id, ); @@ -361,7 +368,7 @@ where amount_with_fee, current_height, minimum_confirmations, - max_outputs, + calculate_max_inputs_in_block(num_outputs), selection_strategy_is_use_all, parent_key_id, ) @@ -476,40 +483,20 @@ where }) .collect::>(); - let max_available = eligible.len(); + // max_available can not be bigger than max_outputs + let max_available = min(eligible.len(), max_outputs); // sort eligible outputs by increasing value eligible.sort_by_key(|out| out.value); // use a sliding window to identify potential sets of possible outputs to spend - // Case of amount > total amount of max_outputs(500): - // The limit exists because by default, we always select as many inputs as - // possible in a transaction, to reduce both the Output set and the fees. - // But that only makes sense up to a point, hence the limit to avoid being too - // greedy. But if max_outputs(500) is actually not enough to cover the whole - // amount, the wallet should allow going over it to satisfy what the user - // wants to send. So the wallet considers max_outputs more of a soft limit. - if eligible.len() > max_outputs { - for window in eligible.windows(max_outputs) { + if max_available > 0 { + for window in eligible.windows(max_available) { let windowed_eligibles = window.iter().cloned().collect::>(); if let Some(outputs) = select_from(amount, select_all, windowed_eligibles) { return (max_available, outputs); } } - // Not exist in any window of which total amount >= amount. - // Then take coins from the smallest one up to the total amount of selected - // coins = the amount. - if let Some(outputs) = select_from(amount, false, eligible.clone()) { - debug!( - "Extending maximum number of outputs. {} outputs selected.", - outputs.len() - ); - return (max_available, outputs); - } - } else { - if let Some(outputs) = select_from(amount, select_all, eligible.clone()) { - return (max_available, outputs); - } } // we failed to find a suitable set of outputs to spend, @@ -518,7 +505,7 @@ where eligible.reverse(); ( max_available, - eligible.iter().take(max_outputs).cloned().collect(), + eligible.iter().take(max_available).cloned().collect(), ) } diff --git a/wallet/src/libwallet/internal/tx.rs b/wallet/src/libwallet/internal/tx.rs index 683a369f4..6d7201089 100644 --- a/wallet/src/libwallet/internal/tx.rs +++ b/wallet/src/libwallet/internal/tx.rs @@ -47,7 +47,6 @@ pub fn estimate_send_tx( wallet: &mut T, amount: u64, minimum_confirmations: u64, - max_outputs: usize, num_change_outputs: usize, selection_strategy_is_use_all: bool, parent_key_id: &Identifier, @@ -80,7 +79,6 @@ where amount, current_height, minimum_confirmations, - max_outputs, num_change_outputs, selection_strategy_is_use_all, parent_key_id, @@ -93,7 +91,6 @@ pub fn add_inputs_to_slate( wallet: &mut T, slate: &mut Slate, minimum_confirmations: u64, - max_outputs: usize, num_change_outputs: usize, selection_strategy_is_use_all: bool, parent_key_id: &Identifier, @@ -119,7 +116,6 @@ where wallet, slate, minimum_confirmations, - max_outputs, num_change_outputs, selection_strategy_is_use_all, parent_key_id.clone(), diff --git a/wallet/src/libwallet/types.rs b/wallet/src/libwallet/types.rs index 81ef38f9c..cef7298e1 100644 --- a/wallet/src/libwallet/types.rs +++ b/wallet/src/libwallet/types.rs @@ -710,8 +710,6 @@ pub struct SendTXArgs { pub method: String, /// destination url pub dest: String, - /// Max number of outputs - pub max_outputs: usize, /// Number of change outputs to generate pub num_change_outputs: usize, /// whether to use all outputs (combine) diff --git a/wallet/src/test_framework/mod.rs b/wallet/src/test_framework/mod.rs index 029dff57b..d4ef26f8b 100644 --- a/wallet/src/test_framework/mod.rs +++ b/wallet/src/test_framework/mod.rs @@ -198,7 +198,6 @@ where None, // account amount, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, diff --git a/wallet/tests/accounts.rs b/wallet/tests/accounts.rs index 98340c0d8..1967f23a9 100644 --- a/wallet/tests/accounts.rs +++ b/wallet/tests/accounts.rs @@ -180,7 +180,6 @@ fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { let (mut slate, lock_fn) = api.initiate_tx( None, reward, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, diff --git a/wallet/tests/check.rs b/wallet/tests/check.rs index 8e46d70ca..d07470472 100644 --- a/wallet/tests/check.rs +++ b/wallet/tests/check.rs @@ -158,7 +158,6 @@ fn check_repair_impl(test_dir: &str) -> Result<(), libwallet::Error> { None, reward * 2, // amount cm, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, // optional message diff --git a/wallet/tests/file.rs b/wallet/tests/file.rs index 925f7cca4..5c51f38a1 100644 --- a/wallet/tests/file.rs +++ b/wallet/tests/file.rs @@ -105,7 +105,6 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { Some("mining"), reward * 2, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs Some(message.to_owned()), // optional message diff --git a/wallet/tests/repost.rs b/wallet/tests/repost.rs index e24cd6f62..8de394959 100644 --- a/wallet/tests/repost.rs +++ b/wallet/tests/repost.rs @@ -104,7 +104,6 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { Some("mining"), reward * 2, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, @@ -200,7 +199,6 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { None, amount * 2, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, diff --git a/wallet/tests/restore.rs b/wallet/tests/restore.rs index 9f15a72bd..7ff64f079 100644 --- a/wallet/tests/restore.rs +++ b/wallet/tests/restore.rs @@ -237,7 +237,6 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { let (slate_i, lock_fn) = sender_api.initiate_tx( None, amount, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, @@ -259,7 +258,6 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { None, amount * 2, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, @@ -281,7 +279,6 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { None, amount * 3, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, @@ -309,7 +306,6 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> { None, amount * 3, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, diff --git a/wallet/tests/self_send.rs b/wallet/tests/self_send.rs index 54cab3078..88e98eeea 100644 --- a/wallet/tests/self_send.rs +++ b/wallet/tests/self_send.rs @@ -88,7 +88,6 @@ fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> { Some("mining"), reward * 2, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, diff --git a/wallet/tests/transaction.rs b/wallet/tests/transaction.rs index ac22461f7..5031f6cd6 100644 --- a/wallet/tests/transaction.rs +++ b/wallet/tests/transaction.rs @@ -99,7 +99,6 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { let (slate_i, lock_fn) = sender_api.initiate_tx( None, amount, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, @@ -232,7 +231,6 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { None, amount * 2, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs )?; @@ -243,7 +241,6 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { None, amount * 2, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs false, // select the smallest amount of outputs )?; @@ -261,7 +258,6 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { None, amount * 2, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, @@ -312,6 +308,24 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> { Ok(()) })?; + // Initiate transaction with weight more that + // core::global::max_block_weight() should fail + let invalid_amount_of_outputs = + core::global::max_block_weight() / core::consensus::BLOCK_OUTPUT_WEIGHT + 1; + let res = wallet::controller::owner_single_use(wallet1.clone(), |sender_api| { + // note this will increment the block count as part of the transaction "posting" + sender_api.initiate_tx( + None, + amount, // amount + 2, // minimum confirmations + invalid_amount_of_outputs, // num change outputs + true, // select all outputs + None, + )?; + Ok(()) + }); + assert!(res.is_err()); + // let logging finish thread::sleep(Duration::from_millis(200)); Ok(()) @@ -358,7 +372,6 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> { let (slate_i, lock_fn) = sender_api.initiate_tx( None, amount, // amount 2, // minimum confirmations - 500, // max outputs 1, // num change outputs true, // select all outputs None, From 65c0b1ecad7c24d69106fe145a3ec2ad73faa439 Mon Sep 17 00:00:00 2001 From: hashmap Date: Wed, 13 Feb 2019 00:16:09 +0100 Subject: [PATCH 07/28] Fix handling of IO WouldBlock error in Stratum server (#2528) If WouldBlock error happens Stratum server drops part of a message to read or write. This PR inroduces a worker's buffer to store partially read message which will be completed next time. For write the existing util function is used. Fixes #2524 --- servers/src/mining/stratumserver.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/servers/src/mining/stratumserver.rs b/servers/src/mining/stratumserver.rs index 439265770..4c9164569 100644 --- a/servers/src/mining/stratumserver.rs +++ b/servers/src/mining/stratumserver.rs @@ -152,6 +152,7 @@ pub struct Worker { stream: BufStream, error: bool, authenticated: bool, + buffer: String, } impl Worker { @@ -164,15 +165,18 @@ impl Worker { stream: stream, error: false, authenticated: false, + buffer: String::with_capacity(4096), } } // Get Message from the worker - fn read_message(&mut self, line: &mut String) -> Option { + fn read_message(&mut self) -> Option { // Read and return a single message or None - match self.stream.read_line(line) { - Ok(n) => { - return Some(n); + match self.stream.read_line(&mut self.buffer) { + Ok(_) => { + let res = self.buffer.clone(); + self.buffer.clear(); + return Some(res); } Err(ref e) if e.kind() == ErrorKind::WouldBlock => { // Not an error, just no messages ready @@ -183,6 +187,7 @@ impl Worker { "(Server ID: {}) Error in connection with stratum client: {}", self.id, e ); + self.buffer.clear(); self.error = true; return None; } @@ -195,7 +200,11 @@ impl Worker { if !message.ends_with("\n") { message += "\n"; } - match self.stream.write(message.as_bytes()) { + match util::read_write::write_all( + &mut self.stream, + message.as_bytes(), + Duration::from_secs(1), + ) { Ok(_) => match self.stream.flush() { Ok(_) => {} Err(e) => { @@ -281,10 +290,9 @@ impl StratumServer { // Handle an RPC request message from the worker(s) fn handle_rpc_requests(&mut self, stratum_stats: &mut Arc>) { let mut workers_l = self.workers.lock(); - let mut the_message = String::with_capacity(4096); for num in 0..workers_l.len() { - match workers_l[num].read_message(&mut the_message) { - Some(_) => { + match workers_l[num].read_message() { + Some(the_message) => { // Decompose the request from the JSONRpc wrapper let request: RpcRequest = match serde_json::from_str(&the_message) { Ok(request) => request, @@ -297,13 +305,10 @@ impl StratumServer { the_message.as_bytes(), ); workers_l[num].error = true; - the_message.clear(); continue; } }; - the_message.clear(); - let mut stratum_stats = stratum_stats.write(); let worker_stats_id = match stratum_stats .worker_stats From d6936f0ae7b1a7e7585df5fd712c217be3172a2d Mon Sep 17 00:00:00 2001 From: Peter Kalambet Date: Wed, 13 Feb 2019 02:22:41 +0300 Subject: [PATCH 08/28] Add more details to wallet TLS setup instruction (#2565) --- doc/wallet/tls-setup.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/doc/wallet/tls-setup.md b/doc/wallet/tls-setup.md index b73afbc7c..a6ff70e8f 100644 --- a/doc/wallet/tls-setup.md +++ b/doc/wallet/tls-setup.md @@ -17,6 +17,18 @@ tls_certificate_file = "/path/to/my/cerificate/fullchain.pem" tls_certificate_key = "/path/to/my/cerificate/privkey.pem" ``` +And update `api_listen_interface` to your static IP if you want to lock your wallet only to external interface + +```toml +api_listen_interface = "3.3.3.3" +``` + +Or, in case you are using DynDNS or `localhost` in order to comunicate with your wallet, just put `0.0.0.0` as mentioned in the inline instruction. + +```toml +api_listen_interface = "0.0.0.0" +``` + If you have Stratum server enabled (you run a miner) make sure that wallet listener URL starts with `https` in node config (by default `~/.grin/grin-server.toml`): ```toml @@ -57,13 +69,15 @@ Now you have the certificate files but only root user can read it. We run grin a ```sh sudo groupadd tls-cert sudo usermod -a -G tls-cert ubuntu -chgrp -R tls-cert /etc/letsencrypt -chmod -R g=rX /etc/letsencrypt +sudo chgrp -R tls-cert /etc/letsencrypt +sudo chmod -R g=rX /etc/letsencrypt sudo chmod 2755 /etc/letsencrypt ``` The last step is needed for renewal, it makes sure that all new files will have the same group ownership. +Now you need to logout so the user's group membership modification can take place. + ### Update wallet config Refer to `I have a TLS certificate already` because you have it now. Use the folowing values: From 91cca2bf61aff6de2199f5c11d4c42b269fcec44 Mon Sep 17 00:00:00 2001 From: John Tromp Date: Wed, 13 Feb 2019 01:10:17 +0100 Subject: [PATCH 09/28] test: add CuckAToo31 solution test (#2552) add CuckAToo31 solution test --- core/src/pow/cuckatoo.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/src/pow/cuckatoo.rs b/core/src/pow/cuckatoo.rs index f8da12f5f..8ae3d50b1 100644 --- a/core/src/pow/cuckatoo.rs +++ b/core/src/pow/cuckatoo.rs @@ -353,6 +353,16 @@ mod test { 0x1b2c20ad, 0x1bd7a83c, 0x1c05d5b0, 0x1c0b9caa, ]; + // Cuckatoo 31 Solution for Header [0u8;80] - nonce 99 + static V1_31: [u64; 42] = [ + 0x1128e07, 0xc181131, 0x110fad36, 0x1135ddee, 0x1669c7d3, 0x1931e6ea, 0x1c0005f3, 0x1dd6ecca, + 0x1e29ce7e, 0x209736fc, 0x2692bf1a, 0x27b85aa9, 0x29bb7693, 0x2dc2a047, 0x2e28650a, 0x2f381195, + 0x350eb3f9, 0x3beed728, 0x3e861cbc, 0x41448cc1, 0x41f08f6d, 0x42fbc48a, 0x4383ab31, 0x4389c61f, + 0x4540a5ce, 0x49a17405, 0x50372ded, 0x512f0db0, 0x588b6288, 0x5a36aa46, 0x5c29e1fe, 0x6118ab16, + 0x634705b5, 0x6633d190, 0x6683782f, 0x6728b6e1, 0x67adfb45, 0x68ae2306, 0x6d60f5e1, 0x78af3c4f, + 0x7dde51ab, 0x7faced21 + ]; + #[test] fn cuckatoo() { let ret = basic_solve::(); @@ -371,6 +381,14 @@ mod test { if let Err(r) = ret { panic!("validate_29_vectors u64: Error: {}", r); } + let ret = validate31_vectors::(); + if let Err(r) = ret { + panic!("validate_31_vectors u32: Error: {}", r); + } + let ret = validate31_vectors::(); + if let Err(r) = ret { + panic!("validate_31_vectors u64: Error: {}", r); + } let ret = validate_fail::(); if let Err(r) = ret { panic!("validate_fail u32: Error: {}", r); @@ -391,6 +409,16 @@ mod test { Ok(()) } + fn validate31_vectors() -> Result<(), Error> + where + T: EdgeType, + { + let mut ctx = CuckatooContext::::new_impl(31, 42, 10).unwrap(); + ctx.set_header_nonce([0u8; 80].to_vec(), Some(99), false)?; + assert!(ctx.verify(&Proof::new(V1_31.to_vec().clone())).is_ok()); + Ok(()) + } + fn validate_fail() -> Result<(), Error> where T: EdgeType, From 563c674700e52b6df7e2e4659201b63421aeaa18 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Wed, 13 Feb 2019 02:41:29 -0800 Subject: [PATCH 10/28] refactor: reserve capacity in aggregate (#2568) --- core/src/core/transaction.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index c536d1167..00f45044c 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -1000,15 +1000,22 @@ pub fn aggregate(mut txs: Vec) -> Result { } else if txs.len() == 1 { return Ok(txs.pop().unwrap()); } + let mut n_inputs = 0; + let mut n_outputs = 0; + let mut n_kernels = 0; + for tx in txs.iter() { + n_inputs += tx.body.inputs.len(); + n_outputs += tx.body.outputs.len(); + n_kernels += tx.body.kernels.len(); + } - let mut inputs: Vec = vec![]; - let mut outputs: Vec = vec![]; - let mut kernels: Vec = vec![]; + let mut inputs: Vec = Vec::with_capacity(n_inputs); + let mut outputs: Vec = Vec::with_capacity(n_outputs); + let mut kernels: Vec = Vec::with_capacity(n_kernels); // we will sum these together at the end to give us the overall offset for the // transaction - let mut kernel_offsets: Vec = vec![]; - + let mut kernel_offsets: Vec = Vec::with_capacity(txs.len()); for mut tx in txs { // we will sum these later to give a single aggregate offset kernel_offsets.push(tx.offset); From 5d904250d5dc3e2fe4c3ce30bb86e7f710087d34 Mon Sep 17 00:00:00 2001 From: hashmap Date: Wed, 13 Feb 2019 18:33:25 +0100 Subject: [PATCH 11/28] Use failure for Pool and Committed errors (#2570) It doesn't play nice with failure-based error management, we have to throw away an exisiting error and create a new one (failure-based) --- core/src/core/committed.rs | 7 ++++++- pool/Cargo.toml | 2 ++ pool/src/types.rs | 15 ++++++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/core/src/core/committed.rs b/core/src/core/committed.rs index 63fba9471..3aebfab49 100644 --- a/core/src/core/committed.rs +++ b/core/src/core/committed.rs @@ -20,17 +20,22 @@ use crate::keychain::BlindingFactor; use crate::util::secp::key::SecretKey; use crate::util::secp::pedersen::Commitment; use crate::util::{secp, secp_static, static_secp_instance}; +use failure::Fail; /// Errors from summing and verifying kernel excesses via committed trait. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Fail)] pub enum Error { /// Keychain related error. + #[fail(display = "Keychain error {}", _0)] Keychain(keychain::Error), /// Secp related error. + #[fail(display = "Secp error {}", _0)] Secp(secp::Error), /// Kernel sums do not equal output sums. + #[fail(display = "Kernel sum mismatch")] KernelSumMismatch, /// Committed overage (fee or reward) is invalid + #[fail(display = "Invalid value")] InvalidValue, } diff --git a/pool/Cargo.toml b/pool/Cargo.toml index a14d3bc74..431bd7533 100644 --- a/pool/Cargo.toml +++ b/pool/Cargo.toml @@ -16,6 +16,8 @@ serde = "1" serde_derive = "1" log = "0.4" chrono = "0.4.4" +failure = "0.1" +failure_derive = "0.1" grin_core = { path = "../core", version = "1.0.1" } grin_keychain = { path = "../keychain", version = "1.0.1" } diff --git a/pool/src/types.rs b/pool/src/types.rs index 41233e122..04f1a1ee2 100644 --- a/pool/src/types.rs +++ b/pool/src/types.rs @@ -23,6 +23,7 @@ use self::core::core::hash::Hash; use self::core::core::transaction::{self, Transaction}; use self::core::core::{BlockHeader, BlockSums}; use self::core::{consensus, global}; +use failure::Fail; use grin_core as core; use grin_keychain as keychain; @@ -179,32 +180,44 @@ pub struct TxSource { } /// Possible errors when interacting with the transaction pool. -#[derive(Debug)] +#[derive(Debug, Fail)] pub enum PoolError { /// An invalid pool entry caused by underlying tx validation error + #[fail(display = "Invalid Tx {}", _0)] InvalidTx(transaction::Error), /// An invalid pool entry caused by underlying block validation error + #[fail(display = "Invalid Block {}", _0)] InvalidBlock(block::Error), /// Underlying keychain error. + #[fail(display = "Keychain error {}", _0)] Keychain(keychain::Error), /// Underlying "committed" error. + #[fail(display = "Committed error {}", _0)] Committed(committed::Error), /// Attempt to add a transaction to the pool with lock_height /// greater than height of current block + #[fail(display = "Immature transaction")] ImmatureTransaction, /// Attempt to spend a coinbase output before it has sufficiently matured. + #[fail(display = "Immature coinbase")] ImmatureCoinbase, /// Problem propagating a stem tx to the next Dandelion relay node. + #[fail(display = "Dandelion error")] DandelionError, /// Transaction pool is over capacity, can't accept more transactions + #[fail(display = "Over capacity")] OverCapacity, /// Transaction fee is too low given its weight + #[fail(display = "Low fee transaction {}", _0)] LowFeeTransaction(u64), /// Attempt to add a duplicate output to the pool. + #[fail(display = "Duplicate commitment")] DuplicateCommitment, /// Attempt to add a duplicate tx to the pool. + #[fail(display = "Duplicate tx")] DuplicateTx, /// Other kinds of error (not yet pulled out into meaningful errors). + #[fail(display = "General pool error {}", _0)] Other(String), } From 41ed10940deab4d325ac521c8cec881f88be8b7b Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Wed, 13 Feb 2019 10:40:31 -0800 Subject: [PATCH 12/28] fix: Fix race condition with dandelion_relay peer map and make more semantic (#2548) * fix: Fix race condition with dandelion_relay peer map and make more semantic * Fix bug where we don't actually re-read the dandelion_relay variable after refreshing it --- p2p/src/peers.rs | 41 +++++++++++++++++++--------------------- servers/src/grin/seed.rs | 16 +++++++--------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/p2p/src/peers.rs b/p2p/src/peers.rs index 892622093..f60abbc4c 100644 --- a/p2p/src/peers.rs +++ b/p2p/src/peers.rs @@ -38,7 +38,7 @@ pub struct Peers { pub adapter: Arc, store: PeerStore, peers: RwLock>>, - dandelion_relay: RwLock>>, + dandelion_relay: RwLock)>>, config: P2PConfig, } @@ -49,7 +49,7 @@ impl Peers { store, config, peers: RwLock::new(HashMap::new()), - dandelion_relay: RwLock::new(HashMap::new()), + dandelion_relay: RwLock::new(None), } } @@ -115,10 +115,9 @@ impl Peers { fn set_dandelion_relay(&self, peer: &Arc) { // Clear the map and add new relay let dandelion_relay = &self.dandelion_relay; - dandelion_relay.write().clear(); dandelion_relay .write() - .insert(Utc::now().timestamp(), peer.clone()); + .replace((Utc::now().timestamp(), peer.clone())); debug!( "Successfully updated Dandelion relay to: {}", peer.info.addr @@ -126,7 +125,7 @@ impl Peers { } // Get the dandelion relay - pub fn get_dandelion_relay(&self) -> HashMap> { + pub fn get_dandelion_relay(&self) -> Option<(i64, Arc)> { self.dandelion_relay.read().clone() } @@ -370,24 +369,22 @@ impl Peers { /// Relays the provided stem transaction to our single stem peer. pub fn relay_stem_transaction(&self, tx: &core::Transaction) -> Result<(), Error> { - let dandelion_relay = self.get_dandelion_relay(); - if dandelion_relay.is_empty() { - debug!("No dandelion relay, updating."); - self.update_dandelion_relay(); - } - // If still return an error, let the caller handle this as they see fit. - // The caller will "fluff" at this point as the stem phase is finished. - if dandelion_relay.is_empty() { - return Err(Error::NoDandelionRelay); - } - for relay in dandelion_relay.values() { - if relay.is_connected() { - if let Err(e) = relay.send_stem_transaction(tx) { - debug!("Error sending stem transaction to peer relay: {:?}", e); + self.get_dandelion_relay() + .or_else(|| { + debug!("No dandelion relay, updating."); + self.update_dandelion_relay(); + self.get_dandelion_relay() + }) + // If still return an error, let the caller handle this as they see fit. + // The caller will "fluff" at this point as the stem phase is finished. + .ok_or(Error::NoDandelionRelay) + .map(|(_, relay)| { + if relay.is_connected() { + if let Err(e) = relay.send_stem_transaction(tx) { + debug!("Error sending stem transaction to peer relay: {:?}", e); + } } - } - } - Ok(()) + }) } /// Broadcasts the provided transaction to PEER_PREFERRED_COUNT of our diff --git a/servers/src/grin/seed.rs b/servers/src/grin/seed.rs index 6561210fb..fa01cc5a1 100644 --- a/servers/src/grin/seed.rs +++ b/servers/src/grin/seed.rs @@ -249,17 +249,15 @@ fn monitor_peers( fn update_dandelion_relay(peers: Arc, dandelion_config: DandelionConfig) { // Dandelion Relay Updater let dandelion_relay = peers.get_dandelion_relay(); - if dandelion_relay.is_empty() { + if let Some((last_added, _)) = dandelion_relay { + let dandelion_interval = Utc::now().timestamp() - last_added; + if dandelion_interval >= dandelion_config.relay_secs.unwrap() as i64 { + debug!("monitor_peers: updating expired dandelion relay"); + peers.update_dandelion_relay(); + } + } else { debug!("monitor_peers: no dandelion relay updating"); peers.update_dandelion_relay(); - } else { - for last_added in dandelion_relay.keys() { - let dandelion_interval = Utc::now().timestamp() - last_added; - if dandelion_interval >= dandelion_config.relay_secs.unwrap() as i64 { - debug!("monitor_peers: updating expired dandelion relay"); - peers.update_dandelion_relay(); - } - } } } From d4540f32a38e92bff0ef984da314ae83c2be63a5 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Thu, 14 Feb 2019 03:01:54 -0800 Subject: [PATCH 13/28] refactor: use sort_unstable instead of sort, more efficient with_* methods for TransactionBody (#2564) --- core/src/core/compact_block.rs | 6 ++-- core/src/core/transaction.rs | 66 +++++++++++++++------------------- core/src/pow/cuckatoo.rs | 2 +- core/src/pow/types.rs | 4 +-- 4 files changed, 35 insertions(+), 43 deletions(-) diff --git a/core/src/core/compact_block.rs b/core/src/core/compact_block.rs index 031728069..b143234ab 100644 --- a/core/src/core/compact_block.rs +++ b/core/src/core/compact_block.rs @@ -62,9 +62,9 @@ impl CompactBlockBody { /// Sort everything. fn sort(&mut self) { - self.out_full.sort(); - self.kern_full.sort(); - self.kern_ids.sort(); + self.out_full.sort_unstable(); + self.kern_full.sort_unstable(); + self.kern_ids.sort_unstable(); } /// "Lightweight" validation. diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 00f45044c..70b8c6122 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -487,9 +487,9 @@ impl TransactionBody { /// Sort the inputs|outputs|kernels. pub fn sort(&mut self) { - self.inputs.sort(); - self.outputs.sort(); - self.kernels.sort(); + self.inputs.sort_unstable(); + self.outputs.sort_unstable(); + self.kernels.sort_unstable(); } /// Creates a new transaction body initialized with @@ -501,7 +501,7 @@ impl TransactionBody { kernels: Vec, verify_sorted: bool, ) -> Result { - let body = TransactionBody { + let mut body = TransactionBody { inputs, outputs, kernels, @@ -511,52 +511,44 @@ impl TransactionBody { // If we are verifying sort order then verify and // return an error if not sorted lexicographically. body.verify_sorted()?; - Ok(body) } else { // If we are not verifying sort order then sort in place and return. - let mut body = body; body.sort(); - Ok(body) } + Ok(body) } /// Builds a new body with the provided inputs added. Existing /// inputs, if any, are kept intact. /// Sort order is maintained. - pub fn with_input(self, input: Input) -> TransactionBody { - let mut new_ins = self.inputs; - new_ins.push(input); - new_ins.sort(); - TransactionBody { - inputs: new_ins, - ..self - } + pub fn with_input(mut self, input: Input) -> TransactionBody { + self.inputs + .binary_search(&input) + .err() + .map(|e| self.inputs.insert(e, input)); + self } /// Builds a new TransactionBody with the provided output added. Existing /// outputs, if any, are kept intact. /// Sort order is maintained. - pub fn with_output(self, output: Output) -> TransactionBody { - let mut new_outs = self.outputs; - new_outs.push(output); - new_outs.sort(); - TransactionBody { - outputs: new_outs, - ..self - } + pub fn with_output(mut self, output: Output) -> TransactionBody { + self.outputs + .binary_search(&output) + .err() + .map(|e| self.outputs.insert(e, output)); + self } /// Builds a new TransactionBody with the provided kernel added. Existing /// kernels, if any, are kept intact. /// Sort order is maintained. - pub fn with_kernel(self, kernel: TxKernel) -> TransactionBody { - let mut new_kerns = self.kernels; - new_kerns.push(kernel); - new_kerns.sort(); - TransactionBody { - kernels: new_kerns, - ..self - } + pub fn with_kernel(mut self, kernel: TxKernel) -> TransactionBody { + self.kernels + .binary_search(&kernel) + .err() + .map(|e| self.kernels.insert(e, kernel)); + self } /// Total fee for a TransactionBody is the sum of fees of all kernels. @@ -987,8 +979,8 @@ pub fn cut_through(inputs: &mut Vec, outputs: &mut Vec) -> Result // filter and sort inputs.retain(|inp| !to_cut_through.contains(&inp.commitment())); outputs.retain(|out| !to_cut_through.contains(&out.commitment())); - inputs.sort(); - outputs.sort(); + inputs.sort_unstable(); + outputs.sort_unstable(); Ok(()) } @@ -1029,7 +1021,7 @@ pub fn aggregate(mut txs: Vec) -> Result { cut_through(&mut inputs, &mut outputs)?; // Now sort kernels. - kernels.sort(); + kernels.sort_unstable(); // now sum the kernel_offsets up to give us an aggregate offset for the // transaction @@ -1100,9 +1092,9 @@ pub fn deaggregate(mk_tx: Transaction, txs: Vec) -> Result) -> Proof { - in_nonces.sort(); + in_nonces.sort_unstable(); Proof { edge_bits: global::min_edge_bits(), nonces: in_nonces, @@ -369,7 +369,7 @@ impl Proof { .map(|()| (rng.gen::() & nonce_mask) as u64) .take(proof_size) .collect(); - v.sort(); + v.sort_unstable(); Proof { edge_bits: global::min_edge_bits(), nonces: v, From 99494c6fa67566859df6d9b6a3262d4c28a55f46 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Fri, 15 Feb 2019 05:41:19 -0800 Subject: [PATCH 14/28] get rid of default implementation of Hashed trait for writable things (#2573) --- chain/src/txhashset/utxo_view.rs | 2 +- chain/src/types.rs | 7 ++--- core/src/core/block.rs | 19 ++++++++------ core/src/core/compact_block.rs | 4 ++- core/src/core/hash.rs | 40 +++++++++++++++++++---------- core/src/core/id.rs | 5 +++- core/src/core/transaction.rs | 11 +++++++- core/src/pow/types.rs | 4 ++- core/src/ser.rs | 8 +++--- core/tests/vec_backend.rs | 4 ++- servers/src/mining/stratumserver.rs | 1 + store/tests/pmmr.rs | 3 +++ 12 files changed, 74 insertions(+), 34 deletions(-) diff --git a/chain/src/txhashset/utxo_view.rs b/chain/src/txhashset/utxo_view.rs index 1b648ba72..2823acbe8 100644 --- a/chain/src/txhashset/utxo_view.rs +++ b/chain/src/txhashset/utxo_view.rs @@ -14,7 +14,7 @@ //! Lightweight readonly view into output MMR for convenience. -use crate::core::core::hash::Hash; +use crate::core::core::hash::{Hash, Hashed}; use crate::core::core::pmmr::{self, ReadonlyPMMR}; use crate::core::core::{Block, BlockHeader, Input, Output, Transaction}; use crate::core::global; diff --git a/chain/src/types.rs b/chain/src/types.rs index 7e784b809..27895e7c4 100644 --- a/chain/src/types.rs +++ b/chain/src/types.rs @@ -73,10 +73,11 @@ impl Tip { total_difficulty: header.total_difficulty(), } } +} - /// *Really* easy to accidentally call hash() on a tip (thinking its a header). - /// So lets make hash() do the right thing here. - pub fn hash(&self) -> Hash { +impl Hashed for Tip { + /// The hash of the underlying block. + fn hash(&self) -> Hash { self.last_block_h } } diff --git a/core/src/core/block.rs b/core/src/core/block.rs index c765d90eb..5f1887af0 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -25,7 +25,7 @@ use std::sync::Arc; use crate::consensus::{reward, REWARD}; use crate::core::committed::{self, Committed}; use crate::core::compact_block::{CompactBlock, CompactBlockBody}; -use crate::core::hash::{Hash, Hashed, ZERO_HASH}; +use crate::core::hash::{DefaultHashable, Hash, Hashed, ZERO_HASH}; use crate::core::verifier_cache::VerifierCache; use crate::core::{ transaction, Commitment, Input, Output, Transaction, TransactionBody, TxKernel, Weighting, @@ -160,9 +160,9 @@ impl FixedLength for HeaderEntry { const LEN: usize = Hash::LEN + 8 + Difficulty::LEN + 4 + 1; } -impl HeaderEntry { +impl Hashed for HeaderEntry { /// The hash of the underlying block. - pub fn hash(&self) -> Hash { + fn hash(&self) -> Hash { self.hash } } @@ -197,6 +197,7 @@ pub struct BlockHeader { /// Proof of work and related pub pow: ProofOfWork, } +impl DefaultHashable for BlockHeader {} impl Default for BlockHeader { fn default() -> BlockHeader { @@ -353,6 +354,13 @@ pub struct Block { body: TransactionBody, } +impl Hashed for Block { + /// The hash of the underlying block. + fn hash(&self) -> Hash { + self.header.hash() + } +} + /// Implementation of Writeable for a block, defines how to write the block to a /// binary writer. Differentiates between writing the block for the purpose of /// full serialization and the one of just extracting a hash. @@ -570,11 +578,6 @@ impl Block { &mut self.body.kernels } - /// Blockhash, computed using only the POW - pub fn hash(&self) -> Hash { - self.header.hash() - } - /// Sum of all fees (inputs less outputs) in the block pub fn total_fees(&self) -> u64 { self.body diff --git a/core/src/core/compact_block.rs b/core/src/core/compact_block.rs index b143234ab..ea7d2a634 100644 --- a/core/src/core/compact_block.rs +++ b/core/src/core/compact_block.rs @@ -17,7 +17,7 @@ use rand::{thread_rng, Rng}; use crate::core::block::{Block, BlockHeader, Error}; -use crate::core::hash::Hashed; +use crate::core::hash::{DefaultHashable, Hashed}; use crate::core::id::ShortIdentifiable; use crate::core::{Output, ShortId, TxKernel}; use crate::ser::{self, read_multi, Readable, Reader, VerifySortedAndUnique, Writeable, Writer}; @@ -137,6 +137,8 @@ pub struct CompactBlock { body: CompactBlockBody, } +impl DefaultHashable for CompactBlock {} + impl CompactBlock { /// "Lightweight" validation. fn validate_read(&self) -> Result<(), Error> { diff --git a/core/src/core/hash.rs b/core/src/core/hash.rs index 446ee8910..e0638762c 100644 --- a/core/src/core/hash.rs +++ b/core/src/core/hash.rs @@ -36,6 +36,19 @@ pub const ZERO_HASH: Hash = Hash([0; 32]); #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] pub struct Hash([u8; 32]); +impl DefaultHashable for Hash {} + +impl Hash { + fn hash_with(&self, other: T) -> Hash { + let mut hasher = HashWriter::default(); + ser::Writeable::write(self, &mut hasher).unwrap(); + ser::Writeable::write(&other, &mut hasher).unwrap(); + let mut ret = [0; 32]; + hasher.finalize(&mut ret); + Hash(ret) + } +} + impl fmt::Debug for Hash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let hash_hex = self.to_hex(); @@ -212,25 +225,26 @@ impl ser::Writer for HashWriter { pub trait Hashed { /// Obtain the hash of the object fn hash(&self) -> Hash; - /// Hash the object together with another writeable object - fn hash_with(&self, other: T) -> Hash; } -impl Hashed for W { +/// Implementing this trait enables the default +/// hash implementation +pub trait DefaultHashable: Writeable {} +impl Hashed for D { fn hash(&self) -> Hash { let mut hasher = HashWriter::default(); - ser::Writeable::write(self, &mut hasher).unwrap(); - let mut ret = [0; 32]; - hasher.finalize(&mut ret); - Hash(ret) - } - - fn hash_with(&self, other: T) -> Hash { - let mut hasher = HashWriter::default(); - ser::Writeable::write(self, &mut hasher).unwrap(); - ser::Writeable::write(&other, &mut hasher).unwrap(); + Writeable::write(self, &mut hasher).unwrap(); let mut ret = [0; 32]; hasher.finalize(&mut ret); Hash(ret) } } + +impl DefaultHashable for &D {} +impl DefaultHashable for (D, E) {} +impl DefaultHashable for (D, E, F) {} + +/// Implement Hashed trait for external types here +impl DefaultHashable for crate::util::secp::pedersen::RangeProof {} +impl DefaultHashable for Vec {} +impl DefaultHashable for u64 {} diff --git a/core/src/core/id.rs b/core/src/core/id.rs index 99ea8643c..9921bb17c 100644 --- a/core/src/core/id.rs +++ b/core/src/core/id.rs @@ -20,7 +20,7 @@ use std::cmp::Ordering; use byteorder::{ByteOrder, LittleEndian}; use siphasher::sip::SipHasher24; -use crate::core::hash::{Hash, Hashed}; +use crate::core::hash::{DefaultHashable, Hash, Hashed}; use crate::ser::{self, Readable, Reader, Writeable, Writer}; use crate::util; @@ -73,6 +73,7 @@ impl ShortIdentifiable for H { #[derive(Clone, Serialize, Deserialize, Hash)] pub struct ShortId([u8; 6]); +impl DefaultHashable for ShortId {} /// We want to sort short_ids in a canonical and consistent manner so we can /// verify sort order in the same way we do for full inputs|outputs|kernels /// themselves. @@ -168,6 +169,8 @@ mod test { } } + impl DefaultHashable for Foo {} + let foo = Foo(0); let expected_hash = diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 70b8c6122..0e67e6489 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -14,7 +14,7 @@ //! Transactions -use crate::core::hash::Hashed; +use crate::core::hash::{DefaultHashable, Hashed}; use crate::core::verifier_cache::VerifierCache; use crate::core::{committed, Committed}; use crate::keychain::{self, BlindingFactor}; @@ -50,6 +50,8 @@ enum_from_primitive! { } } +impl DefaultHashable for KernelFeatures {} + impl Writeable for KernelFeatures { fn write(&self, writer: &mut W) -> Result<(), ser::Error> { writer.write_u8(*self as u8)?; @@ -170,6 +172,7 @@ pub struct TxKernel { pub excess_sig: secp::Signature, } +impl DefaultHashable for TxKernel {} hashable_ord!(TxKernel); impl ::std::hash::Hash for TxKernel { @@ -753,6 +756,8 @@ pub struct Transaction { body: TransactionBody, } +impl DefaultHashable for Transaction {} + /// PartialEq impl PartialEq for Transaction { fn eq(&self, tx: &Transaction) -> bool { @@ -1113,6 +1118,7 @@ pub struct Input { pub commit: Commitment, } +impl DefaultHashable for Input {} hashable_ord!(Input); impl ::std::hash::Hash for Input { @@ -1218,6 +1224,7 @@ pub struct Output { pub proof: RangeProof, } +impl DefaultHashable for Output {} hashable_ord!(Output); impl ::std::hash::Hash for Output { @@ -1330,6 +1337,8 @@ pub struct OutputIdentifier { pub commit: Commitment, } +impl DefaultHashable for OutputIdentifier {} + impl OutputIdentifier { /// Build a new output_identifier. pub fn new(features: OutputFeatures, commit: &Commitment) -> OutputIdentifier { diff --git a/core/src/pow/types.rs b/core/src/pow/types.rs index 1e83607bd..49e53a76d 100644 --- a/core/src/pow/types.rs +++ b/core/src/pow/types.rs @@ -22,7 +22,7 @@ use rand::{thread_rng, Rng}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use crate::consensus::{graph_weight, MIN_DIFFICULTY, SECOND_POW_EDGE_BITS}; -use crate::core::hash::Hashed; +use crate::core::hash::{DefaultHashable, Hashed}; use crate::global; use crate::ser::{self, FixedLength, Readable, Reader, Writeable, Writer}; @@ -324,6 +324,8 @@ pub struct Proof { pub nonces: Vec, } +impl DefaultHashable for Proof {} + impl fmt::Debug for Proof { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Cuckoo{}(", self.edge_bits)?; diff --git a/core/src/ser.rs b/core/src/ser.rs index 7b8903db7..babebae79 100644 --- a/core/src/ser.rs +++ b/core/src/ser.rs @@ -19,7 +19,7 @@ //! To use it simply implement `Writeable` or `Readable` and then use the //! `serialize` or `deserialize` functions on them as appropriate. -use crate::core::hash::{Hash, Hashed}; +use crate::core::hash::{DefaultHashable, Hash, Hashed}; use crate::keychain::{BlindingFactor, Identifier, IDENTIFIER_SIZE}; use crate::util::read_write::read_exact; use crate::util::secp::constants::{ @@ -615,7 +615,7 @@ where match elem { Ok(e) => buf.push(e), Err(Error::IOErr(ref _d, ref kind)) if *kind == io::ErrorKind::UnexpectedEof => { - break + break; } Err(e) => return Err(e), } @@ -706,7 +706,7 @@ pub trait FixedLength { } /// Trait for types that can be added to a PMMR. -pub trait PMMRable: Writeable + Clone + Debug { +pub trait PMMRable: Writeable + Clone + Debug + DefaultHashable { /// The type of element actually stored in the MMR data file. /// This allows us to store Hash elements in the header MMR for variable size BlockHeaders. type E: FixedLength + Readable + Writeable; @@ -721,7 +721,7 @@ pub trait PMMRIndexHashable { fn hash_with_index(&self, index: u64) -> Hash; } -impl PMMRIndexHashable for T { +impl PMMRIndexHashable for T { fn hash_with_index(&self, index: u64) -> Hash { (index, self).hash() } diff --git a/core/tests/vec_backend.rs b/core/tests/vec_backend.rs index 25143260b..e7bae7cba 100644 --- a/core/tests/vec_backend.rs +++ b/core/tests/vec_backend.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use self::core::core::hash::Hash; +use self::core::core::hash::{DefaultHashable, Hash}; use self::core::core::pmmr::{self, Backend}; use self::core::core::BlockHeader; use self::core::ser; @@ -25,6 +25,8 @@ use std::path::Path; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct TestElem(pub [u32; 4]); +impl DefaultHashable for TestElem {} + impl FixedLength for TestElem { const LEN: usize = 16; } diff --git a/servers/src/mining/stratumserver.rs b/servers/src/mining/stratumserver.rs index 4c9164569..be6b2b9cb 100644 --- a/servers/src/mining/stratumserver.rs +++ b/servers/src/mining/stratumserver.rs @@ -29,6 +29,7 @@ use std::{cmp, thread}; use crate::chain; use crate::common::stats::{StratumStats, WorkerStats}; use crate::common::types::{StratumServerConfig, SyncState}; +use crate::core::core::hash::Hashed; use crate::core::core::verifier_cache::VerifierCache; use crate::core::core::Block; use crate::core::{pow, ser}; diff --git a/store/tests/pmmr.rs b/store/tests/pmmr.rs index 26d75ec7f..00abd7a5f 100644 --- a/store/tests/pmmr.rs +++ b/store/tests/pmmr.rs @@ -21,6 +21,7 @@ use std::fs; use chrono::prelude::Utc; use croaring::Bitmap; +use crate::core::core::hash::DefaultHashable; use crate::core::core::pmmr::{Backend, PMMR}; use crate::core::ser::{ Error, FixedLength, PMMRIndexHashable, PMMRable, Readable, Reader, Writeable, Writer, @@ -903,6 +904,8 @@ fn load(pos: u64, elems: &[TestElem], backend: &mut store::pmmr::PMMRBackend Date: Fri, 15 Feb 2019 22:33:10 +0800 Subject: [PATCH 15/28] suppress the debug log for unexpected file report (#2574) * supress the debug log for unexpected file report in check_and_remove_files * revise according to review comments * rustfmt --- chain/src/txhashset/txhashset.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index 3520ebb2c..9be78cd27 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -1496,19 +1496,27 @@ fn check_and_remove_files(txhashset_path: &PathBuf, header: &BlockHeader) -> Res .difference(&pmmr_files_expected) .cloned() .collect(); + let mut removed = 0; if !difference.is_empty() { - debug!( - "Unexpected file(s) found in txhashset subfolder {:?}, removing.", - &subdirectory_path - ); - for diff in difference { + for diff in &difference { let diff_path = subdirectory_path.join(diff); - file::delete(diff_path.clone())?; - debug!( - "check_and_remove_files: unexpected file '{:?}' removed", - diff_path - ); + match file::delete(diff_path.clone()) { + Err(e) => error!( + "check_and_remove_files: fail to remove file '{:?}', Err: {:?}", + diff_path, e, + ), + Ok(_) => { + removed += 1; + trace!("check_and_remove_files: file '{:?}' removed", diff_path); + } + } } + debug!( + "{} tmp file(s) found in txhashset subfolder {:?}, {} removed.", + difference.len(), + &subdirectory_path, + removed, + ); } } Ok(()) From 049a0cd1286f2fef41eaa87dc1722c05889c2477 Mon Sep 17 00:00:00 2001 From: hashmap Date: Fri, 15 Feb 2019 19:46:25 +0100 Subject: [PATCH 16/28] Fix compiler warnings (#2579) --- config/src/config.rs | 1 + src/bin/cmd/server.rs | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/config/src/config.rs b/config/src/config.rs index 252f43c1b..af1261124 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -46,6 +46,7 @@ const GRIN_HOME: &'static str = ".grin"; const GRIN_CHAIN_DIR: &'static str = "chain_data"; /// Wallet data directory pub const GRIN_WALLET_DIR: &'static str = "wallet_data"; +/// API secret file name pub const API_SECRET_FILE_NAME: &'static str = ".api_secret"; fn get_grin_path(chain_type: &global::ChainTypes) -> Result { diff --git a/src/bin/cmd/server.rs b/src/bin/cmd/server.rs index ea9c4ad0b..1d3b03c1a 100644 --- a/src/bin/cmd/server.rs +++ b/src/bin/cmd/server.rs @@ -13,8 +13,6 @@ // limitations under the License. /// Grin server commands processing -#[cfg(not(target_os = "windows"))] -use std::env::current_dir; use std::process::exit; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; From aad0e9402a826e14df9de02bbdc6eb1dc3e4da6e Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Fri, 15 Feb 2019 11:12:27 -0800 Subject: [PATCH 17/28] fix: update Cargo.lock (#2580) --- Cargo.lock | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index b0d760be8..360c9a767 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -913,6 +913,8 @@ version = "1.0.1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "grin_chain 1.0.1", "grin_core 1.0.1", "grin_keychain 1.0.1", From ac6ed71abd54bdbb89d83e12ef5a30e59c4087d7 Mon Sep 17 00:00:00 2001 From: hashmap Date: Fri, 15 Feb 2019 22:17:00 +0100 Subject: [PATCH 18/28] Refactor API handlers (#2572) Also add some API tests --- api/src/client.rs | 9 +++ api/src/handlers/blocks_api.rs | 12 +--- api/src/handlers/chain_api.rs | 76 ++++----------------- api/src/handlers/peers_api.rs | 15 ++--- api/src/handlers/pool_api.rs | 26 +++----- api/src/handlers/transactions_api.rs | 59 ++--------------- api/src/handlers/utils.rs | 15 +++-- api/src/lib.rs | 3 +- api/src/web.rs | 99 ++++++++++++++++++++++++++++ servers/tests/api.rs | 97 ++++++++++++++++++++++----- 10 files changed, 236 insertions(+), 175 deletions(-) diff --git a/api/src/client.rs b/api/src/client.rs index bc176924c..98636ce0b 100644 --- a/api/src/client.rs +++ b/api/src/client.rs @@ -52,6 +52,15 @@ where } } +/// Helper function to easily issue a HTTP GET request +/// on a given URL that returns nothing. Handles request +/// building and response code checking. +pub fn get_no_ret(url: &str, api_secret: Option) -> Result<(), Error> { + let req = build_request(url, "GET", api_secret, None)?; + send_request(req)?; + Ok(()) +} + /// Helper function to easily issue a HTTP POST request with the provided JSON /// object as body on a given URL that returns a JSON object. Handles request /// building, JSON serialization and deserialization, and response code diff --git a/api/src/handlers/blocks_api.rs b/api/src/handlers/blocks_api.rs index e03d35c28..9da0a1c87 100644 --- a/api/src/handlers/blocks_api.rs +++ b/api/src/handlers/blocks_api.rs @@ -11,7 +11,6 @@ // 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::utils::{get_output, w}; use crate::chain; use crate::core::core::hash::Hash; @@ -68,10 +67,7 @@ impl HeaderHandler { impl Handler for HeaderHandler { fn get(&self, req: Request) -> ResponseFuture { - let el = match req.uri().path().trim_right_matches('/').rsplit('/').next() { - None => return response(StatusCode::BAD_REQUEST, "invalid url"), - Some(el) => el, - }; + let el = right_path_element!(req); result_to_response(self.get_header(el.to_string())) } } @@ -130,11 +126,7 @@ fn check_block_param(input: &String) -> Result<(), Error> { impl Handler for BlockHandler { fn get(&self, req: Request) -> ResponseFuture { - let el = match req.uri().path().trim_right_matches('/').rsplit('/').next() { - None => return response(StatusCode::BAD_REQUEST, "invalid url"), - Some(el) => el, - }; - + let el = right_path_element!(req); let h = match self.parse_input(el.to_string()) { Err(e) => { return response( diff --git a/api/src/handlers/chain_api.rs b/api/src/handlers/chain_api.rs index af269d71f..d0df2aa4f 100644 --- a/api/src/handlers/chain_api.rs +++ b/api/src/handlers/chain_api.rs @@ -22,9 +22,7 @@ use crate::util; use crate::util::secp::pedersen::Commitment; use crate::web::*; use hyper::{Body, Request, StatusCode}; -use std::collections::HashMap; use std::sync::Weak; -use url::form_urlencoded; /// Chain handler. Get the head details. /// GET /v1/chain @@ -101,21 +99,9 @@ impl OutputHandler { fn outputs_by_ids(&self, req: &Request) -> Result, Error> { let mut commitments: Vec = vec![]; - let query = match req.uri().query() { - Some(q) => q, - None => return Err(ErrorKind::RequestError("no query string".to_owned()))?, - }; - let params = form_urlencoded::parse(query.as_bytes()) - .into_owned() - .collect::>(); - - for (k, id) in params { - if k == "id" { - for id in id.split(',') { - commitments.push(id.to_owned()); - } - } - } + let query = must_get_query!(req); + let params = QueryParams::from(query); + params.process_multival_param("id", |id| commitments.push(id.to_owned())); let mut outputs: Vec = vec![]; for x in commitments { @@ -159,49 +145,17 @@ impl OutputHandler { // returns outputs for a specified range of blocks fn outputs_block_batch(&self, req: &Request) -> Result, Error> { let mut commitments: Vec = vec![]; - let mut start_height = 1; - let mut end_height = 1; - let mut include_rp = false; - let query = match req.uri().query() { - Some(q) => q, - None => return Err(ErrorKind::RequestError("no query string".to_owned()))?, - }; - - let params = form_urlencoded::parse(query.as_bytes()).into_owned().fold( - HashMap::new(), - |mut hm, (k, v)| { - hm.entry(k).or_insert(vec![]).push(v); - hm - }, - ); - - if let Some(ids) = params.get("id") { - for id in ids { - for id in id.split(',') { - if let Ok(x) = util::from_hex(String::from(id)) { - commitments.push(Commitment::from_vec(x)); - } - } + let query = must_get_query!(req); + let params = QueryParams::from(query); + params.process_multival_param("id", |id| { + if let Ok(x) = util::from_hex(String::from(id)) { + commitments.push(Commitment::from_vec(x)); } - } - if let Some(heights) = params.get("start_height") { - for height in heights { - start_height = height - .parse() - .map_err(|_| ErrorKind::RequestError("invalid start_height".to_owned()))?; - } - } - if let Some(heights) = params.get("end_height") { - for height in heights { - end_height = height - .parse() - .map_err(|_| ErrorKind::RequestError("invalid end_height".to_owned()))?; - } - } - if let Some(_) = params.get("include_rp") { - include_rp = true; - } + }); + let start_height = parse_param!(params, "start_height", 1); + let end_height = parse_param!(params, "end_height", 1); + let include_rp = params.get("include_rp").is_some(); debug!( "outputs_block_batch: {}-{}, {:?}, {:?}", @@ -223,11 +177,7 @@ impl OutputHandler { impl Handler for OutputHandler { fn get(&self, req: Request) -> ResponseFuture { - let command = match req.uri().path().trim_right_matches('/').rsplit('/').next() { - Some(c) => c, - None => return response(StatusCode::BAD_REQUEST, "invalid url"), - }; - match command { + match right_path_element!(req) { "byids" => result_to_response(self.outputs_by_ids(&req)), "byheight" => result_to_response(self.outputs_block_batch(&req)), _ => response(StatusCode::BAD_REQUEST, ""), diff --git a/api/src/handlers/peers_api.rs b/api/src/handlers/peers_api.rs index 31494a17c..692245dbc 100644 --- a/api/src/handlers/peers_api.rs +++ b/api/src/handlers/peers_api.rs @@ -37,11 +37,11 @@ pub struct PeersConnectedHandler { impl Handler for PeersConnectedHandler { fn get(&self, _req: Request) -> ResponseFuture { - let mut peers: Vec = vec![]; - for p in &w(&self.peers).connected_peers() { - let peer_info = p.info.clone(); - peers.push(peer_info.into()); - } + let peers: Vec = w(&self.peers) + .connected_peers() + .iter() + .map(|p| p.info.clone().into()) + .collect(); json_response(&peers) } } @@ -56,10 +56,7 @@ pub struct PeerHandler { impl Handler for PeerHandler { fn get(&self, req: Request) -> ResponseFuture { - let command = match req.uri().path().trim_right_matches('/').rsplit('/').next() { - Some(c) => c, - None => return response(StatusCode::BAD_REQUEST, "invalid url"), - }; + let command = right_path_element!(req); if let Ok(addr) = command.parse() { match w(&self.peers).get_peer(addr) { Ok(peer) => json_response(&peer), diff --git a/api/src/handlers/pool_api.rs b/api/src/handlers/pool_api.rs index f96d3685e..299b79a28 100644 --- a/api/src/handlers/pool_api.rs +++ b/api/src/handlers/pool_api.rs @@ -23,12 +23,11 @@ use crate::types::*; use crate::util; use crate::util::RwLock; use crate::web::*; +use failure::ResultExt; use futures::future::ok; use futures::Future; use hyper::{Body, Request, StatusCode}; -use std::collections::HashMap; use std::sync::Weak; -use url::form_urlencoded; /// Get basic information about the transaction pool. /// GET /v1/pool @@ -61,15 +60,7 @@ pub struct PoolPushHandler { impl PoolPushHandler { fn update_pool(&self, req: Request) -> Box + Send> { - let params = match req.uri().query() { - Some(query_string) => form_urlencoded::parse(query_string.as_bytes()) - .into_owned() - .fold(HashMap::new(), |mut hm, (k, v)| { - hm.entry(k).or_insert(vec![]).push(v); - hm - }), - None => HashMap::new(), - }; + let params = QueryParams::from(req.uri().query()); let fluff = params.get("fluff").is_some(); let pool_arc = w(&self.tx_pool).clone(); @@ -99,13 +90,14 @@ impl PoolPushHandler { // Push to tx pool. let mut tx_pool = pool_arc.write(); - let header = tx_pool.blockchain.chain_head().unwrap(); - tx_pool + let header = tx_pool + .blockchain + .chain_head() + .context(ErrorKind::Internal("Failed to get chain head".to_owned()))?; + let res = tx_pool .add_to_pool(source, tx, !fluff, &header) - .map_err(|e| { - error!("update_pool: failed with error: {:?}", e); - ErrorKind::Internal(format!("Failed to update pool: {:?}", e)).into() - }) + .context(ErrorKind::Internal("Failed to update pool".to_owned()))?; + Ok(res) }), ) } diff --git a/api/src/handlers/transactions_api.rs b/api/src/handlers/transactions_api.rs index 3a279b477..42723e71d 100644 --- a/api/src/handlers/transactions_api.rs +++ b/api/src/handlers/transactions_api.rs @@ -22,9 +22,7 @@ use crate::util::secp::pedersen::Commitment; use crate::web::*; use failure::ResultExt; use hyper::{Body, Request, StatusCode}; -use std::collections::HashMap; use std::sync::Weak; -use url::form_urlencoded; // Sum tree handler. Retrieve the roots: // GET /v1/txhashset/roots @@ -114,59 +112,14 @@ impl TxHashSetHandler { impl Handler for TxHashSetHandler { fn get(&self, req: Request) -> ResponseFuture { - let mut start_index = 1; - let mut max = 100; - let mut id = "".to_owned(); - // TODO: probably need to set a reasonable max limit here - let mut last_n = 10; - if let Some(query_string) = req.uri().query() { - let params = form_urlencoded::parse(query_string.as_bytes()) - .into_owned() - .fold(HashMap::new(), |mut hm, (k, v)| { - hm.entry(k).or_insert(vec![]).push(v); - hm - }); - if let Some(nums) = params.get("n") { - for num in nums { - if let Ok(n) = str::parse(num) { - last_n = n; - } - } - } - if let Some(start_indexes) = params.get("start_index") { - for si in start_indexes { - if let Ok(s) = str::parse(si) { - start_index = s; - } - } - } - if let Some(maxes) = params.get("max") { - for ma in maxes { - if let Ok(m) = str::parse(ma) { - max = m; - } - } - } - if let Some(ids) = params.get("id") { - if !ids.is_empty() { - id = ids.last().unwrap().to_owned(); - } - } - } - let command = match req - .uri() - .path() - .trim_right() - .trim_right_matches("/") - .rsplit("/") - .next() - { - Some(c) => c, - None => return response(StatusCode::BAD_REQUEST, "invalid url"), - }; + let params = QueryParams::from(req.uri().query()); + let last_n = parse_param_no_err!(params, "n", 10); + let start_index = parse_param_no_err!(params, "start_index", 1); + let max = parse_param_no_err!(params, "max", 100); + let id = parse_param_no_err!(params, "id", "".to_owned()); - match command { + match right_path_element!(req) { "roots" => json_response_pretty(&self.get_roots()), "lastoutputs" => json_response_pretty(&self.get_last_n_output(last_n)), "lastrangeproofs" => json_response_pretty(&self.get_last_n_rangeproof(last_n)), diff --git a/api/src/handlers/utils.rs b/api/src/handlers/utils.rs index 6a4f98ad0..bedaf0904 100644 --- a/api/src/handlers/utils.rs +++ b/api/src/handlers/utils.rs @@ -48,12 +48,15 @@ pub fn get_output( OutputIdentifier::new(OutputFeatures::Coinbase, &commit), ]; - for x in outputs.iter() { - if let Ok(_) = w(chain).is_unspent(&x) { - let block_height = w(chain).get_header_for_output(&x).unwrap().height; - let output_pos = w(chain).get_output_pos(&x.commit).unwrap_or(0); - return Ok((Output::new(&commit, block_height, output_pos), x.clone())); - } + for x in outputs.iter().filter(|x| w(chain).is_unspent(x).is_ok()) { + let block_height = w(chain) + .get_header_for_output(&x) + .context(ErrorKind::Internal( + "Can't get header for output".to_owned(), + ))? + .height; + let output_pos = w(chain).get_output_pos(&x.commit).unwrap_or(0); + return Ok((Output::new(&commit, block_height, output_pos), x.clone())); } Err(ErrorKind::NotFound)? } diff --git a/api/src/lib.rs b/api/src/lib.rs index 4ad2cebd8..282a29009 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -30,13 +30,14 @@ extern crate serde_derive; #[macro_use] extern crate log; +#[macro_use] +mod web; pub mod auth; pub mod client; mod handlers; mod rest; mod router; mod types; -mod web; pub use crate::auth::BasicAuthMiddleware; pub use crate::handlers::start_rest_apis; diff --git a/api/src/web.rs b/api/src/web.rs index 10eebcbb2..4d4a54ba5 100644 --- a/api/src/web.rs +++ b/api/src/web.rs @@ -5,7 +5,9 @@ use futures::{Future, Stream}; use hyper::{Body, Request, Response, StatusCode}; use serde::{Deserialize, Serialize}; use serde_json; +use std::collections::HashMap; use std::fmt::Debug; +use url::form_urlencoded; /// Parse request body pub fn parse_body(req: Request) -> Box + Send> @@ -81,3 +83,100 @@ pub fn just_response + Debug>(status: StatusCode, text: T) -> Resp pub fn response + Debug>(status: StatusCode, text: T) -> ResponseFuture { Box::new(ok(just_response(status, text))) } + +pub struct QueryParams { + params: HashMap>, +} + +impl QueryParams { + pub fn process_multival_param(&self, name: &str, mut f: F) + where + F: FnMut(&str), + { + if let Some(ids) = self.params.get(name) { + for id in ids { + for id in id.split(',') { + f(id); + } + } + } + } + + pub fn get(&self, name: &str) -> Option<&String> { + match self.params.get(name) { + None => None, + Some(v) => v.first(), + } + } +} + +impl From<&str> for QueryParams { + fn from(query_string: &str) -> Self { + let params = form_urlencoded::parse(query_string.as_bytes()) + .into_owned() + .fold(HashMap::new(), |mut hm, (k, v)| { + hm.entry(k).or_insert(vec![]).push(v); + hm + }); + QueryParams { params } + } +} + +impl From> for QueryParams { + fn from(query_string: Option<&str>) -> Self { + match query_string { + Some(query_string) => Self::from(query_string), + None => QueryParams { + params: HashMap::new(), + }, + } + } +} + +impl From> for QueryParams { + fn from(req: Request) -> Self { + Self::from(req.uri().query()) + } +} + +#[macro_export] +macro_rules! right_path_element( + ($req: expr) =>( + match $req.uri().path().trim_right_matches('/').rsplit('/').next() { + None => return response(StatusCode::BAD_REQUEST, "invalid url"), + Some(el) => el, + }; + )); + +#[macro_export] +macro_rules! must_get_query( + ($req: expr) =>( + match $req.uri().query() { + Some(q) => q, + None => return Err(ErrorKind::RequestError("no query string".to_owned()))?, + } + )); + +#[macro_export] +macro_rules! parse_param( + ($param: expr, $name: expr, $default: expr) =>( + match $param.get($name) { + None => $default, + Some(val) => match val.parse() { + Ok(val) => val, + Err(_) => return Err(ErrorKind::RequestError(format!("invalid value of parameter {}", $name)))?, + } + } + )); + +#[macro_export] +macro_rules! parse_param_no_err( + ($param: expr, $name: expr, $default: expr) =>( + match $param.get($name) { + None => $default, + Some(val) => match val.parse() { + Ok(val) => val, + Err(_) => $default, + } + } + )); diff --git a/servers/tests/api.rs b/servers/tests/api.rs index de856e82d..b2835911e 100644 --- a/servers/tests/api.rs +++ b/servers/tests/api.rs @@ -18,8 +18,7 @@ extern crate log; mod framework; use self::core::global::{self, ChainTypes}; -use self::util::init_test_logger; -use self::util::Mutex; +use self::util::{init_test_logger, to_hex, Mutex}; use crate::framework::{LocalServerContainer, LocalServerContainerConfig}; use grin_api as api; use grin_core as core; @@ -79,6 +78,7 @@ fn simple_server_wallet() { warn!("Testing chain handler"); let tip = get_tip(&base_addr, api_server_port); assert!(tip.is_ok()); + assert!(validate_chain(&base_addr, api_server_port).is_ok()); warn!("Testing status handler"); let status = get_status(&base_addr, api_server_port); @@ -94,17 +94,30 @@ fn simple_server_wallet() { warn!("Testing block handler"); let last_block_by_height = get_block_by_height(&base_addr, api_server_port, current_tip.height); assert!(last_block_by_height.is_ok()); + let block_hash = current_tip.last_block_pushed; let last_block_by_height_compact = get_block_by_height_compact(&base_addr, api_server_port, current_tip.height); assert!(last_block_by_height_compact.is_ok()); - let block_hash = current_tip.last_block_pushed; + let unspent_commit = get_unspent_output(&last_block_by_height.unwrap()).unwrap(); + let last_block_by_hash = get_block_by_hash(&base_addr, api_server_port, &block_hash); assert!(last_block_by_hash.is_ok()); let last_block_by_hash_compact = get_block_by_hash_compact(&base_addr, api_server_port, &block_hash); assert!(last_block_by_hash_compact.is_ok()); + warn!("Testing header handler"); + let last_header_by_height = + get_header_by_height(&base_addr, api_server_port, current_tip.height); + assert!(last_header_by_height.is_ok()); + + let last_header_by_hash = get_header_by_hash(&base_addr, api_server_port, &block_hash); + assert!(last_header_by_hash.is_ok()); + + let last_header_by_commit = get_header_by_commit(&base_addr, api_server_port, &unspent_commit); + assert!(last_header_by_commit.is_ok()); + warn!("Testing chain output handler"); let start_height = 0; let end_height = current_tip.height; @@ -286,6 +299,20 @@ fn get_block_by_hash( api::client::get::(url.as_str(), None).map_err(|e| Error::API(e)) } +fn get_header_by_commit( + base_addr: &String, + api_server_port: u16, + commit: &api::PrintableCommitment, +) -> Result { + let url = format!( + "http://{}:{}/v1/headers/{}", + base_addr, + api_server_port, + to_hex(commit.to_vec()) + ); + api::client::get::(url.as_str(), None).map_err(|e| Error::API(e)) +} + fn get_block_by_hash_compact( base_addr: &String, api_server_port: u16, @@ -298,6 +325,31 @@ fn get_block_by_hash_compact( api::client::get::(url.as_str(), None).map_err(|e| Error::API(e)) } +// Header handler functions +fn get_header_by_height( + base_addr: &String, + api_server_port: u16, + height: u64, +) -> Result { + let url = format!( + "http://{}:{}/v1/headers/{}", + base_addr, api_server_port, height + ); + api::client::get::(url.as_str(), None).map_err(|e| Error::API(e)) +} + +fn get_header_by_hash( + base_addr: &String, + api_server_port: u16, + header_hash: &String, +) -> Result { + let url = format!( + "http://{}:{}/v1/headers/{}", + base_addr, api_server_port, header_hash + ); + api::client::get::(url.as_str(), None).map_err(|e| Error::API(e)) +} + // Chain output handler functions fn get_outputs_by_ids1( base_addr: &String, @@ -343,6 +395,11 @@ fn get_outputs_by_height( api::client::get::>(url.as_str(), None).map_err(|e| Error::API(e)) } +fn validate_chain(base_addr: &String, api_server_port: u16) -> Result<(), Error> { + let url = format!("http://{}:{}/v1/chain/validate", base_addr, api_server_port); + api::client::get_no_ret(url.as_str(), None).map_err(|e| Error::API(e)) +} + // TxHashSet handler functions fn get_txhashset_roots(base_addr: &String, api_server_port: u16) -> Result { let url = format!( @@ -412,19 +469,6 @@ fn get_txhashset_lastkernels( api::client::get::>(url.as_str(), None).map_err(|e| Error::API(e)) } -// Helper function to get a vec of commitment output ids from a vec of block -// outputs -fn get_ids_from_block_outputs(block_outputs: Vec) -> Vec { - let mut ids: Vec = Vec::new(); - for block_output in block_outputs { - let outputs = &block_output.outputs; - for output in outputs { - ids.push(util::to_hex(output.clone().commit.0.to_vec())); - } - } - ids.into_iter().take(100).collect() -} - pub fn ban_peer(base_addr: &String, api_server_port: u16, peer_addr: &String) -> Result<(), Error> { let url = format!( "http://{}:{}/v1/peers/{}/ban", @@ -477,6 +521,27 @@ pub fn get_all_peers( api::client::get::>(url.as_str(), None).map_err(|e| Error::API(e)) } +// Helper function to get a vec of commitment output ids from a vec of block +// outputs +fn get_ids_from_block_outputs(block_outputs: Vec) -> Vec { + let mut ids: Vec = Vec::new(); + for block_output in block_outputs { + let outputs = &block_output.outputs; + for output in outputs { + ids.push(util::to_hex(output.clone().commit.0.to_vec())); + } + } + ids.into_iter().take(100).collect() +} + +fn get_unspent_output(block: &api::BlockPrintable) -> Option { + match block.outputs.iter().find(|o| !o.spent) { + None => None, + Some(output) => Some(api::PrintableCommitment { + commit: output.commit.clone(), + }), + } +} /// Error type wrapping underlying module errors. #[derive(Debug)] pub enum Error { From dc6542d82b04cbab65abfd3e986946f86267db44 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Fri, 15 Feb 2019 15:32:37 -0800 Subject: [PATCH 19/28] chore/docs: eliminate warnings (#2583) * chore: replace trim_right with $ sed -i'' 's/trim_right/trim_end/' **/*.rs * docs: individually document macros to avoid warning, add TODO to make to_edge hygenic * docs: document impl_array_newtype macros, refactor: move all impl_array_newtype macro traits into impl_array_netype_index --- api/src/web.rs | 2 +- core/src/pow/common.rs | 6 +++++- util/src/macros.rs | 25 ++++++++++++++----------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/api/src/web.rs b/api/src/web.rs index 4d4a54ba5..1bd296237 100644 --- a/api/src/web.rs +++ b/api/src/web.rs @@ -142,7 +142,7 @@ impl From> for QueryParams { #[macro_export] macro_rules! right_path_element( ($req: expr) =>( - match $req.uri().path().trim_right_matches('/').rsplit('/').next() { + match $req.uri().path().trim_end_matches('/').rsplit('/').next() { None => return response(StatusCode::BAD_REQUEST, "invalid url"), Some(el) => el, }; diff --git a/core/src/pow/common.rs b/core/src/pow/common.rs index f5513fed5..be8714c71 100644 --- a/core/src/pow/common.rs +++ b/core/src/pow/common.rs @@ -102,7 +102,7 @@ pub fn create_siphash_keys(header: &[u8]) -> Result<[u64; 4], Error> { ]) } -/// Macros to clean up integer unwrapping +/// Macro to clean up u64 unwrapping #[macro_export] macro_rules! to_u64 { ($n:expr) => { @@ -110,6 +110,7 @@ macro_rules! to_u64 { }; } +/// Macro to clean up u64 unwrapping as u32 #[macro_export] macro_rules! to_u32 { ($n:expr) => { @@ -117,6 +118,7 @@ macro_rules! to_u32 { }; } +/// Macro to clean up u64 unwrapping as usize #[macro_export] macro_rules! to_usize { ($n:expr) => { @@ -124,6 +126,8 @@ macro_rules! to_usize { }; } +/// Macro to clean up casting to edge type +/// TODO: this macro uses unhygenic data T #[macro_export] macro_rules! to_edge { ($n:expr) => { diff --git a/util/src/macros.rs b/util/src/macros.rs index 57d609528..77aeb793a 100644 --- a/util/src/macros.rs +++ b/util/src/macros.rs @@ -28,6 +28,7 @@ //! Macros to support Rust BIP-32 code (though could conceivably be used for other things) +/// gives a newtype array wrapper standard array traits #[macro_export] macro_rules! impl_array_newtype { ($thing:ident, $ty:ty, $len:expr) => { @@ -86,16 +87,6 @@ macro_rules! impl_array_newtype { } } - impl ::std::ops::Index for $thing { - type Output = $ty; - - #[inline] - fn index(&self, index: usize) -> &$ty { - let &$thing(ref dat) = self; - &dat[index] - } - } - impl_index_newtype!($thing, $ty); impl PartialEq for $thing { @@ -164,6 +155,7 @@ macro_rules! impl_array_newtype { }; } +/// gives a newtype array wrapper serialization and deserialization methods #[macro_export] macro_rules! impl_array_newtype_encodable { ($thing:ident, $ty:ty, $len:expr) => { @@ -193,7 +185,7 @@ macro_rules! impl_array_newtype_encodable { *item = match seq.next_element()? { Some(c) => c, None => { - return Err($crate::serde::de::Error::custom("end of stream")) + return Err($crate::serde::de::Error::custom("end of stream")); } }; } @@ -218,6 +210,7 @@ macro_rules! impl_array_newtype_encodable { }; } +/// gives a newtype array wrapper the Debug trait #[macro_export] macro_rules! impl_array_newtype_show { ($thing:ident) => { @@ -229,9 +222,19 @@ macro_rules! impl_array_newtype_show { }; } +/// gives a newtype array wrapper Index traits #[macro_export] macro_rules! impl_index_newtype { ($thing:ident, $ty:ty) => { + impl ::std::ops::Index for $thing { + type Output = $ty; + + #[inline] + fn index(&self, index: usize) -> &$ty { + let &$thing(ref dat) = self; + &dat[index] + } + } impl ::std::ops::Index<::std::ops::Range> for $thing { type Output = [$ty]; From 23cb9e25143b357a14122455cbe10d0f976e8295 Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Mon, 18 Feb 2019 12:15:32 +0000 Subject: [PATCH 20/28] Map peers by ip only (ignoring port unless on loopback ip) (#2540) * wip * big refactor, regretting doing this now * PeerAddr everywhere * cleanup * fixup server tests * peers api working for GET, POST is still WIP * we can now ban/unban peers by ip only (port optional) --- api/src/handlers/peers_api.rs | 42 +++-- .../{read_sock_addr.rs => read_peer_addr.rs} | 4 +- p2p/src/handshake.rs | 54 +++---- p2p/src/lib.rs | 4 +- p2p/src/msg.rs | 68 +-------- p2p/src/peer.rs | 34 ++--- p2p/src/peers.rs | 134 +++++++--------- p2p/src/protocol.rs | 17 +-- p2p/src/serv.rs | 48 +++--- p2p/src/store.rs | 43 ++---- p2p/src/types.rs | 143 +++++++++++++++--- p2p/tests/peer_handshake.rs | 5 +- servers/src/common/adapters.rs | 36 ++--- servers/src/grin/seed.rs | 78 ++++------ servers/src/grin/server.rs | 21 +-- servers/src/grin/sync/header_sync.rs | 2 +- servers/tests/framework.rs | 11 +- servers/tests/simulnet.rs | 9 +- src/bin/cmd/server.rs | 42 +---- 19 files changed, 373 insertions(+), 422 deletions(-) rename p2p/fuzz/fuzz_targets/{read_sock_addr.rs => read_peer_addr.rs} (65%) diff --git a/api/src/handlers/peers_api.rs b/api/src/handlers/peers_api.rs index 692245dbc..6453432fb 100644 --- a/api/src/handlers/peers_api.rs +++ b/api/src/handlers/peers_api.rs @@ -14,7 +14,7 @@ use super::utils::w; use crate::p2p; -use crate::p2p::types::{PeerInfoDisplay, ReasonForBan}; +use crate::p2p::types::{PeerAddr, PeerInfoDisplay, ReasonForBan}; use crate::router::{Handler, ResponseFuture}; use crate::web::*; use hyper::{Body, Request, StatusCode}; @@ -57,16 +57,25 @@ pub struct PeerHandler { impl Handler for PeerHandler { fn get(&self, req: Request) -> ResponseFuture { let command = right_path_element!(req); - if let Ok(addr) = command.parse() { - match w(&self.peers).get_peer(addr) { - Ok(peer) => json_response(&peer), - Err(_) => response(StatusCode::NOT_FOUND, "peer not found"), - } + + // We support both "ip" and "ip:port" here for peer_addr. + // "ip:port" is only really useful for local usernet testing on loopback address. + // Normally we map peers to ip and only allow a single peer per ip address. + let peer_addr; + if let Ok(ip_addr) = command.parse() { + peer_addr = PeerAddr::from_ip(ip_addr); + } else if let Ok(addr) = command.parse() { + peer_addr = PeerAddr(addr); } else { - response( + return response( StatusCode::BAD_REQUEST, format!("peer address unrecognized: {}", req.uri().path()), - ) + ); + } + + match w(&self.peers).get_peer(peer_addr) { + Ok(peer) => json_response(&peer), + Err(_) => response(StatusCode::NOT_FOUND, "peer not found"), } } fn post(&self, req: Request) -> ResponseFuture { @@ -77,20 +86,23 @@ impl Handler for PeerHandler { }; let addr = match path_elems.next() { None => return response(StatusCode::BAD_REQUEST, "invalid url"), - Some(a) => match a.parse() { - Err(e) => { + Some(a) => { + if let Ok(ip_addr) = a.parse() { + PeerAddr::from_ip(ip_addr) + } else if let Ok(addr) = a.parse() { + PeerAddr(addr) + } else { return response( StatusCode::BAD_REQUEST, - format!("invalid peer address: {}", e), + format!("invalid peer address: {}", req.uri().path()), ); } - Ok(addr) => addr, - }, + } }; match command { - "ban" => w(&self.peers).ban_peer(&addr, ReasonForBan::ManualBan), - "unban" => w(&self.peers).unban_peer(&addr), + "ban" => w(&self.peers).ban_peer(addr, ReasonForBan::ManualBan), + "unban" => w(&self.peers).unban_peer(addr), _ => return response(StatusCode::BAD_REQUEST, "invalid command"), }; diff --git a/p2p/fuzz/fuzz_targets/read_sock_addr.rs b/p2p/fuzz/fuzz_targets/read_peer_addr.rs similarity index 65% rename from p2p/fuzz/fuzz_targets/read_sock_addr.rs rename to p2p/fuzz/fuzz_targets/read_peer_addr.rs index cbe9a26ea..723634a1a 100644 --- a/p2p/fuzz/fuzz_targets/read_sock_addr.rs +++ b/p2p/fuzz/fuzz_targets/read_peer_addr.rs @@ -5,9 +5,9 @@ extern crate grin_core; extern crate grin_p2p; use grin_core::ser; -use grin_p2p::msg::SockAddr; +use grin_p2p::types::PeerAddr; fuzz_target!(|data: &[u8]| { let mut d = data.clone(); - let _t: Result = ser::deserialize(&mut d); + let _t: Result = ser::deserialize(&mut d); }); diff --git a/p2p/src/handshake.rs b/p2p/src/handshake.rs index cd0ea197a..dbb1b14da 100644 --- a/p2p/src/handshake.rs +++ b/p2p/src/handshake.rs @@ -22,11 +22,9 @@ use rand::{thread_rng, Rng}; use crate::core::core::hash::Hash; use crate::core::pow::Difficulty; -use crate::msg::{ - read_message, write_message, Hand, Shake, SockAddr, Type, PROTOCOL_VERSION, USER_AGENT, -}; +use crate::msg::{read_message, write_message, Hand, Shake, Type, PROTOCOL_VERSION, USER_AGENT}; use crate::peer::Peer; -use crate::types::{Capabilities, Direction, Error, P2PConfig, PeerInfo, PeerLiveInfo}; +use crate::types::{Capabilities, Direction, Error, P2PConfig, PeerAddr, PeerInfo, PeerLiveInfo}; /// Local generated nonce for peer connecting. /// Used for self-connecting detection (on receiver side), @@ -44,7 +42,7 @@ pub struct Handshake { /// a node id. nonces: Arc>>, /// Ring buffer of self addr(s) collected from PeerWithSelf detection (by nonce). - pub addrs: Arc>>, + pub addrs: Arc>>, /// The genesis block header of the chain seen by this node. /// We only want to connect to other nodes seeing the same chain (forks are /// ok). @@ -67,13 +65,13 @@ impl Handshake { &self, capab: Capabilities, total_difficulty: Difficulty, - self_addr: SocketAddr, + self_addr: PeerAddr, conn: &mut TcpStream, ) -> Result { // prepare the first part of the handshake let nonce = self.next_nonce(); let peer_addr = match conn.peer_addr() { - Ok(pa) => pa, + Ok(pa) => PeerAddr(pa), Err(e) => return Err(Error::Connection(e)), }; @@ -83,8 +81,8 @@ impl Handshake { nonce: nonce, genesis: self.genesis, total_difficulty: total_difficulty, - sender_addr: SockAddr(self_addr), - receiver_addr: SockAddr(peer_addr), + sender_addr: self_addr, + receiver_addr: peer_addr, user_agent: USER_AGENT.to_string(), }; @@ -118,7 +116,7 @@ impl Handshake { // If denied then we want to close the connection // (without providing our peer with any details why). - if Peer::is_denied(&self.config, &peer_info.addr) { + if Peer::is_denied(&self.config, peer_info.addr) { return Err(Error::ConnectionClose); } @@ -155,7 +153,7 @@ impl Handshake { } else { // check the nonce to see if we are trying to connect to ourselves let nonces = self.nonces.read(); - let addr = extract_ip(&hand.sender_addr.0, &conn); + let addr = resolve_peer_addr(hand.sender_addr, &conn); if nonces.contains(&hand.nonce) { // save ip addresses of ourselves let mut addrs = self.addrs.write(); @@ -171,7 +169,7 @@ impl Handshake { let peer_info = PeerInfo { capabilities: hand.capabilities, user_agent: hand.user_agent, - addr: extract_ip(&hand.sender_addr.0, &conn), + addr: resolve_peer_addr(hand.sender_addr, &conn), version: hand.version, live_info: Arc::new(RwLock::new(PeerLiveInfo { total_difficulty: hand.total_difficulty, @@ -186,7 +184,7 @@ impl Handshake { // so check if we are configured to explicitly allow or deny it. // If denied then we want to close the connection // (without providing our peer with any details why). - if Peer::is_denied(&self.config, &peer_info.addr) { + if Peer::is_denied(&self.config, peer_info.addr) { return Err(Error::ConnectionClose); } @@ -219,28 +217,12 @@ impl Handshake { } } -// Attempts to make a best guess at the correct remote IP by checking if the -// advertised address is the loopback and our TCP connection. Note that the -// port reported by the connection is always incorrect for receiving -// connections as it's dynamically allocated by the server. -fn extract_ip(advertised: &SocketAddr, conn: &TcpStream) -> SocketAddr { - match advertised { - &SocketAddr::V4(v4sock) => { - let ip = v4sock.ip(); - if ip.is_loopback() || ip.is_unspecified() { - if let Ok(addr) = conn.peer_addr() { - return SocketAddr::new(addr.ip(), advertised.port()); - } - } - } - &SocketAddr::V6(v6sock) => { - let ip = v6sock.ip(); - if ip.is_loopback() || ip.is_unspecified() { - if let Ok(addr) = conn.peer_addr() { - return SocketAddr::new(addr.ip(), advertised.port()); - } - } - } +/// Resolve the correct peer_addr based on the connection and the advertised port. +fn resolve_peer_addr(advertised: PeerAddr, conn: &TcpStream) -> PeerAddr { + let port = advertised.0.port(); + if let Ok(addr) = conn.peer_addr() { + PeerAddr(SocketAddr::new(addr.ip(), port)) + } else { + advertised } - advertised.clone() } diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 4f967b1fb..3ba530201 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -52,6 +52,6 @@ pub use crate::peers::Peers; pub use crate::serv::{DummyAdapter, Server}; pub use crate::store::{PeerData, State}; pub use crate::types::{ - Capabilities, ChainAdapter, Direction, Error, P2PConfig, PeerInfo, ReasonForBan, Seeding, - TxHashSetRead, MAX_BLOCK_HEADERS, MAX_LOCATORS, MAX_PEER_ADDRS, + Capabilities, ChainAdapter, Direction, Error, P2PConfig, PeerAddr, PeerInfo, ReasonForBan, + Seeding, TxHashSetRead, MAX_BLOCK_HEADERS, MAX_LOCATORS, MAX_PEER_ADDRS, }; diff --git a/p2p/src/msg.rs b/p2p/src/msg.rs index 3f9a6d733..8e7b5d151 100644 --- a/p2p/src/msg.rs +++ b/p2p/src/msg.rs @@ -16,7 +16,6 @@ use num::FromPrimitive; use std::io::{Read, Write}; -use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::time; use crate::core::core::hash::Hash; @@ -25,7 +24,7 @@ use crate::core::pow::Difficulty; use crate::core::ser::{self, FixedLength, Readable, Reader, StreamingReader, Writeable, Writer}; use crate::core::{consensus, global}; use crate::types::{ - Capabilities, Error, ReasonForBan, MAX_BLOCK_HEADERS, MAX_LOCATORS, MAX_PEER_ADDRS, + Capabilities, Error, PeerAddr, ReasonForBan, MAX_BLOCK_HEADERS, MAX_LOCATORS, MAX_PEER_ADDRS, }; use crate::util::read_write::read_exact; @@ -254,9 +253,9 @@ pub struct Hand { /// may be needed pub total_difficulty: Difficulty, /// network address of the sender - pub sender_addr: SockAddr, + pub sender_addr: PeerAddr, /// network address of the receiver - pub receiver_addr: SockAddr, + pub receiver_addr: PeerAddr, /// name of version of the software pub user_agent: String, } @@ -283,8 +282,8 @@ impl Readable for Hand { let (version, capab, nonce) = ser_multiread!(reader, read_u32, read_u32, read_u64); let capabilities = Capabilities::from_bits_truncate(capab); let total_diff = Difficulty::read(reader)?; - let sender_addr = SockAddr::read(reader)?; - let receiver_addr = SockAddr::read(reader)?; + let sender_addr = PeerAddr::read(reader)?; + let receiver_addr = PeerAddr::read(reader)?; let ua = reader.read_bytes_len_prefix()?; let user_agent = String::from_utf8(ua).map_err(|_| ser::Error::CorruptedData)?; let genesis = Hash::read(reader)?; @@ -373,7 +372,7 @@ impl Readable for GetPeerAddrs { /// GetPeerAddrs. #[derive(Debug)] pub struct PeerAddrs { - pub peers: Vec, + pub peers: Vec, } impl Writeable for PeerAddrs { @@ -394,10 +393,9 @@ impl Readable for PeerAddrs { } else if peer_count == 0 { return Ok(PeerAddrs { peers: vec![] }); } - // let peers = try_map_vec!([0..peer_count], |_| SockAddr::read(reader)); let mut peers = Vec::with_capacity(peer_count as usize); for _ in 0..peer_count { - peers.push(SockAddr::read(reader)?); + peers.push(PeerAddr::read(reader)?); } Ok(PeerAddrs { peers: peers }) } @@ -431,58 +429,6 @@ impl Readable for PeerError { } } -/// Only necessary so we can implement Readable and Writeable. Rust disallows -/// implementing traits when both types are outside of this crate (which is the -/// case for SocketAddr and Readable/Writeable). -#[derive(Debug)] -pub struct SockAddr(pub SocketAddr); - -impl Writeable for SockAddr { - fn write(&self, writer: &mut W) -> Result<(), ser::Error> { - match self.0 { - SocketAddr::V4(sav4) => { - ser_multiwrite!( - writer, - [write_u8, 0], - [write_fixed_bytes, &sav4.ip().octets().to_vec()], - [write_u16, sav4.port()] - ); - } - SocketAddr::V6(sav6) => { - writer.write_u8(1)?; - for seg in &sav6.ip().segments() { - writer.write_u16(*seg)?; - } - writer.write_u16(sav6.port())?; - } - } - Ok(()) - } -} - -impl Readable for SockAddr { - fn read(reader: &mut dyn Reader) -> Result { - let v4_or_v6 = reader.read_u8()?; - if v4_or_v6 == 0 { - let ip = reader.read_fixed_bytes(4)?; - let port = reader.read_u16()?; - Ok(SockAddr(SocketAddr::V4(SocketAddrV4::new( - Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]), - port, - )))) - } else { - let ip = try_iter_map_vec!(0..8, |_| reader.read_u16()); - let port = reader.read_u16()?; - Ok(SockAddr(SocketAddr::V6(SocketAddrV6::new( - Ipv6Addr::new(ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]), - port, - 0, - 0, - )))) - } - } -} - /// Serializable wrapper for the block locator. #[derive(Debug)] pub struct Locator { diff --git a/p2p/src/peer.rs b/p2p/src/peer.rs index eecae9b25..1b50bf59a 100644 --- a/p2p/src/peer.rs +++ b/p2p/src/peer.rs @@ -14,7 +14,7 @@ use crate::util::{Mutex, RwLock}; use std::fs::File; -use std::net::{Shutdown, SocketAddr, TcpStream}; +use std::net::{Shutdown, TcpStream}; use std::sync::Arc; use crate::conn; @@ -25,7 +25,8 @@ use crate::handshake::Handshake; use crate::msg::{self, BanReason, GetPeerAddrs, Locator, Ping, TxHashSetRequest}; use crate::protocol::Protocol; use crate::types::{ - Capabilities, ChainAdapter, Error, NetAdapter, P2PConfig, PeerInfo, ReasonForBan, TxHashSetRead, + Capabilities, ChainAdapter, Error, NetAdapter, P2PConfig, PeerAddr, PeerInfo, ReasonForBan, + TxHashSetRead, }; use chrono::prelude::{DateTime, Utc}; @@ -93,7 +94,7 @@ impl Peer { conn: &mut TcpStream, capab: Capabilities, total_difficulty: Difficulty, - self_addr: SocketAddr, + self_addr: PeerAddr, hs: &Handshake, na: Arc, ) -> Result { @@ -124,10 +125,9 @@ impl Peer { self.connection = Some(Mutex::new(conn::listen(conn, handler))); } - pub fn is_denied(config: &P2PConfig, peer_addr: &SocketAddr) -> bool { - let peer = format!("{}:{}", peer_addr.ip(), peer_addr.port()); + pub fn is_denied(config: &P2PConfig, peer_addr: PeerAddr) -> bool { if let Some(ref denied) = config.peers_deny { - if denied.contains(&peer) { + if denied.contains(&peer_addr) { debug!( "checking peer allowed/denied: {:?} explicitly denied", peer_addr @@ -136,7 +136,7 @@ impl Peer { } } if let Some(ref allowed) = config.peers_allow { - if allowed.contains(&peer) { + if allowed.contains(&peer_addr) { debug!( "checking peer allowed/denied: {:?} explicitly allowed", peer_addr @@ -566,7 +566,7 @@ impl ChainAdapter for TrackingAdapter { self.adapter.get_transaction(kernel_hash) } - fn tx_kernel_received(&self, kernel_hash: Hash, addr: SocketAddr) { + fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) { self.push_recv(kernel_hash); self.adapter.tx_kernel_received(kernel_hash, addr) } @@ -582,23 +582,23 @@ impl ChainAdapter for TrackingAdapter { self.adapter.transaction_received(tx, stem) } - fn block_received(&self, b: core::Block, addr: SocketAddr, _was_requested: bool) -> bool { + fn block_received(&self, b: core::Block, addr: PeerAddr, _was_requested: bool) -> bool { let bh = b.hash(); self.push_recv(bh); self.adapter.block_received(b, addr, self.has_req(bh)) } - fn compact_block_received(&self, cb: core::CompactBlock, addr: SocketAddr) -> bool { + fn compact_block_received(&self, cb: core::CompactBlock, addr: PeerAddr) -> bool { self.push_recv(cb.hash()); self.adapter.compact_block_received(cb, addr) } - fn header_received(&self, bh: core::BlockHeader, addr: SocketAddr) -> bool { + fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> bool { self.push_recv(bh.hash()); self.adapter.header_received(bh, addr) } - fn headers_received(&self, bh: &[core::BlockHeader], addr: SocketAddr) -> bool { + fn headers_received(&self, bh: &[core::BlockHeader], addr: PeerAddr) -> bool { self.adapter.headers_received(bh, addr) } @@ -618,7 +618,7 @@ impl ChainAdapter for TrackingAdapter { self.adapter.txhashset_receive_ready() } - fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: SocketAddr) -> bool { + fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: PeerAddr) -> bool { self.adapter.txhashset_write(h, txhashset_data, peer_addr) } @@ -634,19 +634,19 @@ impl ChainAdapter for TrackingAdapter { } impl NetAdapter for TrackingAdapter { - fn find_peer_addrs(&self, capab: Capabilities) -> Vec { + fn find_peer_addrs(&self, capab: Capabilities) -> Vec { self.adapter.find_peer_addrs(capab) } - fn peer_addrs_received(&self, addrs: Vec) { + fn peer_addrs_received(&self, addrs: Vec) { self.adapter.peer_addrs_received(addrs) } - fn peer_difficulty(&self, addr: SocketAddr, diff: Difficulty, height: u64) { + fn peer_difficulty(&self, addr: PeerAddr, diff: Difficulty, height: u64) { self.adapter.peer_difficulty(addr, diff, height) } - fn is_banned(&self, addr: SocketAddr) -> bool { + fn is_banned(&self, addr: PeerAddr) -> bool { self.adapter.is_banned(addr) } } diff --git a/p2p/src/peers.rs b/p2p/src/peers.rs index f60abbc4c..19713b7d8 100644 --- a/p2p/src/peers.rs +++ b/p2p/src/peers.rs @@ -15,7 +15,6 @@ use crate::util::RwLock; use std::collections::HashMap; use std::fs::File; -use std::net::SocketAddr; use std::sync::Arc; use rand::{thread_rng, Rng}; @@ -30,14 +29,14 @@ use chrono::Duration; use crate::peer::Peer; use crate::store::{PeerData, PeerStore, State}; use crate::types::{ - Capabilities, ChainAdapter, Direction, Error, NetAdapter, P2PConfig, ReasonForBan, + Capabilities, ChainAdapter, Direction, Error, NetAdapter, P2PConfig, PeerAddr, ReasonForBan, TxHashSetRead, MAX_PEER_ADDRS, }; pub struct Peers { pub adapter: Arc, store: PeerStore, - peers: RwLock>>, + peers: RwLock>>, dandelion_relay: RwLock)>>, config: P2PConfig, } @@ -56,33 +55,25 @@ impl Peers { /// Adds the peer to our internal peer mapping. Note that the peer is still /// returned so the server can run it. pub fn add_connected(&self, peer: Arc) -> Result<(), Error> { - let peer_data: PeerData; - let addr: SocketAddr; - { - peer_data = PeerData { - addr: peer.info.addr, - capabilities: peer.info.capabilities, - user_agent: peer.info.user_agent.clone(), - flags: State::Healthy, - last_banned: 0, - ban_reason: ReasonForBan::None, - last_connected: Utc::now().timestamp(), - }; - addr = peer.info.addr.clone(); - } - debug!("Saving newly connected peer {}.", addr); + let peer_data = PeerData { + addr: peer.info.addr, + capabilities: peer.info.capabilities, + user_agent: peer.info.user_agent.clone(), + flags: State::Healthy, + last_banned: 0, + ban_reason: ReasonForBan::None, + last_connected: Utc::now().timestamp(), + }; + debug!("Saving newly connected peer {}.", peer_data.addr); self.save_peer(&peer_data)?; + self.peers.write().insert(peer_data.addr, peer.clone()); - { - let mut peers = self.peers.write(); - peers.insert(addr, peer.clone()); - } Ok(()) } /// Add a peer as banned to block future connections, usually due to failed /// handshake - pub fn add_banned(&self, addr: SocketAddr, ban_reason: ReasonForBan) -> Result<(), Error> { + pub fn add_banned(&self, addr: PeerAddr, ban_reason: ReasonForBan) -> Result<(), Error> { let peer_data = PeerData { addr, capabilities: Capabilities::UNKNOWN, @@ -129,18 +120,8 @@ impl Peers { self.dandelion_relay.read().clone() } - pub fn is_known(&self, addr: &SocketAddr) -> bool { - self.peers.read().contains_key(addr) - } - - /// Check whether an ip address is in the active peers list, ignore the port - pub fn is_known_ip(&self, addr: &SocketAddr) -> bool { - for socket in self.peers.read().keys() { - if addr.ip() == socket.ip() { - return true; - } - } - return false; + pub fn is_known(&self, addr: PeerAddr) -> bool { + self.peers.read().contains_key(&addr) } /// Get vec of peers we are currently connected to. @@ -166,8 +147,8 @@ impl Peers { } /// Get a peer we're connected to by address. - pub fn get_connected_peer(&self, addr: &SocketAddr) -> Option> { - self.peers.read().get(addr).map(|p| p.clone()) + pub fn get_connected_peer(&self, addr: PeerAddr) -> Option> { + self.peers.read().get(&addr).map(|p| p.clone()) } /// Number of peers currently connected to. @@ -257,31 +238,18 @@ impl Peers { self.most_work_peers().pop() } - pub fn is_banned(&self, peer_addr: SocketAddr) -> bool { - if global::is_production_mode() { - // Ban only cares about ip address, no mather what port. - // so, we query all saved peers with one same ip address, and ignore port - let peers_data = self.store.find_peers_by_ip(peer_addr); - for peer_data in peers_data { - if peer_data.flags == State::Banned { - return true; - } - } - } else { - // For travis-ci test, we need run multiple nodes in one server, with same ip address. - // so, just query the ip address and the port - if let Ok(peer_data) = self.store.get_peer(peer_addr) { - if peer_data.flags == State::Banned { - return true; - } + pub fn is_banned(&self, peer_addr: PeerAddr) -> bool { + if let Ok(peer) = self.store.get_peer(peer_addr) { + if peer.flags == State::Banned { + return true; } } false } /// Ban a peer, disconnecting it if we're currently connected - pub fn ban_peer(&self, peer_addr: &SocketAddr, ban_reason: ReasonForBan) { - if let Err(e) = self.update_state(*peer_addr, State::Banned) { + pub fn ban_peer(&self, peer_addr: PeerAddr, ban_reason: ReasonForBan) { + if let Err(e) = self.update_state(peer_addr, State::Banned) { error!("Couldn't ban {}: {:?}", peer_addr, e); } @@ -295,12 +263,12 @@ impl Peers { } /// Unban a peer, checks if it exists and banned then unban - pub fn unban_peer(&self, peer_addr: &SocketAddr) { + pub fn unban_peer(&self, peer_addr: PeerAddr) { debug!("unban_peer: peer {}", peer_addr); - match self.get_peer(*peer_addr) { + match self.get_peer(peer_addr) { Ok(_) => { - if self.is_banned(*peer_addr) { - if let Err(e) = self.update_state(*peer_addr, State::Healthy) { + if self.is_banned(peer_addr) { + if let Err(e) = self.update_state(peer_addr, State::Healthy) { error!("Couldn't unban {}: {:?}", peer_addr, e); } } else { @@ -424,12 +392,12 @@ impl Peers { } /// Get peer in store by address - pub fn get_peer(&self, peer_addr: SocketAddr) -> Result { + pub fn get_peer(&self, peer_addr: PeerAddr) -> Result { self.store.get_peer(peer_addr).map_err(From::from) } /// Whether we've already seen a peer with the provided address - pub fn exists_peer(&self, peer_addr: SocketAddr) -> Result { + pub fn exists_peer(&self, peer_addr: PeerAddr) -> Result { self.store.exists_peer(peer_addr).map_err(From::from) } @@ -439,7 +407,7 @@ impl Peers { } /// Updates the state of a peer in store - pub fn update_state(&self, peer_addr: SocketAddr, new_state: State) -> Result<(), Error> { + pub fn update_state(&self, peer_addr: PeerAddr, new_state: State) -> Result<(), Error> { self.store .update_state(peer_addr, new_state) .map_err(From::from) @@ -495,9 +463,9 @@ impl Peers { // now clean up peer map based on the list to remove { let mut peers = self.peers.write(); - for p in rm { - let _ = peers.get(&p).map(|p| p.stop()); - peers.remove(&p); + for addr in rm { + let _ = peers.get(&addr).map(|peer| peer.stop()); + peers.remove(&addr); } } } @@ -558,7 +526,7 @@ impl ChainAdapter for Peers { self.adapter.get_transaction(kernel_hash) } - fn tx_kernel_received(&self, kernel_hash: Hash, addr: SocketAddr) { + fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) { self.adapter.tx_kernel_received(kernel_hash, addr) } @@ -566,7 +534,7 @@ impl ChainAdapter for Peers { self.adapter.transaction_received(tx, stem) } - fn block_received(&self, b: core::Block, peer_addr: SocketAddr, was_requested: bool) -> bool { + fn block_received(&self, b: core::Block, peer_addr: PeerAddr, was_requested: bool) -> bool { let hash = b.hash(); if !self.adapter.block_received(b, peer_addr, was_requested) { // if the peer sent us a block that's intrinsically bad @@ -575,45 +543,45 @@ impl ChainAdapter for Peers { "Received a bad block {} from {}, the peer will be banned", hash, peer_addr ); - self.ban_peer(&peer_addr, ReasonForBan::BadBlock); + self.ban_peer(peer_addr, ReasonForBan::BadBlock); false } else { true } } - fn compact_block_received(&self, cb: core::CompactBlock, peer_addr: SocketAddr) -> bool { + fn compact_block_received(&self, cb: core::CompactBlock, peer_addr: PeerAddr) -> bool { let hash = cb.hash(); if !self.adapter.compact_block_received(cb, peer_addr) { // if the peer sent us a block that's intrinsically bad // they are either mistaken or malevolent, both of which require a ban debug!( "Received a bad compact block {} from {}, the peer will be banned", - hash, &peer_addr + hash, peer_addr ); - self.ban_peer(&peer_addr, ReasonForBan::BadCompactBlock); + self.ban_peer(peer_addr, ReasonForBan::BadCompactBlock); false } else { true } } - fn header_received(&self, bh: core::BlockHeader, peer_addr: SocketAddr) -> bool { + fn header_received(&self, bh: core::BlockHeader, peer_addr: PeerAddr) -> bool { if !self.adapter.header_received(bh, peer_addr) { // if the peer sent us a block header that's intrinsically bad // they are either mistaken or malevolent, both of which require a ban - self.ban_peer(&peer_addr, ReasonForBan::BadBlockHeader); + self.ban_peer(peer_addr, ReasonForBan::BadBlockHeader); false } else { true } } - fn headers_received(&self, headers: &[core::BlockHeader], peer_addr: SocketAddr) -> bool { + fn headers_received(&self, headers: &[core::BlockHeader], peer_addr: PeerAddr) -> bool { if !self.adapter.headers_received(headers, peer_addr) { // if the peer sent us a block header that's intrinsically bad // they are either mistaken or malevolent, both of which require a ban - self.ban_peer(&peer_addr, ReasonForBan::BadBlockHeader); + self.ban_peer(peer_addr, ReasonForBan::BadBlockHeader); false } else { true @@ -636,13 +604,13 @@ impl ChainAdapter for Peers { self.adapter.txhashset_receive_ready() } - fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: SocketAddr) -> bool { + fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: PeerAddr) -> bool { if !self.adapter.txhashset_write(h, txhashset_data, peer_addr) { debug!( "Received a bad txhashset data from {}, the peer will be banned", &peer_addr ); - self.ban_peer(&peer_addr, ReasonForBan::BadTxHashSet); + self.ban_peer(peer_addr, ReasonForBan::BadTxHashSet); false } else { true @@ -663,14 +631,14 @@ impl ChainAdapter for Peers { impl NetAdapter for Peers { /// Find good peers we know with the provided capability and return their /// addresses. - fn find_peer_addrs(&self, capab: Capabilities) -> Vec { + fn find_peer_addrs(&self, capab: Capabilities) -> Vec { let peers = self.find_peers(State::Healthy, capab, MAX_PEER_ADDRS as usize); trace!("find_peer_addrs: {} healthy peers picked", peers.len()); map_vec!(peers, |p| p.addr) } /// A list of peers has been received from one of our peers. - fn peer_addrs_received(&self, peer_addrs: Vec) { + fn peer_addrs_received(&self, peer_addrs: Vec) { trace!("Received {} peer addrs, saving.", peer_addrs.len()); for pa in peer_addrs { if let Ok(e) = self.exists_peer(pa) { @@ -693,13 +661,13 @@ impl NetAdapter for Peers { } } - fn peer_difficulty(&self, addr: SocketAddr, diff: Difficulty, height: u64) { - if let Some(peer) = self.get_connected_peer(&addr) { + fn peer_difficulty(&self, addr: PeerAddr, diff: Difficulty, height: u64) { + if let Some(peer) = self.get_connected_peer(addr) { peer.info.update(height, diff); } } - fn is_banned(&self, addr: SocketAddr) -> bool { + fn is_banned(&self, addr: PeerAddr) -> bool { if let Ok(peer) = self.get_peer(addr) { peer.flags == State::Banned } else { diff --git a/p2p/src/protocol.rs b/p2p/src/protocol.rs index b4dd4b5f9..38df07c75 100644 --- a/p2p/src/protocol.rs +++ b/p2p/src/protocol.rs @@ -16,7 +16,6 @@ use std::cmp; use std::env; use std::fs::File; use std::io::{BufWriter, Write}; -use std::net::SocketAddr; use std::sync::Arc; use crate::conn::{Message, MessageHandler, Response}; @@ -25,18 +24,18 @@ use crate::util::{RateCounter, RwLock}; use chrono::prelude::Utc; use crate::msg::{ - BanReason, GetPeerAddrs, Headers, Locator, PeerAddrs, Ping, Pong, SockAddr, TxHashSetArchive, + BanReason, GetPeerAddrs, Headers, Locator, PeerAddrs, Ping, Pong, TxHashSetArchive, TxHashSetRequest, Type, }; -use crate::types::{Error, NetAdapter}; +use crate::types::{Error, NetAdapter, PeerAddr}; pub struct Protocol { adapter: Arc, - addr: SocketAddr, + addr: PeerAddr, } impl Protocol { - pub fn new(adapter: Arc, addr: SocketAddr) -> Protocol { + pub fn new(adapter: Arc, addr: PeerAddr) -> Protocol { Protocol { adapter, addr } } } @@ -231,19 +230,17 @@ impl MessageHandler for Protocol { Type::GetPeerAddrs => { let get_peers: GetPeerAddrs = msg.body()?; - let peer_addrs = adapter.find_peer_addrs(get_peers.capabilities); + let peers = adapter.find_peer_addrs(get_peers.capabilities); Ok(Some(Response::new( Type::PeerAddrs, - PeerAddrs { - peers: peer_addrs.iter().map(|sa| SockAddr(*sa)).collect(), - }, + PeerAddrs { peers }, writer, ))) } Type::PeerAddrs => { let peer_addrs: PeerAddrs = msg.body()?; - adapter.peer_addrs_received(peer_addrs.peers.iter().map(|pa| pa.0).collect()); + adapter.peer_addrs_received(peer_addrs.peers); Ok(None) } diff --git a/p2p/src/serv.rs b/p2p/src/serv.rs index 45fc38354..8be990846 100644 --- a/p2p/src/serv.rs +++ b/p2p/src/serv.rs @@ -29,7 +29,7 @@ use crate::peer::Peer; use crate::peers::Peers; use crate::store::PeerStore; use crate::types::{ - Capabilities, ChainAdapter, Error, NetAdapter, P2PConfig, ReasonForBan, Seeding, TxHashSetRead, + Capabilities, ChainAdapter, Error, NetAdapter, P2PConfig, PeerAddr, ReasonForBan, TxHashSetRead, }; use crate::util::{Mutex, StopState}; use chrono::prelude::{DateTime, Utc}; @@ -82,6 +82,8 @@ impl Server { match listener.accept() { Ok((stream, peer_addr)) => { + let peer_addr = PeerAddr(peer_addr); + if self.check_undesirable(&stream) { continue; } @@ -107,8 +109,8 @@ impl Server { /// Asks the server to connect to a new peer. Directly returns the peer if /// we're already connected to the provided address. - pub fn connect(&self, addr: &SocketAddr) -> Result, Error> { - if Peer::is_denied(&self.config, &addr) { + pub fn connect(&self, addr: PeerAddr) -> Result, Error> { + if Peer::is_denied(&self.config, addr) { debug!("connect_peer: peer {} denied, not connecting.", addr); return Err(Error::ConnectionClose); } @@ -134,7 +136,7 @@ impl Server { self.config.port, addr ); - match TcpStream::connect_timeout(addr, Duration::from_secs(10)) { + match TcpStream::connect_timeout(&addr.0, Duration::from_secs(10)) { Ok(mut stream) => { let addr = SocketAddr::new(self.config.host, self.config.port); let total_diff = self.peers.total_difficulty(); @@ -143,7 +145,7 @@ impl Server { &mut stream, self.capabilities, total_diff, - addr, + PeerAddr(addr), &self.handshake, self.peers.clone(), )?; @@ -191,13 +193,17 @@ impl Server { /// different sets of peers themselves. In addition, it prevent potential /// duplicate connections, malicious or not. fn check_undesirable(&self, stream: &TcpStream) -> bool { - // peer has been banned, go away! if let Ok(peer_addr) = stream.peer_addr() { - let banned = self.peers.is_banned(peer_addr); - let known_ip = - self.peers.is_known_ip(&peer_addr) && self.config.seeding_type == Seeding::DNSSeed; - if banned || known_ip { - debug!("Peer {} banned or known, refusing connection.", peer_addr); + let peer_addr = PeerAddr(peer_addr); + if self.peers.is_banned(peer_addr) { + debug!("Peer {} banned, refusing connection.", peer_addr); + if let Err(e) = stream.shutdown(Shutdown::Both) { + debug!("Error shutting down conn: {:?}", e); + } + return true; + } + if self.peers.is_known(peer_addr) { + debug!("Peer {} already known, refusing connection.", peer_addr); if let Err(e) = stream.shutdown(Shutdown::Both) { debug!("Error shutting down conn: {:?}", e); } @@ -234,18 +240,18 @@ impl ChainAdapter for DummyAdapter { fn get_transaction(&self, _h: Hash) -> Option { None } - fn tx_kernel_received(&self, _h: Hash, _addr: SocketAddr) {} + fn tx_kernel_received(&self, _h: Hash, _addr: PeerAddr) {} fn transaction_received(&self, _: core::Transaction, _stem: bool) {} - fn compact_block_received(&self, _cb: core::CompactBlock, _addr: SocketAddr) -> bool { + fn compact_block_received(&self, _cb: core::CompactBlock, _addr: PeerAddr) -> bool { true } - fn header_received(&self, _bh: core::BlockHeader, _addr: SocketAddr) -> bool { + fn header_received(&self, _bh: core::BlockHeader, _addr: PeerAddr) -> bool { true } - fn block_received(&self, _: core::Block, _: SocketAddr, _: bool) -> bool { + fn block_received(&self, _: core::Block, _: PeerAddr, _: bool) -> bool { true } - fn headers_received(&self, _: &[core::BlockHeader], _: SocketAddr) -> bool { + fn headers_received(&self, _: &[core::BlockHeader], _: PeerAddr) -> bool { true } fn locate_headers(&self, _: &[Hash]) -> Vec { @@ -262,7 +268,7 @@ impl ChainAdapter for DummyAdapter { false } - fn txhashset_write(&self, _h: Hash, _txhashset_data: File, _peer_addr: SocketAddr) -> bool { + fn txhashset_write(&self, _h: Hash, _txhashset_data: File, _peer_addr: PeerAddr) -> bool { false } @@ -277,12 +283,12 @@ impl ChainAdapter for DummyAdapter { } impl NetAdapter for DummyAdapter { - fn find_peer_addrs(&self, _: Capabilities) -> Vec { + fn find_peer_addrs(&self, _: Capabilities) -> Vec { vec![] } - fn peer_addrs_received(&self, _: Vec) {} - fn peer_difficulty(&self, _: SocketAddr, _: Difficulty, _: u64) {} - fn is_banned(&self, _: SocketAddr) -> bool { + fn peer_addrs_received(&self, _: Vec) {} + fn peer_difficulty(&self, _: PeerAddr, _: Difficulty, _: u64) {} + fn is_banned(&self, _: PeerAddr) -> bool { false } } diff --git a/p2p/src/store.rs b/p2p/src/store.rs index 921070706..074cc066f 100644 --- a/p2p/src/store.rs +++ b/p2p/src/store.rs @@ -17,19 +17,17 @@ use chrono::Utc; use num::FromPrimitive; use rand::{thread_rng, Rng}; -use std::net::SocketAddr; use std::sync::Arc; use crate::lmdb; use crate::core::ser::{self, Readable, Reader, Writeable, Writer}; -use crate::msg::SockAddr; -use crate::types::{Capabilities, ReasonForBan}; +use crate::types::{Capabilities, PeerAddr, ReasonForBan}; use grin_store::{self, option_to_not_found, to_key, Error}; const STORE_SUBPATH: &'static str = "peers"; -const PEER_PREFIX: u8 = 'p' as u8; +const PEER_PREFIX: u8 = 'P' as u8; /// Types of messages enum_from_primitive! { @@ -45,7 +43,7 @@ enum_from_primitive! { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PeerData { /// Network address of the peer. - pub addr: SocketAddr, + pub addr: PeerAddr, /// What capabilities the peer advertises. Unknown until a successful /// connection. pub capabilities: Capabilities, @@ -63,7 +61,7 @@ pub struct PeerData { impl Writeable for PeerData { fn write(&self, writer: &mut W) -> Result<(), ser::Error> { - SockAddr(self.addr).write(writer)?; + self.addr.write(writer)?; ser_multiwrite!( writer, [write_u32, self.capabilities.bits()], @@ -79,7 +77,7 @@ impl Writeable for PeerData { impl Readable for PeerData { fn read(reader: &mut dyn Reader) -> Result { - let addr = SockAddr::read(reader)?; + let addr = PeerAddr::read(reader)?; let capab = reader.read_u32()?; let ua = reader.read_bytes_len_prefix()?; let (fl, lb, br) = ser_multiread!(reader, read_u8, read_i64, read_i32); @@ -99,7 +97,7 @@ impl Readable for PeerData { match State::from_u8(fl) { Some(flags) => Ok(PeerData { - addr: addr.0, + addr, capabilities, user_agent, flags: flags, @@ -132,20 +130,20 @@ impl PeerStore { batch.commit() } - pub fn get_peer(&self, peer_addr: SocketAddr) -> Result { + pub fn get_peer(&self, peer_addr: PeerAddr) -> Result { option_to_not_found( self.db.get_ser(&peer_key(peer_addr)[..]), &format!("Peer at address: {}", peer_addr), ) } - pub fn exists_peer(&self, peer_addr: SocketAddr) -> Result { + pub fn exists_peer(&self, peer_addr: PeerAddr) -> Result { self.db.exists(&peer_key(peer_addr)[..]) } /// TODO - allow below added to avoid github issue reports #[allow(dead_code)] - pub fn delete_peer(&self, peer_addr: SocketAddr) -> Result<(), Error> { + pub fn delete_peer(&self, peer_addr: PeerAddr) -> Result<(), Error> { let batch = self.db.batch()?; batch.delete(&peer_key(peer_addr)[..])?; batch.commit() @@ -162,17 +160,6 @@ impl PeerStore { peers.iter().take(count).cloned().collect() } - /// Query all peers with same IP address, and ignore the port - pub fn find_peers_by_ip(&self, peer_addr: SocketAddr) -> Vec { - self.db - .iter::(&to_key( - PEER_PREFIX, - &mut format!("{}", peer_addr.ip()).into_bytes(), - )) - .unwrap() - .collect::>() - } - /// List all known peers /// Used for /v1/peers/all api endpoint pub fn all_peers(&self) -> Vec { @@ -182,7 +169,7 @@ impl PeerStore { /// Convenience method to load a peer data, update its status and save it /// back. If new state is Banned its last banned time will be updated too. - pub fn update_state(&self, peer_addr: SocketAddr, new_state: State) -> Result<(), Error> { + pub fn update_state(&self, peer_addr: PeerAddr, new_state: State) -> Result<(), Error> { let batch = self.db.batch()?; let mut peer = option_to_not_found( @@ -194,7 +181,7 @@ impl PeerStore { peer.last_banned = Utc::now().timestamp(); } - batch.put_ser(&peer_key(peer.addr)[..], &peer)?; + batch.put_ser(&peer_key(peer_addr)[..], &peer)?; batch.commit() } @@ -226,9 +213,7 @@ impl PeerStore { } } -fn peer_key(peer_addr: SocketAddr) -> Vec { - to_key( - PEER_PREFIX, - &mut format!("{}:{}", peer_addr.ip(), peer_addr.port()).into_bytes(), - ) +// Ignore the port unless ip is loopback address. +fn peer_key(peer_addr: PeerAddr) -> Vec { + to_key(PEER_PREFIX, &mut peer_addr.as_key().into_bytes()) } diff --git a/p2p/src/types.rs b/p2p/src/types.rs index 60c6eef5c..c6cffefdd 100644 --- a/p2p/src/types.rs +++ b/p2p/src/types.rs @@ -16,15 +16,18 @@ use crate::util::RwLock; use std::convert::From; use std::fs::File; use std::io; -use std::net::{IpAddr, SocketAddr}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; + use std::sync::mpsc; use std::sync::Arc; use chrono::prelude::*; +use crate::core::core; use crate::core::core::hash::Hash; +use crate::core::global; use crate::core::pow::Difficulty; -use crate::core::{core, ser}; +use crate::core::ser::{self, Readable, Reader, Writeable, Writer}; use grin_store; /// Maximum number of block headers a peer should ever send @@ -95,6 +98,106 @@ impl From> for Error { } } +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub struct PeerAddr(pub SocketAddr); + +impl Writeable for PeerAddr { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { + match self.0 { + SocketAddr::V4(sav4) => { + ser_multiwrite!( + writer, + [write_u8, 0], + [write_fixed_bytes, &sav4.ip().octets().to_vec()], + [write_u16, sav4.port()] + ); + } + SocketAddr::V6(sav6) => { + writer.write_u8(1)?; + for seg in &sav6.ip().segments() { + writer.write_u16(*seg)?; + } + writer.write_u16(sav6.port())?; + } + } + Ok(()) + } +} + +impl Readable for PeerAddr { + fn read(reader: &mut dyn Reader) -> Result { + let v4_or_v6 = reader.read_u8()?; + if v4_or_v6 == 0 { + let ip = reader.read_fixed_bytes(4)?; + let port = reader.read_u16()?; + Ok(PeerAddr(SocketAddr::V4(SocketAddrV4::new( + Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]), + port, + )))) + } else { + let ip = try_iter_map_vec!(0..8, |_| reader.read_u16()); + let port = reader.read_u16()?; + Ok(PeerAddr(SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::new(ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]), + port, + 0, + 0, + )))) + } + } +} + +impl std::hash::Hash for PeerAddr { + /// If loopback address then we care about ip and port. + /// If regular address then we only care about the ip and ignore the port. + fn hash(&self, state: &mut H) { + if self.0.ip().is_loopback() { + self.0.hash(state); + } else { + self.0.ip().hash(state); + } + } +} + +impl PartialEq for PeerAddr { + /// If loopback address then we care about ip and port. + /// If regular address then we only care about the ip and ignore the port. + fn eq(&self, other: &PeerAddr) -> bool { + if self.0.ip().is_loopback() { + self.0 == other.0 + } else { + self.0.ip() == other.0.ip() + } + } +} + +impl Eq for PeerAddr {} + +impl std::fmt::Display for PeerAddr { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl PeerAddr { + /// Convenient way of constructing a new peer_addr from an ip_addr + /// defaults to port 3414 on mainnet and 13414 on floonet. + pub fn from_ip(addr: IpAddr) -> PeerAddr { + let port = if global::is_floonet() { 13414 } else { 3414 }; + PeerAddr(SocketAddr::new(addr, port)) + } + + /// If the ip is loopback then our key is "ip:port" (mainly for local usernet testing). + /// Otherwise we only care about the ip (we disallow multiple peers on the same ip address). + pub fn as_key(&self) -> String { + if self.0.ip().is_loopback() { + format!("{}:{}", self.0.ip(), self.0.port()) + } else { + format!("{}", self.0.ip()) + } + } +} + /// Configuration for the peer-to-peer server. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct P2PConfig { @@ -106,18 +209,18 @@ pub struct P2PConfig { pub seeding_type: Seeding, /// The list of seed nodes, if using Seeding as a seed type - pub seeds: Option>, + pub seeds: Option>, /// Capabilities expose by this node, also conditions which other peers this /// node will have an affinity toward when connection. pub capabilities: Capabilities, - pub peers_allow: Option>, + pub peers_allow: Option>, - pub peers_deny: Option>, + pub peers_deny: Option>, /// The list of preferred peers that we will try to connect to - pub peers_preferred: Option>, + pub peers_preferred: Option>, pub ban_window: Option, @@ -125,7 +228,7 @@ pub struct P2PConfig { pub peer_min_preferred_count: Option, - pub dandelion_peer: Option, + pub dandelion_peer: Option, } /// Default address for peer-to-peer connections. @@ -178,7 +281,7 @@ impl P2PConfig { } /// Type of seeding the server will use to find other peers on the network. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] pub enum Seeding { /// No seeding, mostly for tests that programmatically connect None, @@ -262,7 +365,7 @@ pub struct PeerInfo { pub capabilities: Capabilities, pub user_agent: String, pub version: u32, - pub addr: SocketAddr, + pub addr: PeerAddr, pub direction: Direction, pub live_info: Arc>, } @@ -307,7 +410,7 @@ pub struct PeerInfoDisplay { pub capabilities: Capabilities, pub user_agent: String, pub version: u32, - pub addr: SocketAddr, + pub addr: PeerAddr, pub direction: Direction, pub total_difficulty: Difficulty, pub height: u64, @@ -353,22 +456,22 @@ pub trait ChainAdapter: Sync + Send { fn get_transaction(&self, kernel_hash: Hash) -> Option; - fn tx_kernel_received(&self, kernel_hash: Hash, addr: SocketAddr); + fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr); /// A block has been received from one of our peers. Returns true if the /// block could be handled properly and is not deemed defective by the /// chain. Returning false means the block will never be valid and /// may result in the peer being banned. - fn block_received(&self, b: core::Block, addr: SocketAddr, was_requested: bool) -> bool; + fn block_received(&self, b: core::Block, addr: PeerAddr, was_requested: bool) -> bool; - fn compact_block_received(&self, cb: core::CompactBlock, addr: SocketAddr) -> bool; + fn compact_block_received(&self, cb: core::CompactBlock, addr: PeerAddr) -> bool; - fn header_received(&self, bh: core::BlockHeader, addr: SocketAddr) -> bool; + fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> bool; /// A set of block header has been received, typically in response to a /// block /// header request. - fn headers_received(&self, bh: &[core::BlockHeader], addr: SocketAddr) -> bool; + fn headers_received(&self, bh: &[core::BlockHeader], addr: PeerAddr) -> bool; /// Finds a list of block headers based on the provided locator. Tries to /// identify the common chain and gets the headers that follow it @@ -401,7 +504,7 @@ pub trait ChainAdapter: Sync + Send { /// If we're willing to accept that new state, the data stream will be /// read as a zip file, unzipped and the resulting state files should be /// rewound to the provided indexes. - fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: SocketAddr) -> bool; + fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: PeerAddr) -> bool; } /// Additional methods required by the protocol that don't need to be @@ -409,14 +512,14 @@ pub trait ChainAdapter: Sync + Send { pub trait NetAdapter: ChainAdapter { /// Find good peers we know with the provided capability and return their /// addresses. - fn find_peer_addrs(&self, capab: Capabilities) -> Vec; + fn find_peer_addrs(&self, capab: Capabilities) -> Vec; /// A list of peers has been received from one of our peers. - fn peer_addrs_received(&self, _: Vec); + fn peer_addrs_received(&self, _: Vec); /// Heard total_difficulty from a connected peer (via ping/pong). - fn peer_difficulty(&self, _: SocketAddr, _: Difficulty, _: u64); + fn peer_difficulty(&self, _: PeerAddr, _: Difficulty, _: u64); /// Is this peer currently banned? - fn is_banned(&self, addr: SocketAddr) -> bool; + fn is_banned(&self, addr: PeerAddr) -> bool; } diff --git a/p2p/tests/peer_handshake.rs b/p2p/tests/peer_handshake.rs index ae229f473..57c335e4d 100644 --- a/p2p/tests/peer_handshake.rs +++ b/p2p/tests/peer_handshake.rs @@ -25,6 +25,7 @@ use std::{thread, time}; use crate::core::core::hash::Hash; use crate::core::pow::Difficulty; +use crate::p2p::types::PeerAddr; use crate::p2p::Peer; fn open_port() -> u16 { @@ -70,7 +71,7 @@ fn peer_handshake() { let addr = SocketAddr::new(p2p_config.host, p2p_config.port); let mut socket = TcpStream::connect_timeout(&addr, time::Duration::from_secs(10)).unwrap(); - let my_addr = "127.0.0.1:5000".parse().unwrap(); + let my_addr = PeerAddr("127.0.0.1:5000".parse().unwrap()); let mut peer = Peer::connect( &mut socket, p2p::Capabilities::UNKNOWN, @@ -89,7 +90,7 @@ fn peer_handshake() { peer.send_ping(Difficulty::min(), 0).unwrap(); thread::sleep(time::Duration::from_secs(1)); - let server_peer = server.peers.get_connected_peer(&my_addr).unwrap(); + let server_peer = server.peers.get_connected_peer(my_addr).unwrap(); assert_eq!(server_peer.info.total_difficulty(), Difficulty::min()); assert!(server.peers.peer_count() > 0); } diff --git a/servers/src/common/adapters.rs b/servers/src/common/adapters.rs index 279919cab..ae160267b 100644 --- a/servers/src/common/adapters.rs +++ b/servers/src/common/adapters.rs @@ -17,7 +17,6 @@ use crate::util::RwLock; use std::fs::File; -use std::net::SocketAddr; use std::sync::{Arc, Weak}; use std::thread; use std::time::Instant; @@ -31,6 +30,7 @@ use crate::core::core::{BlockHeader, BlockSums, CompactBlock}; use crate::core::pow::Difficulty; use crate::core::{core, global}; use crate::p2p; +use crate::p2p::types::PeerAddr; use crate::pool; use crate::util::OneTime; use chrono::prelude::*; @@ -62,7 +62,7 @@ impl p2p::ChainAdapter for NetToChainAdapter { self.tx_pool.read().retrieve_tx_by_kernel_hash(kernel_hash) } - fn tx_kernel_received(&self, kernel_hash: Hash, addr: SocketAddr) { + fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) { // nothing much we can do with a new transaction while syncing if self.sync_state.is_syncing() { return; @@ -71,7 +71,7 @@ impl p2p::ChainAdapter for NetToChainAdapter { let tx = self.tx_pool.read().retrieve_tx_by_kernel_hash(kernel_hash); if tx.is_none() { - self.request_transaction(kernel_hash, &addr); + self.request_transaction(kernel_hash, addr); } } @@ -107,7 +107,7 @@ impl p2p::ChainAdapter for NetToChainAdapter { } } - fn block_received(&self, b: core::Block, addr: SocketAddr, was_requested: bool) -> bool { + fn block_received(&self, b: core::Block, addr: PeerAddr, was_requested: bool) -> bool { debug!( "Received block {} at {} from {} [in/out/kern: {}/{}/{}] going to process.", b.hash(), @@ -120,7 +120,7 @@ impl p2p::ChainAdapter for NetToChainAdapter { self.process_block(b, addr, was_requested) } - fn compact_block_received(&self, cb: core::CompactBlock, addr: SocketAddr) -> bool { + fn compact_block_received(&self, cb: core::CompactBlock, addr: PeerAddr) -> bool { let bhash = cb.hash(); debug!( "Received compact_block {} at {} from {} [out/kern/kern_ids: {}/{}/{}] going to process.", @@ -187,7 +187,7 @@ impl p2p::ChainAdapter for NetToChainAdapter { } else { if self.sync_state.status() == SyncStatus::NoSync { debug!("adapter: block invalid after hydration, requesting full block"); - self.request_block(&cb.header, &addr); + self.request_block(&cb.header, addr); true } else { debug!("block invalid after hydration, ignoring it, cause still syncing"); @@ -201,7 +201,7 @@ impl p2p::ChainAdapter for NetToChainAdapter { } } - fn header_received(&self, bh: core::BlockHeader, addr: SocketAddr) -> bool { + fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> bool { let bhash = bh.hash(); debug!( "Received block header {} at {} from {}, going to process.", @@ -227,13 +227,13 @@ impl p2p::ChainAdapter for NetToChainAdapter { // we have successfully processed a block header // so we can go request the block itself - self.request_compact_block(&bh, &addr); + self.request_compact_block(&bh, addr); // done receiving the header true } - fn headers_received(&self, bhs: &[core::BlockHeader], addr: SocketAddr) -> bool { + fn headers_received(&self, bhs: &[core::BlockHeader], addr: PeerAddr) -> bool { info!("Received {} block headers from {}", bhs.len(), addr,); if bhs.len() == 0 { @@ -342,7 +342,7 @@ impl p2p::ChainAdapter for NetToChainAdapter { /// If we're willing to accept that new state, the data stream will be /// read as a zip file, unzipped and the resulting state files should be /// rewound to the provided indexes. - fn txhashset_write(&self, h: Hash, txhashset_data: File, _peer_addr: SocketAddr) -> bool { + fn txhashset_write(&self, h: Hash, txhashset_data: File, _peer_addr: PeerAddr) -> bool { // check status again after download, in case 2 txhashsets made it somehow if let SyncStatus::TxHashsetDownload { .. } = self.sync_state.status() { } else { @@ -421,7 +421,7 @@ impl NetToChainAdapter { // pushing the new block through the chain pipeline // remembering to reset the head if we have a bad block - fn process_block(&self, b: core::Block, addr: SocketAddr, was_requested: bool) -> bool { + fn process_block(&self, b: core::Block, addr: PeerAddr, was_requested: bool) -> bool { // We cannot process blocks earlier than the horizon so check for this here. { let head = self.chain().head().unwrap(); @@ -458,7 +458,7 @@ impl NetToChainAdapter { && !self.sync_state.is_syncing() { debug!("process_block: received an orphan block, checking the parent: {:}", previous.hash()); - self.request_block_by_hash(previous.hash(), &addr) + self.request_block_by_hash(previous.hash(), addr) } } true @@ -525,7 +525,7 @@ impl NetToChainAdapter { } } - fn request_transaction(&self, h: Hash, addr: &SocketAddr) { + fn request_transaction(&self, h: Hash, addr: PeerAddr) { self.send_tx_request_to_peer(h, addr, |peer, h| peer.send_tx_request(h)) } @@ -533,24 +533,24 @@ impl NetToChainAdapter { // it into a full block then fallback to requesting the full block // from the same peer that gave us the compact block // consider additional peers for redundancy? - fn request_block(&self, bh: &BlockHeader, addr: &SocketAddr) { + fn request_block(&self, bh: &BlockHeader, addr: PeerAddr) { self.request_block_by_hash(bh.hash(), addr) } - fn request_block_by_hash(&self, h: Hash, addr: &SocketAddr) { + fn request_block_by_hash(&self, h: Hash, addr: PeerAddr) { self.send_block_request_to_peer(h, addr, |peer, h| peer.send_block_request(h)) } // After we have received a block header in "header first" propagation // we need to go request the block (compact representation) from the // same peer that gave us the header (unless we have already accepted the block) - fn request_compact_block(&self, bh: &BlockHeader, addr: &SocketAddr) { + fn request_compact_block(&self, bh: &BlockHeader, addr: PeerAddr) { self.send_block_request_to_peer(bh.hash(), addr, |peer, h| { peer.send_compact_block_request(h) }) } - fn send_tx_request_to_peer(&self, h: Hash, addr: &SocketAddr, f: F) + fn send_tx_request_to_peer(&self, h: Hash, addr: PeerAddr, f: F) where F: Fn(&p2p::Peer, Hash) -> Result<(), p2p::Error>, { @@ -567,7 +567,7 @@ impl NetToChainAdapter { } } - fn send_block_request_to_peer(&self, h: Hash, addr: &SocketAddr, f: F) + fn send_block_request_to_peer(&self, h: Hash, addr: PeerAddr, f: F) where F: Fn(&p2p::Peer, Hash) -> Result<(), p2p::Error>, { diff --git a/servers/src/grin/seed.rs b/servers/src/grin/seed.rs index fa01cc5a1..dd6f2d134 100644 --- a/servers/src/grin/seed.rs +++ b/servers/src/grin/seed.rs @@ -21,12 +21,13 @@ use chrono::prelude::{DateTime, Utc}; use chrono::{Duration, MIN_DATE}; use rand::{thread_rng, Rng}; use std::collections::HashMap; -use std::net::{SocketAddr, ToSocketAddrs}; +use std::net::ToSocketAddrs; use std::sync::{mpsc, Arc}; use std::{cmp, str, thread, time}; use crate::core::global; use crate::p2p; +use crate::p2p::types::PeerAddr; use crate::p2p::ChainAdapter; use crate::pool::DandelionConfig; use crate::util::{Mutex, StopState}; @@ -52,8 +53,8 @@ pub fn connect_and_monitor( p2p_server: Arc, capabilities: p2p::Capabilities, dandelion_config: DandelionConfig, - seed_list: Box Vec + Send>, - preferred_peers: Option>, + seed_list: Box Vec + Send>, + preferred_peers: Option>, stop_state: Arc>, ) { let _ = thread::Builder::new() @@ -78,7 +79,7 @@ pub fn connect_and_monitor( let mut prev_ping = Utc::now(); let mut start_attempt = 0; - let mut connecting_history: HashMap> = HashMap::new(); + let mut connecting_history: HashMap> = HashMap::new(); loop { if stop_state.lock().is_stopped() { @@ -140,8 +141,8 @@ pub fn connect_and_monitor( fn monitor_peers( peers: Arc, config: p2p::P2PConfig, - tx: mpsc::Sender, - preferred_peers_list: Option>, + tx: mpsc::Sender, + preferred_peers_list: Option>, ) { // regularly check if we need to acquire more peers and if so, gets // them from db @@ -156,7 +157,7 @@ fn monitor_peers( let interval = Utc::now().timestamp() - x.last_banned; // Unban peer if interval >= config.ban_window() { - peers.unban_peer(&x.addr); + peers.unban_peer(x.addr); debug!( "monitor_peers: unbanned {} after {} seconds", x.addr, interval @@ -192,7 +193,7 @@ fn monitor_peers( // loop over connected peers // ask them for their list of peers - let mut connected_peers: Vec = vec![]; + let mut connected_peers: Vec = vec![]; for p in peers.connected_peers() { trace!( "monitor_peers: {}:{} ask {} for more peers", @@ -205,19 +206,16 @@ fn monitor_peers( } // Attempt to connect to preferred peers if there is some - match preferred_peers_list { - Some(preferred_peers) => { - for p in preferred_peers { - if !connected_peers.is_empty() { - if !connected_peers.contains(&p) { - tx.send(p).unwrap(); - } - } else { + if let Some(preferred_peers) = preferred_peers_list { + for p in preferred_peers { + if !connected_peers.is_empty() { + if !connected_peers.contains(&p) { tx.send(p).unwrap(); } + } else { + tx.send(p).unwrap(); } } - None => debug!("monitor_peers: no preferred peers"), } // take a random defunct peer and mark it healthy: over a long period any @@ -235,7 +233,7 @@ fn monitor_peers( config.peer_max_count() as usize, ); - for p in new_peers.iter().filter(|p| !peers.is_known(&p.addr)) { + for p in new_peers.iter().filter(|p| !peers.is_known(p.addr)) { trace!( "monitor_peers: on {}:{}, queue to soon try {}", config.host, @@ -265,9 +263,9 @@ fn update_dandelion_relay(peers: Arc, dandelion_config: DandelionCon // otherwise use the seeds provided. fn connect_to_seeds_and_preferred_peers( peers: Arc, - tx: mpsc::Sender, - seed_list: Box Vec>, - peers_preferred_list: Option>, + tx: mpsc::Sender, + seed_list: Box Vec>, + peers_preferred_list: Option>, ) { // check if we have some peers in db // look for peers that are able to give us other peers (via PEER_LIST capability) @@ -303,14 +301,14 @@ fn listen_for_addrs( peers: Arc, p2p: Arc, capab: p2p::Capabilities, - rx: &mpsc::Receiver, - connecting_history: &mut HashMap>, + rx: &mpsc::Receiver, + connecting_history: &mut HashMap>, ) { // Pull everything currently on the queue off the queue. // Does not block so addrs may be empty. // We will take(max_peers) from this later but we want to drain the rx queue // here to prevent it backing up. - let addrs: Vec = rx.try_iter().collect(); + let addrs: Vec = rx.try_iter().collect(); // If we have a healthy number of outbound peers then we are done here. if peers.healthy_peers_mix() { @@ -342,7 +340,7 @@ fn listen_for_addrs( let p2p_c = p2p.clone(); let _ = thread::Builder::new() .name("peer_connect".to_string()) - .spawn(move || match p2p_c.connect(&addr) { + .spawn(move || match p2p_c.connect(addr) { Ok(p) => { let _ = p.send_peer_request(capab); let _ = peers_c.update_state(addr, p2p::State::Healthy); @@ -368,9 +366,9 @@ fn listen_for_addrs( } } -pub fn dns_seeds() -> Box Vec + Send> { +pub fn dns_seeds() -> Box Vec + Send> { Box::new(|| { - let mut addresses: Vec = vec![]; + let mut addresses: Vec = vec![]; let net_seeds = if global::is_floonet() { FLOONET_DNS_SEEDS } else { @@ -384,7 +382,7 @@ pub fn dns_seeds() -> Box Vec + Send> { &mut (addrs .map(|mut addr| { addr.set_port(if global::is_floonet() { 13414 } else { 3414 }); - addr + PeerAddr(addr) }) .filter(|addr| !temp_addresses.contains(addr)) .collect()), @@ -399,26 +397,6 @@ pub fn dns_seeds() -> Box Vec + Send> { /// Convenience function when the seed list is immediately known. Mostly used /// for tests. -pub fn predefined_seeds(addrs_str: Vec) -> Box Vec + Send> { - Box::new(move || { - addrs_str - .iter() - .map(|s| s.parse().unwrap()) - .collect::>() - }) -} - -/// Convenience function when the seed list is immediately known. Mostly used -/// for tests. -pub fn preferred_peers(addrs_str: Vec) -> Option> { - if addrs_str.is_empty() { - None - } else { - Some( - addrs_str - .iter() - .map(|s| s.parse().unwrap()) - .collect::>(), - ) - } +pub fn predefined_seeds(addrs: Vec) -> Box Vec + Send> { + Box::new(move || addrs.clone()) } diff --git a/servers/src/grin/server.rs b/servers/src/grin/server.rs index ea2532a77..ac25eb3f7 100644 --- a/servers/src/grin/server.rs +++ b/servers/src/grin/server.rs @@ -16,7 +16,6 @@ //! the peer-to-peer server, the blockchain and the transaction pool) and acts //! as a facade. -use std::net::SocketAddr; use std::sync::Arc; use std::{thread, time}; @@ -35,6 +34,7 @@ use crate::grin::{dandelion_monitor, seed, sync}; use crate::mining::stratumserver; use crate::mining::test_miner::Miner; use crate::p2p; +use crate::p2p::types::PeerAddr; use crate::pool; use crate::store; use crate::util::file::get_first_line; @@ -103,7 +103,7 @@ impl Server { } /// Instantiates a new server associated with the provided future reactor. - pub fn new(mut config: ServerConfig) -> Result { + pub fn new(config: ServerConfig) -> Result { // Defaults to None (optional) in config file. // This translates to false here. let archive_mode = match config.archive_mode { @@ -178,30 +178,25 @@ impl Server { pool_net_adapter.init(p2p_server.peers.clone()); net_adapter.init(p2p_server.peers.clone()); - if config.p2p_config.seeding_type.clone() != p2p::Seeding::Programmatic { - let seeder = match config.p2p_config.seeding_type.clone() { + if config.p2p_config.seeding_type != p2p::Seeding::Programmatic { + let seeder = match config.p2p_config.seeding_type { p2p::Seeding::None => { warn!("No seed configured, will stay solo until connected to"); seed::predefined_seeds(vec![]) } p2p::Seeding::List => { - seed::predefined_seeds(config.p2p_config.seeds.as_mut().unwrap().clone()) + seed::predefined_seeds(config.p2p_config.seeds.clone().unwrap()) } p2p::Seeding::DNSSeed => seed::dns_seeds(), _ => unreachable!(), }; - let peers_preferred = match config.p2p_config.peers_preferred.clone() { - Some(peers_preferred) => seed::preferred_peers(peers_preferred), - None => None, - }; - seed::connect_and_monitor( p2p_server.clone(), config.p2p_config.capabilities, config.dandelion_config.clone(), seeder, - peers_preferred, + config.p2p_config.peers_preferred.clone(), stop_state.clone(), ); } @@ -273,8 +268,8 @@ impl Server { } /// Asks the server to connect to a peer at the provided network address. - pub fn connect_peer(&self, addr: SocketAddr) -> Result<(), Error> { - self.p2p.connect(&addr)?; + pub fn connect_peer(&self, addr: PeerAddr) -> Result<(), Error> { + self.p2p.connect(addr)?; Ok(()) } diff --git a/servers/src/grin/sync/header_sync.rs b/servers/src/grin/sync/header_sync.rs index 1c21aeee6..81c049315 100644 --- a/servers/src/grin/sync/header_sync.rs +++ b/servers/src/grin/sync/header_sync.rs @@ -148,7 +148,7 @@ impl HeaderSync { && highest_height == peer.info.height() { self.peers - .ban_peer(&peer.info.addr, ReasonForBan::FraudHeight); + .ban_peer(peer.info.addr, ReasonForBan::FraudHeight); info!( "sync: ban a fraud peer: {}, claimed height: {}, total difficulty: {}", peer.info.addr, diff --git a/servers/tests/framework.rs b/servers/tests/framework.rs index d0bc36d71..5b9f8b28d 100644 --- a/servers/tests/framework.rs +++ b/servers/tests/framework.rs @@ -13,6 +13,7 @@ // limitations under the License. use self::keychain::Keychain; +use self::p2p::PeerAddr; use self::util::Mutex; use self::wallet::{HTTPNodeClient, HTTPWalletCommAdapter, LMDBBackend, WalletConfig}; use blake2_rfc as blake2; @@ -191,7 +192,7 @@ impl LocalServerContainer { if self.config.seed_addr.len() > 0 { seeding_type = p2p::Seeding::List; - seeds = vec![self.config.seed_addr.to_string()]; + seeds = vec![PeerAddr(self.config.seed_addr.parse().unwrap())]; } let s = servers::Server::new(servers::ServerConfig { @@ -233,9 +234,9 @@ impl LocalServerContainer { s.start_test_miner(wallet_url, s.stop_state.clone()); } - for p in &mut self.peer_list { + for p in &self.peer_list { println!("{} connecting to peer: {}", self.config.p2p_server_port, p); - let _ = s.connect_peer(p.parse().unwrap()); + let _ = s.connect_peer(PeerAddr(p.parse().unwrap())); } if self.wallet_is_running { @@ -647,7 +648,9 @@ pub fn config(n: u16, test_name_dir: &str, seed_n: u16) -> servers::ServerConfig p2p_config: p2p::P2PConfig { port: 10000 + n, seeding_type: p2p::Seeding::List, - seeds: Some(vec![format!("127.0.0.1:{}", 10000 + seed_n)]), + seeds: Some(vec![PeerAddr( + format!("127.0.0.1:{}", 10000 + seed_n).parse().unwrap(), + )]), ..p2p::P2PConfig::default() }, chain_type: core::global::ChainTypes::AutomatedTesting, diff --git a/servers/tests/simulnet.rs b/servers/tests/simulnet.rs index 424ab0f02..201b03647 100644 --- a/servers/tests/simulnet.rs +++ b/servers/tests/simulnet.rs @@ -19,6 +19,7 @@ mod framework; use self::core::core::hash::Hashed; use self::core::global::{self, ChainTypes}; +use self::p2p::PeerAddr; use self::util::{Mutex, StopState}; use self::wallet::controller; use self::wallet::libwallet::types::{WalletBackend, WalletInst}; @@ -933,7 +934,9 @@ fn replicate_tx_fluff_failure() { // Server 2 (another node) let mut s2_config = framework::config(3001, "tx_fluff", 3001); - s2_config.p2p_config.seeds = Some(vec!["127.0.0.1:13000".to_owned()]); + s2_config.p2p_config.seeds = Some(vec![PeerAddr( + "127.0.0.1:13000".to_owned().parse().unwrap(), + )]); s2_config.dandelion_config.embargo_secs = Some(10); s2_config.dandelion_config.patience_secs = Some(1); s2_config.dandelion_config.relay_secs = Some(1); @@ -944,7 +947,9 @@ fn replicate_tx_fluff_failure() { for i in 0..dl_nodes { // (create some stem nodes) let mut s_config = framework::config(3002 + i, "tx_fluff", 3002 + i); - s_config.p2p_config.seeds = Some(vec!["127.0.0.1:13000".to_owned()]); + s_config.p2p_config.seeds = Some(vec![PeerAddr( + "127.0.0.1:13000".to_owned().parse().unwrap(), + )]); s_config.dandelion_config.embargo_secs = Some(10); s_config.dandelion_config.patience_secs = Some(1); s_config.dandelion_config.relay_secs = Some(1); diff --git a/src/bin/cmd/server.rs b/src/bin/cmd/server.rs index 1d3b03c1a..0a21c5166 100644 --- a/src/bin/cmd/server.rs +++ b/src/bin/cmd/server.rs @@ -24,7 +24,7 @@ use ctrlc; use crate::config::GlobalConfig; use crate::core::global; -use crate::p2p::Seeding; +use crate::p2p::{PeerAddr, Seeding}; use crate::servers; use crate::tui::ui; @@ -116,45 +116,15 @@ pub fn server_command( } if let Some(seeds) = a.values_of("seed") { + let seed_addrs = seeds + .filter_map(|x| x.parse().ok()) + .map(|x| PeerAddr(x)) + .collect(); server_config.p2p_config.seeding_type = Seeding::List; - server_config.p2p_config.seeds = Some(seeds.map(|s| s.to_string()).collect()); + server_config.p2p_config.seeds = Some(seed_addrs); } } - /*if let Some(true) = server_config.run_wallet_listener { - let mut wallet_config = global_config.members.as_ref().unwrap().wallet.clone(); - wallet::init_wallet_seed(wallet_config.clone()); - let wallet = wallet::instantiate_wallet(wallet_config.clone(), ""); - - let _ = thread::Builder::new() - .name("wallet_listener".to_string()) - .spawn(move || { - controller::foreign_listener(wallet, &wallet_config.api_listen_addr()) - .unwrap_or_else(|e| { - panic!( - "Error creating wallet listener: {:?} Config: {:?}", - e, wallet_config - ) - }); - }); - } - if let Some(true) = server_config.run_wallet_owner_api { - let mut wallet_config = global_config.members.unwrap().wallet; - let wallet = wallet::instantiate_wallet(wallet_config.clone(), ""); - wallet::init_wallet_seed(wallet_config.clone()); - - let _ = thread::Builder::new() - .name("wallet_owner_listener".to_string()) - .spawn(move || { - controller::owner_listener(wallet, "127.0.0.1:13420").unwrap_or_else(|e| { - panic!( - "Error creating wallet api listener: {:?} Config: {:?}", - e, wallet_config - ) - }); - }); - }*/ - if let Some(a) = server_args { match a.subcommand() { ("run", _) => { From eafe730a65b1de2d5a1df5be53ebb54d5df25ec2 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 19 Feb 2019 02:02:59 -0800 Subject: [PATCH 21/28] refactor: allocation free cut through algorithms (#2567) --- core/src/core/transaction.rs | 64 ++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 0e67e6489..f6239a484 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -31,7 +31,6 @@ use crate::{consensus, global}; use enum_primitive::FromPrimitive; use std::cmp::Ordering; use std::cmp::{max, min}; -use std::collections::HashSet; use std::sync::Arc; use std::{error, fmt}; @@ -647,14 +646,21 @@ impl TransactionBody { } // Verify that no input is spending an output from the same block. + // Assumes inputs and outputs are sorted fn verify_cut_through(&self) -> Result<(), Error> { - let mut out_set = HashSet::new(); - for out in &self.outputs { - out_set.insert(out.commitment()); - } - for inp in &self.inputs { - if out_set.contains(&inp.commitment()) { - return Err(Error::CutThrough); + let mut inputs = self.inputs.iter().map(|x| x.hash()).peekable(); + let mut outputs = self.outputs.iter().map(|x| x.hash()).peekable(); + while let (Some(ih), Some(oh)) = (inputs.peek(), outputs.peek()) { + match ih.cmp(oh) { + Ordering::Less => { + inputs.next(); + } + Ordering::Greater => { + outputs.next(); + } + Ordering::Equal => { + return Err(Error::CutThrough); + } } } Ok(()) @@ -968,24 +974,34 @@ impl Transaction { /// and outputs. pub fn cut_through(inputs: &mut Vec, outputs: &mut Vec) -> Result<(), Error> { // assemble output commitments set, checking they're all unique - let mut out_set = HashSet::new(); - let all_uniq = { outputs.iter().all(|o| out_set.insert(o.commitment())) }; - if !all_uniq { + outputs.sort_unstable(); + if outputs.windows(2).any(|pair| pair[0] == pair[1]) { return Err(Error::AggregationError); } - - let in_set = inputs - .iter() - .map(|inp| inp.commitment()) - .collect::>(); - - let to_cut_through = in_set.intersection(&out_set).collect::>(); - - // filter and sort - inputs.retain(|inp| !to_cut_through.contains(&inp.commitment())); - outputs.retain(|out| !to_cut_through.contains(&out.commitment())); inputs.sort_unstable(); - outputs.sort_unstable(); + let mut inputs_idx = 0; + let mut outputs_idx = 0; + let mut ncut = 0; + while inputs_idx < inputs.len() && outputs_idx < outputs.len() { + match inputs[inputs_idx].hash().cmp(&outputs[outputs_idx].hash()) { + Ordering::Less => { + inputs[inputs_idx - ncut] = inputs[inputs_idx]; + inputs_idx += 1; + } + Ordering::Greater => { + outputs[outputs_idx - ncut] = outputs[outputs_idx]; + outputs_idx += 1; + } + Ordering::Equal => { + inputs_idx += 1; + outputs_idx += 1; + ncut += 1; + } + } + } + // Cut elements that have already been copied + outputs.drain(outputs_idx - ncut..outputs_idx); + inputs.drain(inputs_idx - ncut..inputs_idx); Ok(()) } @@ -1109,7 +1125,7 @@ pub fn deaggregate(mk_tx: Transaction, txs: Vec) -> Result Date: Tue, 19 Feb 2019 13:22:26 +0000 Subject: [PATCH 22/28] debug how long it takes to verify the kernel sums for fast sync (#2602) --- chain/src/txhashset/txhashset.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index 9be78cd27..4805b2c33 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -1204,11 +1204,19 @@ impl<'a> Extension<'a> { /// from the respective MMRs. /// For a significantly faster way of validating full kernel sums see BlockSums. pub fn validate_kernel_sums(&self) -> Result<((Commitment, Commitment)), Error> { + let now = Instant::now(); + let genesis = self.get_header_by_height(0)?; let (utxo_sum, kernel_sum) = self.verify_kernel_sums( self.header.total_overage(genesis.kernel_mmr_size > 0), self.header.total_kernel_offset(), )?; + + debug!( + "txhashset: validated total kernel sums, took {}s", + now.elapsed().as_secs(), + ); + Ok((utxo_sum, kernel_sum)) } From 48b7421d1e25a923446357c29e860f7cbe37ed65 Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Tue, 19 Feb 2019 13:23:12 +0000 Subject: [PATCH 23/28] use fs2 advisory file lock on startup (#2600) --- Cargo.lock | 11 +++++++++++ servers/Cargo.toml | 1 + servers/src/common/types.rs | 8 +++++++- servers/src/grin/server.rs | 38 +++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 360c9a767..abd662daf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -669,6 +669,15 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -947,6 +956,7 @@ dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "grin_api 1.0.1", "grin_chain 1.0.1", @@ -3215,6 +3225,7 @@ dependencies = [ "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" diff --git a/servers/Cargo.toml b/servers/Cargo.toml index 476b3c670..6b901a32a 100644 --- a/servers/Cargo.toml +++ b/servers/Cargo.toml @@ -11,6 +11,7 @@ edition = "2018" [dependencies] hyper = "0.12" +fs2 = "0.4" futures = "0.1" http = "0.1" hyper-staticfile = "0.3" diff --git a/servers/src/common/types.rs b/servers/src/common/types.rs index 72db40a03..5b2c9e267 100644 --- a/servers/src/common/types.rs +++ b/servers/src/common/types.rs @@ -48,6 +48,8 @@ pub enum Error { Pool(pool::PoolError), /// Invalid Arguments. ArgumentError(String), + /// Error originating from some I/O operation (likely a file on disk). + IOError(std::io::Error), } impl From for Error { @@ -60,7 +62,11 @@ impl From for Error { Error::Chain(e) } } - +impl From for Error { + fn from(e: std::io::Error) -> Error { + Error::IOError(e) + } +} impl From for Error { fn from(e: p2p::Error) -> Error { Error::P2P(e) diff --git a/servers/src/grin/server.rs b/servers/src/grin/server.rs index ac25eb3f7..8ad1d1577 100644 --- a/servers/src/grin/server.rs +++ b/servers/src/grin/server.rs @@ -16,9 +16,15 @@ //! the peer-to-peer server, the blockchain and the transaction pool) and acts //! as a facade. +use std::fs; +use std::fs::File; +use std::io::prelude::*; +use std::path::Path; use std::sync::Arc; use std::{thread, time}; +use fs2::FileExt; + use crate::api; use crate::api::TLSConfig; use crate::chain; @@ -59,6 +65,8 @@ pub struct Server { state_info: ServerStateInfo, /// Stop flag pub stop_state: Arc>, + /// Maintain a lock_file so we do not run multiple Grin nodes from same dir. + lock_file: Arc, } impl Server { @@ -102,8 +110,36 @@ impl Server { } } + // Exclusive (advisory) lock_file to ensure we do not run multiple + // instance of grin server from the same dir. + // This uses fs2 and should be safe cross-platform unless somebody abuses the file itself. + fn one_grin_at_a_time(config: &ServerConfig) -> Result, Error> { + let path = Path::new(&config.db_root); + fs::create_dir_all(path.clone())?; + let path = path.join("grin.lock"); + let lock_file = fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&path)?; + lock_file.try_lock_exclusive().map_err(|e| { + let mut stderr = std::io::stderr(); + writeln!( + &mut stderr, + "Failed to lock {:?} (grin server already running?)", + path + ) + .expect("Could not write to stderr"); + e + })?; + Ok(Arc::new(lock_file)) + } + /// Instantiates a new server associated with the provided future reactor. pub fn new(config: ServerConfig) -> Result { + // Obtain our lock_file or fail immediately with an error. + let lock_file = Server::one_grin_at_a_time(&config)?; + // Defaults to None (optional) in config file. // This translates to false here. let archive_mode = match config.archive_mode { @@ -264,6 +300,7 @@ impl Server { ..Default::default() }, stop_state, + lock_file, }) } @@ -451,6 +488,7 @@ impl Server { pub fn stop(&self) { self.p2p.stop(); self.stop_state.lock().stop(); + let _ = self.lock_file.unlock(); } /// Pause the p2p server. From b1c09946cb3a7e1df5068d123f1bf778e6229574 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Tue, 19 Feb 2019 14:29:58 +0000 Subject: [PATCH 24/28] Update contributing guidelines (#2563) * update contributing guidelines * add pull request template --- .github/pull_request_template.md | 18 ++++++++++++++++++ CONTRIBUTING.md | 18 +++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..bffb612d1 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,18 @@ +--- +name: Pull Request +about: Pull Request checklist +title: '' +labels: '' +assignees: '' + +--- +If your PR is a work in progress, please feel free to create it and include a [WIP] tag in the PR name. We encourage everyone to PR early and often so that other developers know what you're working on. + +Before submitting your PR for final review, please ensure that it: + +* Includes a proper description of what problems the PR addresses, as well as a detailed explanation as to what it changes +* Explains whether/how the change is consensus breaking or breaks existing client functionality +* Contains unit tests exercising new/changed functionality +* Fully considers the potential impact of the change on other parts of the system +* Describes how you've tested the change (e.g. against Floonet, etc) +* Updates any documentation that's affected by the PR diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7615e12d3..9607f69c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,23 @@ The [list of issues](https://github.com/mimblewimble/grin/issues) is a good plac Additional tests are rewarded with an immense amount of positive karma. -More documentation or updates/fixes to existing documentation are also very welcome. However, if submitting a PR(Pull-Request) consisting of documentation changes only, please try to ensure that the change is significantly more substantial than one or two lines. For example, working through an install document and making changes and updates throughout as you find issues is worth a PR. For typos and other small changes, either contact one of the developers, or if you think it's a significant enough error to cause problems for other users, please feel free to open an issue. +More documentation or updates/fixes to existing documentation are also very welcome. + +# PR Guidelines + +We generally prefer you to PR your work earlier rather than later. This ensures everyone else has a better idea of what's being worked on, and can help reduce wasted effort. If work on your PR has just begun, please feel free to create the PR with [WIP] (work in progress) in the PR title, and let us know when it's ready for review in the comments. + +Since mainnet has been released, the bar for having PRs accepted has been raised. Before submitting your PR for approval, please be ensure it: +* Includes a proper description of what problems the PR addresses, as well as a detailed explanation as to what it changes +* Explains whether/how the change is consensus breaking or breaks existing client functionality +* Contains unit tests exercising new/changed functionality +* Fully considers the potential impact of the change on other parts of the system +* Describes how you've tested the change (e.g. against Floonet, etc) +* Updates any documentation that's affected by the PR + +If submitting a PR consisting of documentation changes only, please try to ensure that the change is significantly more substantial than one or two lines. For example, working through an install document and making changes and updates throughout as you find issues is worth a PR. For typos and other small changes, either contact one of the developers, or if you think it's a significant enough error to cause problems for other users, please feel free to open an issue. + +The development team will be happy to help and guide you with any of these points and work with you getting your PR submitted for approval. Create a PR with [WIP] in the title and ask for specific assistance within the issue, or contact the dev team on any of the channels below. # Find Us From 2df633b62291f615ae96ceae0494d12b99d95013 Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Wed, 20 Feb 2019 08:16:13 +0000 Subject: [PATCH 25/28] log timing for rebuild_index (#2607) --- chain/src/txhashset/txhashset.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index 4805b2c33..1acf4b98d 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -1252,18 +1252,29 @@ impl<'a> Extension<'a> { Ok((output_sum, kernel_sum)) } - /// Rebuild the index of MMR positions to the corresponding Output and - /// kernel by iterating over the whole MMR data. This is a costly operation - /// performed only when we receive a full new chain state. + /// Rebuild the index of MMR positions to the corresponding UTXOs. + /// This is a costly operation performed only when we receive a full new chain state. pub fn rebuild_index(&self) -> Result<(), Error> { + let now = Instant::now(); + + let mut count = 0; + for n in 1..self.output_pmmr.unpruned_size() + 1 { // non-pruned leaves only if pmmr::bintree_postorder_height(n) == 0 { if let Some(out) = self.output_pmmr.get_data(n) { self.batch.save_output_pos(&out.commit, n)?; + count += 1; } } } + + debug!( + "txhashset: rebuild_index ({} UTXOs), took {}s", + count, + now.elapsed().as_secs(), + ); + Ok(()) } From e71eca197722fe7d2e1eb49caa430e1fc866f868 Mon Sep 17 00:00:00 2001 From: hashmap Date: Mon, 25 Feb 2019 06:57:21 +0100 Subject: [PATCH 26/28] Remove some unwrap/expect in chain crate (#2621) * Return Result instead of calling expect in root(). It would kill peer's thread. Perhaps we should ban this peer as malicious. * Remove some unwraps --- chain/src/chain.rs | 2 +- chain/src/error.rs | 3 +++ chain/src/txhashset/rewindable_kernel_view.rs | 3 ++- chain/src/txhashset/txhashset.rs | 11 ++++++----- core/src/core/pmmr/rewindable_pmmr.rs | 6 +++--- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 33504d544..80906fe79 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -660,7 +660,7 @@ impl Chain { /// Return a merkle proof valid for the current output pmmr state at the /// given pos - pub fn get_merkle_proof_for_pos(&self, commit: Commitment) -> Result { + pub fn get_merkle_proof_for_pos(&self, commit: Commitment) -> Result { let mut txhashset = self.txhashset.write(); txhashset.merkle_proof(commit) } diff --git a/chain/src/error.rs b/chain/src/error.rs index 637540de7..b39404423 100644 --- a/chain/src/error.rs +++ b/chain/src/error.rs @@ -131,6 +131,9 @@ pub enum ErrorKind { /// We cannot process data once the Grin server has been stopped. #[fail(display = "Stopped (Grin Shutting Down)")] Stopped, + /// Internal Roaring Bitmap error + #[fail(display = "Roaring Bitmap error")] + Bitmap, } impl Display for Error { diff --git a/chain/src/txhashset/rewindable_kernel_view.rs b/chain/src/txhashset/rewindable_kernel_view.rs index c5de1751f..a1be9fc66 100644 --- a/chain/src/txhashset/rewindable_kernel_view.rs +++ b/chain/src/txhashset/rewindable_kernel_view.rs @@ -68,7 +68,8 @@ impl<'a> RewindableKernelView<'a> { /// fast sync where a reorg past the horizon could allow a whole rewrite of /// the kernel set. pub fn validate_root(&self) -> Result<(), Error> { - if self.pmmr.root() != self.header.kernel_root { + let root = self.pmmr.root().map_err(|_| ErrorKind::InvalidRoot)?; + if root != self.header.kernel_root { return Err(ErrorKind::InvalidTxHashSet(format!( "Kernel root at {} does not match", self.header.height diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index 1acf4b98d..342b7d346 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -272,9 +272,11 @@ impl TxHashSet { } /// build a new merkle proof for the given position. - pub fn merkle_proof(&mut self, commit: Commitment) -> Result { - let pos = self.commit_index.get_output_pos(&commit).unwrap(); - PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos).merkle_proof(pos) + pub fn merkle_proof(&mut self, commit: Commitment) -> Result { + let pos = self.commit_index.get_output_pos(&commit)?; + PMMR::at(&mut self.output_pmmr_h.backend, self.output_pmmr_h.last_pos) + .merkle_proof(pos) + .map_err(|_| ErrorKind::MerkleProof.into()) } /// Compact the MMR data files and flush the rm logs @@ -1590,6 +1592,5 @@ pub fn input_pos_to_rewind( current = batch.get_previous_header(¤t)?; } - let bitmap = bitmap_fast_or(None, &mut block_input_bitmaps).unwrap(); - Ok(bitmap) + bitmap_fast_or(None, &mut block_input_bitmaps).ok_or_else(|| ErrorKind::Bitmap.into()) } diff --git a/core/src/core/pmmr/rewindable_pmmr.rs b/core/src/core/pmmr/rewindable_pmmr.rs index 1eb395ece..e696d67af 100644 --- a/core/src/core/pmmr/rewindable_pmmr.rs +++ b/core/src/core/pmmr/rewindable_pmmr.rs @@ -95,9 +95,9 @@ where /// Computes the root of the MMR. Find all the peaks in the current /// tree and "bags" them to get a single peak. - pub fn root(&self) -> Hash { + pub fn root(&self) -> Result { if self.is_empty() { - return ZERO_HASH; + return Ok(ZERO_HASH); } let mut res = None; for peak in self.peaks().iter().rev() { @@ -106,7 +106,7 @@ where Some(rhash) => Some((*peak, rhash).hash_with_index(self.unpruned_size())), } } - res.expect("no root, invalid tree") + res.ok_or_else(|| "no root, invalid tree".to_owned()) } /// Returns a vec of the peaks of this MMR. From 8e2b0c7bc81ce775da83ed1f86203b3817eb314c Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Sun, 24 Feb 2019 21:57:56 -0800 Subject: [PATCH 27/28] Bump version to 1.0.2 (#2623) --- Cargo.lock | 132 ++++++++++++++++++++++---------------------- Cargo.toml | 22 ++++---- api/Cargo.toml | 14 ++--- chain/Cargo.toml | 10 ++-- config/Cargo.toml | 12 ++-- core/Cargo.toml | 6 +- keychain/Cargo.toml | 4 +- p2p/Cargo.toml | 10 ++-- pool/Cargo.toml | 12 ++-- servers/Cargo.toml | 20 +++---- src/bin/grin.yml | 2 +- store/Cargo.toml | 6 +- util/Cargo.toml | 2 +- wallet/Cargo.toml | 16 +++--- 14 files changed, 134 insertions(+), 134 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index abd662daf..ee5925e40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,7 +743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "grin" -version = "1.0.1" +version = "1.0.2" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "built 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -755,16 +755,16 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_api 1.0.1", - "grin_chain 1.0.1", - "grin_config 1.0.1", - "grin_core 1.0.1", - "grin_keychain 1.0.1", - "grin_p2p 1.0.1", - "grin_servers 1.0.1", - "grin_store 1.0.1", - "grin_util 1.0.1", - "grin_wallet 1.0.1", + "grin_api 1.0.2", + "grin_chain 1.0.2", + "grin_config 1.0.2", + "grin_core 1.0.2", + "grin_keychain 1.0.2", + "grin_p2p 1.0.2", + "grin_servers 1.0.2", + "grin_store 1.0.2", + "grin_util 1.0.2", + "grin_wallet 1.0.2", "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "linefeed 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -779,17 +779,17 @@ dependencies = [ [[package]] name = "grin_api" -version = "1.0.1" +version = "1.0.2" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_chain 1.0.1", - "grin_core 1.0.1", - "grin_p2p 1.0.1", - "grin_pool 1.0.1", - "grin_store 1.0.1", - "grin_util 1.0.1", + "grin_chain 1.0.2", + "grin_core 1.0.2", + "grin_p2p 1.0.2", + "grin_pool 1.0.2", + "grin_store 1.0.2", + "grin_util 1.0.2", "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "grin_chain" -version = "1.0.1" +version = "1.0.2" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -819,10 +819,10 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_core 1.0.1", - "grin_keychain 1.0.1", - "grin_store 1.0.1", - "grin_util 1.0.1", + "grin_core 1.0.2", + "grin_keychain 1.0.2", + "grin_store 1.0.2", + "grin_util 1.0.2", "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -833,14 +833,14 @@ dependencies = [ [[package]] name = "grin_config" -version = "1.0.1" +version = "1.0.2" dependencies = [ "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_core 1.0.1", - "grin_p2p 1.0.1", - "grin_servers 1.0.1", - "grin_util 1.0.1", - "grin_wallet 1.0.1", + "grin_core 1.0.2", + "grin_p2p 1.0.2", + "grin_servers 1.0.2", + "grin_util 1.0.2", + "grin_wallet 1.0.2", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -850,7 +850,7 @@ dependencies = [ [[package]] name = "grin_core" -version = "1.0.1" +version = "1.0.2" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -859,8 +859,8 @@ dependencies = [ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_keychain 1.0.1", - "grin_util 1.0.1", + "grin_keychain 1.0.2", + "grin_util 1.0.2", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -876,12 +876,12 @@ dependencies = [ [[package]] name = "grin_keychain" -version = "1.0.1" +version = "1.0.2" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_util 1.0.1", + "grin_util 1.0.2", "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -897,16 +897,16 @@ dependencies = [ [[package]] name = "grin_p2p" -version = "1.0.1" +version = "1.0.2" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_core 1.0.1", - "grin_pool 1.0.1", - "grin_store 1.0.1", - "grin_util 1.0.1", + "grin_core 1.0.2", + "grin_pool 1.0.2", + "grin_store 1.0.2", + "grin_util 1.0.2", "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -918,17 +918,17 @@ dependencies = [ [[package]] name = "grin_pool" -version = "1.0.1" +version = "1.0.2" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_chain 1.0.1", - "grin_core 1.0.1", - "grin_keychain 1.0.1", - "grin_store 1.0.1", - "grin_util 1.0.1", + "grin_chain 1.0.2", + "grin_core 1.0.2", + "grin_keychain 1.0.2", + "grin_store 1.0.2", + "grin_util 1.0.2", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -951,22 +951,22 @@ dependencies = [ [[package]] name = "grin_servers" -version = "1.0.1" +version = "1.0.2" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_api 1.0.1", - "grin_chain 1.0.1", - "grin_core 1.0.1", - "grin_keychain 1.0.1", - "grin_p2p 1.0.1", - "grin_pool 1.0.1", - "grin_store 1.0.1", - "grin_util 1.0.1", - "grin_wallet 1.0.1", + "grin_api 1.0.2", + "grin_chain 1.0.2", + "grin_core 1.0.2", + "grin_keychain 1.0.2", + "grin_p2p 1.0.2", + "grin_pool 1.0.2", + "grin_store 1.0.2", + "grin_util 1.0.2", + "grin_wallet 1.0.2", "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-staticfile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -982,7 +982,7 @@ dependencies = [ [[package]] name = "grin_store" -version = "1.0.1" +version = "1.0.2" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -991,8 +991,8 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_core 1.0.1", - "grin_util 1.0.1", + "grin_core 1.0.2", + "grin_util 1.0.2", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1004,7 +1004,7 @@ dependencies = [ [[package]] name = "grin_util" -version = "1.0.1" +version = "1.0.2" dependencies = [ "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "grin_wallet" -version = "1.0.1" +version = "1.0.2" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1032,12 +1032,12 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_api 1.0.1", - "grin_chain 1.0.1", - "grin_core 1.0.1", - "grin_keychain 1.0.1", - "grin_store 1.0.1", - "grin_util 1.0.1", + "grin_api 1.0.2", + "grin_chain 1.0.2", + "grin_core 1.0.2", + "grin_keychain 1.0.2", + "grin_store 1.0.2", + "grin_util 1.0.2", "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "prettytable-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index f1a0769a2..0c03735cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -34,14 +34,14 @@ linefeed = "0.5" failure = "0.1" failure_derive = "0.1" -grin_api = { path = "./api", version = "1.0.1" } -grin_config = { path = "./config", version = "1.0.1" } -grin_core = { path = "./core", version = "1.0.1" } -grin_keychain = { path = "./keychain", version = "1.0.1" } -grin_p2p = { path = "./p2p", version = "1.0.1" } -grin_servers = { path = "./servers", version = "1.0.1" } -grin_util = { path = "./util", version = "1.0.1" } -grin_wallet = { path = "./wallet", version = "1.0.1" } +grin_api = { path = "./api", version = "1.0.2" } +grin_config = { path = "./config", version = "1.0.2" } +grin_core = { path = "./core", version = "1.0.2" } +grin_keychain = { path = "./keychain", version = "1.0.2" } +grin_p2p = { path = "./p2p", version = "1.0.2" } +grin_servers = { path = "./servers", version = "1.0.2" } +grin_util = { path = "./util", version = "1.0.2" } +grin_wallet = { path = "./wallet", version = "1.0.2" } [target.'cfg(windows)'.dependencies] cursive = { version = "0.10.0", default-features = false, features = ["pancurses-backend"] } @@ -58,5 +58,5 @@ flate2 = "1.0" tar = "0.4" [dev-dependencies] -grin_chain = { path = "./chain", version = "1.0.1" } -grin_store = { path = "./store", version = "1.0.1" } +grin_chain = { path = "./chain", version = "1.0.2" } +grin_store = { path = "./store", version = "1.0.2" } diff --git a/api/Cargo.toml b/api/Cargo.toml index a71cb8c3a..abad11bf6 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_api" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "APIs for grin, a simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -30,9 +30,9 @@ futures = "0.1.21" rustls = "0.13" url = "1.7.0" -grin_core = { path = "../core", version = "1.0.1" } -grin_chain = { path = "../chain", version = "1.0.1" } -grin_p2p = { path = "../p2p", version = "1.0.1" } -grin_pool = { path = "../pool", version = "1.0.1" } -grin_store = { path = "../store", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } +grin_core = { path = "../core", version = "1.0.2" } +grin_chain = { path = "../chain", version = "1.0.2" } +grin_p2p = { path = "../p2p", version = "1.0.2" } +grin_pool = { path = "../pool", version = "1.0.2" } +grin_store = { path = "../store", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } diff --git a/chain/Cargo.toml b/chain/Cargo.toml index 275af2989..c4583a492 100644 --- a/chain/Cargo.toml +++ b/chain/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_chain" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Chain implementation for grin, a simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -22,10 +22,10 @@ serde_derive = "1" chrono = "0.4.4" lru-cache = "0.1" -grin_core = { path = "../core", version = "1.0.1" } -grin_keychain = { path = "../keychain", version = "1.0.1" } -grin_store = { path = "../store", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } +grin_core = { path = "../core", version = "1.0.2" } +grin_keychain = { path = "../keychain", version = "1.0.2" } +grin_store = { path = "../store", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } [dev-dependencies] env_logger = "0.5" diff --git a/config/Cargo.toml b/config/Cargo.toml index 0b262209e..c322e175f 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_config" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Configuration for grin, a simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -16,11 +16,11 @@ serde_derive = "1" toml = "0.4" dirs = "1.0.3" -grin_core = { path = "../core", version = "1.0.1" } -grin_servers = { path = "../servers", version = "1.0.1" } -grin_p2p = { path = "../p2p", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } -grin_wallet = { path = "../wallet", version = "1.0.1" } +grin_core = { path = "../core", version = "1.0.2" } +grin_servers = { path = "../servers", version = "1.0.2" } +grin_p2p = { path = "../p2p", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } +grin_wallet = { path = "../wallet", version = "1.0.2" } [dev-dependencies] pretty_assertions = "0.5.1" diff --git a/core/Cargo.toml b/core/Cargo.toml index 071ca1047..60568142f 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_core" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Chain implementation for grin, a simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -28,8 +28,8 @@ uuid = { version = "0.6", features = ["serde", "v4"] } log = "0.4" chrono = "0.4.4" -grin_keychain = { path = "../keychain", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } +grin_keychain = { path = "../keychain", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } [dev-dependencies] serde_json = "1" diff --git a/keychain/Cargo.toml b/keychain/Cargo.toml index 8efa6214a..bca879d3c 100644 --- a/keychain/Cargo.toml +++ b/keychain/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_keychain" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Chain implementation for grin, a simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -27,4 +27,4 @@ sha2 = "0.7" pbkdf2 = "0.2" -grin_util = { path = "../util", version = "1.0.1" } +grin_util = { path = "../util", version = "1.0.2" } diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml index ef09b6ca6..a417b682a 100644 --- a/p2p/Cargo.toml +++ b/p2p/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_p2p" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Chain implementation for grin, a simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -22,9 +22,9 @@ serde_derive = "1" log = "0.4" chrono = { version = "0.4.4", features = ["serde"] } -grin_core = { path = "../core", version = "1.0.1" } -grin_store = { path = "../store", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } +grin_core = { path = "../core", version = "1.0.2" } +grin_store = { path = "../store", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } [dev-dependencies] -grin_pool = { path = "../pool", version = "1.0.1" } +grin_pool = { path = "../pool", version = "1.0.2" } diff --git a/pool/Cargo.toml b/pool/Cargo.toml index 431bd7533..8e9c8fb44 100644 --- a/pool/Cargo.toml +++ b/pool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_pool" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Chain implementation for grin, a simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -19,10 +19,10 @@ chrono = "0.4.4" failure = "0.1" failure_derive = "0.1" -grin_core = { path = "../core", version = "1.0.1" } -grin_keychain = { path = "../keychain", version = "1.0.1" } -grin_store = { path = "../store", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } +grin_core = { path = "../core", version = "1.0.2" } +grin_keychain = { path = "../keychain", version = "1.0.2" } +grin_store = { path = "../store", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } [dev-dependencies] -grin_chain = { path = "../chain", version = "1.0.1" } +grin_chain = { path = "../chain", version = "1.0.2" } diff --git a/servers/Cargo.toml b/servers/Cargo.toml index 6b901a32a..5aea4701c 100644 --- a/servers/Cargo.toml +++ b/servers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_servers" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -26,15 +26,15 @@ chrono = "0.4.4" bufstream = "~0.1" jsonrpc-core = "~8.0" -grin_api = { path = "../api", version = "1.0.1" } -grin_chain = { path = "../chain", version = "1.0.1" } -grin_core = { path = "../core", version = "1.0.1" } -grin_keychain = { path = "../keychain", version = "1.0.1" } -grin_p2p = { path = "../p2p", version = "1.0.1" } -grin_pool = { path = "../pool", version = "1.0.1" } -grin_store = { path = "../store", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } -grin_wallet = { path = "../wallet", version = "1.0.1" } +grin_api = { path = "../api", version = "1.0.2" } +grin_chain = { path = "../chain", version = "1.0.2" } +grin_core = { path = "../core", version = "1.0.2" } +grin_keychain = { path = "../keychain", version = "1.0.2" } +grin_p2p = { path = "../p2p", version = "1.0.2" } +grin_pool = { path = "../pool", version = "1.0.2" } +grin_store = { path = "../store", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } +grin_wallet = { path = "../wallet", version = "1.0.2" } [dev-dependencies] blake2-rfc = "0.2" diff --git a/src/bin/grin.yml b/src/bin/grin.yml index 94a18e0a1..e6d0eb944 100644 --- a/src/bin/grin.yml +++ b/src/bin/grin.yml @@ -1,5 +1,5 @@ name: grin -version: "1.0.1" +version: "1.0.2" about: Lightweight implementation of the MimbleWimble protocol. author: The Grin Team diff --git a/store/Cargo.toml b/store/Cargo.toml index 2c663da3e..390f63246 100644 --- a/store/Cargo.toml +++ b/store/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_store" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -22,8 +22,8 @@ serde = "1" serde_derive = "1" log = "0.4" -grin_core = { path = "../core", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } +grin_core = { path = "../core", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } [dev-dependencies] chrono = "0.4.4" diff --git a/util/Cargo.toml b/util/Cargo.toml index 93d443a51..057772474 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_util" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index 79e573a58..b5dd5cdfb 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grin_wallet" -version = "1.0.1" +version = "1.0.2" authors = ["Grin Developers "] description = "Simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format." license = "Apache-2.0" @@ -31,12 +31,12 @@ uuid = { version = "0.6", features = ["serde", "v4"] } url = "1.7.0" chrono = { version = "0.4.4", features = ["serde"] } -grin_api = { path = "../api", version = "1.0.1" } -grin_core = { path = "../core", version = "1.0.1" } -grin_keychain = { path = "../keychain", version = "1.0.1" } -grin_store = { path = "../store", version = "1.0.1" } -grin_util = { path = "../util", version = "1.0.1" } -grin_chain = { path = "../chain", version = "1.0.1" } +grin_api = { path = "../api", version = "1.0.2" } +grin_core = { path = "../core", version = "1.0.2" } +grin_keychain = { path = "../keychain", version = "1.0.2" } +grin_store = { path = "../store", version = "1.0.2" } +grin_util = { path = "../util", version = "1.0.2" } +grin_chain = { path = "../chain", version = "1.0.2" } [dev-dependencies] -grin_store = { path = "../store", version = "1.0.1" } +grin_store = { path = "../store", version = "1.0.2" } From 391e311f4c05619bd4b7b0d599a5071ce7753b90 Mon Sep 17 00:00:00 2001 From: hashmap Date: Mon, 25 Feb 2019 07:57:56 +0100 Subject: [PATCH 28/28] Don't extract unexpected files from txhashset archive (#2624) We verify and remove such files later one, it's safer to ignore them during unpacking --- Cargo.lock | 2 ++ chain/Cargo.toml | 2 ++ chain/src/txhashset/txhashset.rs | 39 ++++++++++++++++++++++++++++++- chain/tests/test_txhashset.rs | 6 +---- util/src/zip.rs | 15 ++++++++---- util/tests/test.zip | Bin 0 -> 545 bytes util/tests/zip.rs | 10 +++++++- 7 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 util/tests/test.zip diff --git a/Cargo.lock b/Cargo.lock index ee5925e40..7a7a79415 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -823,10 +823,12 @@ dependencies = [ "grin_keychain 1.0.2", "grin_store 1.0.2", "grin_util 1.0.2", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/chain/Cargo.toml b/chain/Cargo.toml index c4583a492..5ea3619f0 100644 --- a/chain/Cargo.toml +++ b/chain/Cargo.toml @@ -21,6 +21,8 @@ serde = "1" serde_derive = "1" chrono = "0.4.4" lru-cache = "0.1" +lazy_static = "1" +regex = "1" grin_core = { path = "../core", version = "1.0.2" } grin_keychain = { path = "../keychain", version = "1.0.2" } diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index 342b7d346..31d7ac084 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -1447,11 +1447,28 @@ pub fn zip_write( ) -> Result<(), Error> { let txhashset_path = Path::new(&root_dir).join(TXHASHSET_SUBDIR); fs::create_dir_all(txhashset_path.clone())?; - zip::decompress(txhashset_data, &txhashset_path) + zip::decompress(txhashset_data, &txhashset_path, expected_file) .map_err(|ze| ErrorKind::Other(ze.to_string()))?; check_and_remove_files(&txhashset_path, header) } +fn expected_file(path: &Path) -> bool { + use lazy_static::lazy_static; + use regex::Regex; + let s_path = path.to_str().unwrap_or_else(|| ""); + lazy_static! { + static ref RE: Regex = Regex::new( + format!( + r#"^({}|{}|{})(/pmmr_(hash|data|leaf|prun)\.bin(\.\w*)?)?$"#, + OUTPUT_SUBDIR, KERNEL_SUBDIR, RANGE_PROOF_SUBDIR + ) + .as_str() + ) + .unwrap(); + } + RE.is_match(&s_path) +} + /// Check a txhashset directory and remove any unexpected fn check_and_remove_files(txhashset_path: &PathBuf, header: &BlockHeader) -> Result<(), Error> { // First compare the subdirectories @@ -1594,3 +1611,23 @@ pub fn input_pos_to_rewind( bitmap_fast_or(None, &mut block_input_bitmaps).ok_or_else(|| ErrorKind::Bitmap.into()) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_expected_files() { + assert!(!expected_file(Path::new("kernels"))); + assert!(!expected_file(Path::new("xkernel"))); + assert!(expected_file(Path::new("kernel"))); + assert!(expected_file(Path::new("kernel/pmmr_data.bin"))); + assert!(expected_file(Path::new("kernel/pmmr_hash.bin"))); + assert!(expected_file(Path::new("kernel/pmmr_leaf.bin"))); + assert!(expected_file(Path::new("kernel/pmmr_prun.bin"))); + assert!(expected_file(Path::new("kernel/pmmr_leaf.bin.deadbeef"))); + assert!(!expected_file(Path::new("xkernel/pmmr_data.bin"))); + assert!(!expected_file(Path::new("kernel/pmmrx_data.bin"))); + assert!(!expected_file(Path::new("kernel/pmmr_data.binx"))); + } +} diff --git a/chain/tests/test_txhashset.rs b/chain/tests/test_txhashset.rs index 1be151832..41ea97d85 100644 --- a/chain/tests/test_txhashset.rs +++ b/chain/tests/test_txhashset.rs @@ -136,9 +136,5 @@ fn txhashset_contains_expected_files(dirname: String, path_buf: PathBuf) -> bool let intersection: HashSet<_> = zip_files_hashset .difference(&expected_files_hashset) .collect(); - if intersection.is_empty() { - true - } else { - false - } + intersection.is_empty() } diff --git a/util/src/zip.rs b/util/src/zip.rs index 52531bd59..c79d0d008 100644 --- a/util/src/zip.rs +++ b/util/src/zip.rs @@ -62,15 +62,22 @@ pub fn compress(src_dir: &Path, dst_file: &File) -> ZipResult<()> { } /// Decompress a source file into the provided destination path. -pub fn decompress(src_file: R, dest: &Path) -> ZipResult<()> +pub fn decompress(src_file: R, dest: &Path, expected: F) -> ZipResult where R: io::Read + io::Seek, + F: Fn(&Path) -> bool, { + let mut decompressed = 0; let mut archive = zip_rs::ZipArchive::new(src_file)?; for i in 0..archive.len() { let mut file = archive.by_index(i)?; - let file_path = dest.join(file.name()); + let san_name = file.sanitized_name(); + if san_name.to_str().unwrap_or("") != file.name() || !expected(&san_name) { + info!("ignoring a suspicious file: {}", file.name()); + continue; + } + let file_path = dest.join(san_name); if (&*file.name()).ends_with('/') { fs::create_dir_all(&file_path)?; @@ -80,7 +87,6 @@ where fs::create_dir_all(&p)?; } } - //let mut outfile = fs::File::create(&file_path)?; let res = fs::File::create(&file_path); let mut outfile = match res { Err(e) => { @@ -90,6 +96,7 @@ where Ok(r) => r, }; io::copy(&mut file, &mut outfile)?; + decompressed += 1; } // Get and Set permissions @@ -104,5 +111,5 @@ where } } } - Ok(()) + Ok(decompressed) } diff --git a/util/tests/test.zip b/util/tests/test.zip new file mode 100644 index 0000000000000000000000000000000000000000..38b3f499de0163e62ca15ce18350a9d9a477a51b GIT binary patch literal 545 zcmWIWW@h1H0D=Au{XYEp{-1?`Y!K#PkYPyA&ri`SsVE5z;bdU8U359h4v0%DxEUB( zzA-W|u!sQFm1JZVD*#cV0!Xz&eqJh90MJm76a&LlprHwl)s`S02)6*So}T`Ippx7I z{nWC|9FT|Lj?Pm62|-=W$Rx*%D=;L0E@xl>dYWNLBZ!3v8dgZqpan~SHzSh>Gwx6T jnE?Vz8bg8PfCLE8QsgiR@MdKLxrhk}K_2A>d6oeH^pk5C literal 0 HcmV?d00001 diff --git a/util/tests/zip.rs b/util/tests/zip.rs index d2a211b5e..4c4422dc5 100644 --- a/util/tests/zip.rs +++ b/util/tests/zip.rs @@ -38,7 +38,7 @@ fn zip_unzip() { fs::create_dir_all(root.join("./dezipped")).unwrap(); let zip_file = File::open(zip_name).unwrap(); - zip::decompress(zip_file, &root.join("./dezipped")).unwrap(); + zip::decompress(zip_file, &root.join("./dezipped"), |_| true).unwrap(); assert!(root.join("to_zip/foo.txt").is_file()); assert!(root.join("to_zip/bar.txt").is_file()); @@ -46,6 +46,14 @@ fn zip_unzip() { let lorem = root.join("to_zip/sub/lorem"); assert!(lorem.is_file()); assert!(lorem.metadata().unwrap().len() == 55); + + let decompressed = zip::decompress( + File::open("tests/test.zip").unwrap(), + &root.join("./dezipped"), + |_| true, + ) + .unwrap(); + assert_eq!(decompressed, 1); } fn write_files(dir_name: String, root: &Path) -> io::Result<()> {