From d25fc48a3a7f3c3c36bd706e5f63ab21e77f9fd7 Mon Sep 17 00:00:00 2001 From: librelois <elois@ifee.fr> Date: Sat, 9 Jun 2018 01:35:51 +0200 Subject: [PATCH] wip: #80 --- Cargo.lock | 637 ------ Cargo.toml | 2 - blockchain/apply_valid_block.rs | 1 + blockchain/check_and_apply_block.rs | 2 + blockchain/dbex.rs | 155 +- blockchain/lib.rs | 16 +- blockchain/revert_valid_block.rs | 235 +++ blockchain/sync.rs | 41 +- core/cli/en.yml | 29 +- core/lib.rs | 27 +- dal/identity.rs | 26 +- dal/lib.rs | 2 + dal/writers/block.rs | 74 +- dal/writers/certification.rs | 1 + dal/writers/dividend.rs | 17 +- dal/writers/identity.rs | 31 +- dal/writers/requests.rs | 198 +- dal/writers/transaction.rs | 3 + documents/blockchain/v10/documents/block.rs | 19 + documents/lib.rs | 2 +- src/main.rs | 6 +- wotb/data/mod.rs | 62 +- ws2p/Cargo.toml | 33 - ws2p/ack_message.rs | 67 - ws2p/connect_message.rs | 72 - ws2p/constants.rs | 22 - ws2p/lib.rs | 2009 ------------------- ws2p/ok_message.rs | 69 - ws2p/parsers/blocks.rs | 149 -- ws2p/parsers/excluded.rs | 27 - ws2p/parsers/identities.rs | 87 - ws2p/parsers/memberships.rs | 68 - ws2p/parsers/mod.rs | 147 -- ws2p/parsers/transactions.rs | 234 --- ws2p/serializer.rs | 21 - ws2p/ws2p_connection.rs | 399 ---- ws2p/ws2p_db.rs | 137 -- ws2p/ws2p_requests.rs | 44 - 38 files changed, 809 insertions(+), 4362 deletions(-) create mode 100644 blockchain/revert_valid_block.rs delete mode 100644 ws2p/Cargo.toml delete mode 100644 ws2p/ack_message.rs delete mode 100644 ws2p/connect_message.rs delete mode 100644 ws2p/constants.rs delete mode 100644 ws2p/lib.rs delete mode 100644 ws2p/ok_message.rs delete mode 100644 ws2p/parsers/blocks.rs delete mode 100644 ws2p/parsers/excluded.rs delete mode 100644 ws2p/parsers/identities.rs delete mode 100644 ws2p/parsers/memberships.rs delete mode 100644 ws2p/parsers/mod.rs delete mode 100644 ws2p/parsers/transactions.rs delete mode 100644 ws2p/serializer.rs delete mode 100644 ws2p/ws2p_connection.rs delete mode 100644 ws2p/ws2p_db.rs delete mode 100644 ws2p/ws2p_requests.rs diff --git a/Cargo.lock b/Cargo.lock index d7dd4bcd..b5ab38f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,23 +58,6 @@ name = "base58" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "base64" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "base64" version = "0.9.1" @@ -93,11 +76,6 @@ dependencies = [ "serde 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.0.3" @@ -108,15 +86,6 @@ name = "byteorder" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bytes" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.3 (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.15" @@ -152,23 +121,6 @@ dependencies = [ "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "core-foundation" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation-sys" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-deque" version = "0.2.0" @@ -178,15 +130,6 @@ dependencies = [ "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-deque" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-epoch" version = "0.3.1" @@ -201,19 +144,6 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-epoch" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.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-utils" version = "0.2.2" @@ -222,14 +152,6 @@ dependencies = [ "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-utils" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "dtoa" version = "0.4.2" @@ -407,37 +329,12 @@ dependencies = [ "serde_derive 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "duniter-ws2p" -version = "0.1.0" -dependencies = [ - "duniter-conf 0.1.0", - "duniter-crypto 0.1.2", - "duniter-dal 0.1.0", - "duniter-documents 0.7.1", - "duniter-message 0.1.0", - "duniter-module 0.1.0", - "duniter-network 0.1.0", - "duniter-wotb 0.8.0-a0.6", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", - "sqlite 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "durs" version = "0.1.0" dependencies = [ "duniter-core 0.1.0", "duniter-tui 0.1.0", - "duniter-ws2p 0.1.0", ] [[package]] @@ -464,19 +361,6 @@ dependencies = [ "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -491,58 +375,11 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "futures" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "gcc" version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "httparse" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hyper" -version = "0.10.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "idna" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.6 (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)", -] - -[[package]] -name = "iovec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itoa" version = "0.4.1" @@ -557,26 +394,11 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazy_static" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lazycell" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libc" version = "0.2.40" @@ -587,14 +409,6 @@ name = "linked-hash-map" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "log" version = "0.4.1" @@ -603,11 +417,6 @@ dependencies = [ "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "matches" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "memchr" version = "2.0.1" @@ -621,67 +430,6 @@ name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio" -version = "0.6.14" -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)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "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 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (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.32 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "native-tls" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "net2" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nodrop" version = "0.1.12" @@ -708,29 +456,6 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "openssl" -version = "0.9.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (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.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-sys" -version = "0.9.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pbr" version = "1.0.1" @@ -743,11 +468,6 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "pkg-config" version = "0.3.11" @@ -828,18 +548,6 @@ dependencies = [ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "1.0.0" @@ -852,14 +560,6 @@ dependencies = [ "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex-syntax" version = "0.6.0" @@ -868,14 +568,6 @@ dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "remove_dir_all" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rust-crypto" version = "0.2.36" @@ -914,45 +606,11 @@ name = "safemem" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "schannel" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scoped-tls" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "security-framework" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework-sys" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "serde" version = "1.0.57" @@ -978,11 +636,6 @@ dependencies = [ "serde 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sha1" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "simplelog" version = "0.5.2" @@ -993,11 +646,6 @@ dependencies = [ "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "slab" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "sqlite" version = "0.23.9" @@ -1067,15 +715,6 @@ dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "term" version = "0.5.1" @@ -1130,177 +769,11 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tokio" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-core" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.14 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-executor" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-fs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-io" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (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.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (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.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-timer" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tls" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.1.5 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-udp" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ucd-util" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-width" version = "0.1.4" @@ -1324,62 +797,21 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "url" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "vcpkg" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "version_check" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "websocket" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.2.0 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "winapi" version = "0.2.8" @@ -1409,15 +841,6 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "yaml-rust" version = "0.3.5" @@ -1431,66 +854,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbdd17cd962b570302f5297aea8648d5923e22e555c2ed2d8b2e34eca646bf6d" "checksum backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "bff67d0c06556c0b8e6b5f090f0eac52d950d9dfd1d35ba04e4ca3543eaf6a7e" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" -"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" -"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" "checksum base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9263aa6a38da271eec5c91a83ce1e800f093c8535788d403d626d8d5c3f8f007" "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" -"checksum bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1d50c876fb7545f5f289cd8b2aee3f359d073ae819eed5d6373638e2c61e59" "checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba" "checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" -"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" -"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4e2817eb773f770dcb294127c011e22771899c21d18fce7dd739c0b9832e81" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" -"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-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.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" -"checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" -"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" -"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" -"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0" -"checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45" "checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" -"checksum openssl-sys 0.9.30 (registry+https://github.com/rust-lang/crates.io-index)" = "73ae718c3562989cd3a0a5c26610feca02f8116822f6f195e6cf4887481e57f5" "checksum pbr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "deb73390ab68d81992bd994d145f697451bb0b54fd39738e72eef32458ad6907" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" @@ -1501,27 +895,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" "checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3" -"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b" -"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustbreak 2.0.0-rc2 (registry+https://github.com/rust-lang/crates.io-index)" = "676cb04876f4391d5d2f2c9029d10cfe5fe28ad625ad8460531bed1191477083" "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" -"checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" -"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332" -"checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" "checksum serde 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)" = "9478f147957b713a156ce5e4529d77275bbcfddc29563b794939b36230df8ca8" "checksum serde_derive 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)" = "1bdba9c305f1aeff7e83e2ff0685a141780de943cee66bdd89b63913b2b69c86" "checksum serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ad6d546e765177cf3dded3c2e424a8040f870083a0e64064746b958ece9cb1" -"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum simplelog 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9cc12b39fdf4c9a07f88bffac2d628f0118ed5ac077a4b0feece61fadf1429e5" -"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum sqlite 0.23.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d18d7b10278336e7fd9dc259399a0f9ff419616738b6a841b136c362e16db626" "checksum sqlite3-src 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "46e0bc115b563b1ee6c665ef895b56bf488522f57d1c6571887547c57c8f5a88" "checksum sqlite3-sys 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71fec807a1534bd13eeaaec396175d67c79bdc68df55e18a452726ec62a8fb08" @@ -1530,45 +915,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syn 0.13.10 (registry+https://github.com/rust-lang/crates.io-index)" = "77961dcdac942fa8bc033c16f3a790b311c8a27d00811b878ebd8cf9b7ba39d5" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" -"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum tokio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d00555353b013e170ed8bc4e13f648a317d1fd12157dbcae13f7013f6cf29f5" -"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" -"checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" -"checksum tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76766830bbf9a2d5bfb50c95350d56a2e79e2c80f675967fff448bc615899708" -"checksum tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af9eb326f64b2d6b68438e1953341e00ab3cf54de7e35d92bfc73af8555313a" -"checksum tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3cedc8e5af5131dc3423ffa4f877cce78ad25259a9a62de0613735a13ebc64b" -"checksum tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec9b094851aadd2caf83ba3ad8e8c4ce65a42104f7b94d9e6550023f0407853f" -"checksum tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5783254b10c7c84a56f62c74766ef7e5b83d1f13053218c7cab8d3f2c826fa0e" -"checksum tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535fed0ccee189f3d48447587697ba3fd234b3dbbb091f0ec4613ddfec0a7c4c" -"checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913" -"checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"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-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum websocket 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eb277e7f4c23dc49176f74ae200e77651764efb2c25f56ad2d22623b63826369" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "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-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/Cargo.toml b/Cargo.toml index 7d75866b..7b11cf79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ license = "AGPL-3.0" [dependencies] duniter-core = { path = "./core" } duniter-tui = { path = "./tui" } -duniter-ws2p = { path = "./ws2p" } [features] # Treat warnings as a build error. @@ -27,5 +26,4 @@ members = [ "network", "tui", "wotb", - "ws2p", ] diff --git a/blockchain/apply_valid_block.rs b/blockchain/apply_valid_block.rs index 26b31cbc..c395d2fc 100644 --- a/blockchain/apply_valid_block.rs +++ b/blockchain/apply_valid_block.rs @@ -147,6 +147,7 @@ pub fn apply_valid_block<W: WebOfTrust, B: Backend + Debug>( wot_dbs_requests.push(WotsDBsWriteQuery::RevokeIdentity( compact_revoc.issuer, block.blockstamp(), + true, )); } for certification in block.certifications.clone() { diff --git a/blockchain/check_and_apply_block.rs b/blockchain/check_and_apply_block.rs index 21f4e567..2981adef 100644 --- a/blockchain/check_and_apply_block.rs +++ b/blockchain/check_and_apply_block.rs @@ -156,6 +156,7 @@ pub fn check_and_apply_block<W: WebOfTrust, B: Backend + Debug>( &dal_block, None, false, + false, ).expect("duniter_dal::writers::block::write() : DALError") } Block::LocalBlock(block_doc) => { @@ -173,6 +174,7 @@ pub fn check_and_apply_block<W: WebOfTrust, B: Backend + Debug>( &dal_block, old_fork_id, false, + false, ).expect("duniter_dal::writers::block::write() : DALError") } }; diff --git a/blockchain/dbex.rs b/blockchain/dbex.rs index 9999f311..6da2fa30 100644 --- a/blockchain/dbex.rs +++ b/blockchain/dbex.rs @@ -18,12 +18,19 @@ use duniter_dal::identity::DALIdentity; use duniter_documents::blockchain::v10::documents::transaction::*; use duniter_module::DuniterConf; use duniter_wotb::data::rusty::RustyWebOfTrust; +use duniter_wotb::operations::distance::{DistanceCalculator, WotDistance, WotDistanceParameters}; use std::time::*; use *; #[derive(Debug, Clone)] /// Query for wot databases explorer pub enum DBExWotQuery { + /// Ask distance of all members + AllDistances(bool), + /// Show members expire date + ExpireMembers(bool, bool), + /// Show members list + ListMembers(bool), /// Ask member datas MemberDatas(String), } @@ -69,7 +76,6 @@ pub fn dbex_tx(conf: &DuniterConf, query: &DBExTxQuery) { load_dbs_duration.subsec_nanos() / 1_000_000 ); let req_process_begin = SystemTime::now(); - match *query { DBExTxQuery::Balance(ref address_str) => { let pubkey = if let Ok(ed25519_pubkey) = ed25519::PublicKey::from_base58(address_str) { @@ -115,7 +121,8 @@ pub fn dbex_wot(conf: &DuniterConf, query: &DBExWotQuery) { // Open databases let load_dbs_begin = SystemTime::now(); - //let blocks_databases = BlocksV10DBs::open(&db_path, false); + let currency_params_db = + open_db::<CurrencyParamsV10Datas>(&db_path, "params.db").expect("Fail to open params db"); let wot_databases = WotsV10DBs::open(&db_path, false); let load_dbs_duration = SystemTime::now() .duration_since(load_dbs_begin) @@ -125,7 +132,11 @@ pub fn dbex_wot(conf: &DuniterConf, query: &DBExWotQuery) { load_dbs_duration.as_secs(), load_dbs_duration.subsec_nanos() / 1_000_000 ); - let req_process_begin = SystemTime::now(); + + // Get currency parameters + let currency_params = currency_params_db + .read(|db| CurrencyParameters::from(db.clone())) + .expect("Fail to parse currency params !"); // get wot_index let wot_index = DALIdentity::get_wotb_index(&wot_databases.identities_db).expect("DALError"); @@ -134,21 +145,126 @@ pub fn dbex_wot(conf: &DuniterConf, query: &DBExWotQuery) { let wot_reverse_index: HashMap<NodeId, &PubKey> = wot_index.iter().map(|(p, id)| (*id, p)).collect(); + // get wot uid index + let wot_uid_index: HashMap<NodeId, String> = wot_databases + .identities_db + .read(|db| { + db.iter() + .map(|(_, idty)| (idty.wot_id, String::from(idty.idty_doc.username()))) + .collect() + }) + .expect("Fail to read IdentitiesDB !"); + // Open wot db let wot_db = open_wot_db::<RustyWebOfTrust>(&db_path).expect("Fail to open WotDB !"); // Print wot blockstamp //println!("Wot : Current blockstamp = {}.", wot_blockstamp); - // Print members count + // Get members count let members_count = wot_db .read(|db| db.get_enabled()) .expect("Fail to read WotDB") .len(); - println!(" Members count = {}.", members_count); match *query { + DBExWotQuery::AllDistances(ref reverse) => { + println!("compute distances..."); + let compute_distances_begin = SystemTime::now(); + let mut distances_datas: Vec<(NodeId, WotDistance)> = wot_db + .read(|db| { + db.get_enabled() + .iter() + .map(|wot_id| { + ( + *wot_id, + DISTANCE_CALCULATOR + .compute_distance( + db, + WotDistanceParameters { + node: *wot_id, + sentry_requirement: 5, + step_max: currency_params.step_max as u32, + x_percent: currency_params.x_percent, + }, + ) + .expect("Fail to get distance !"), + ) + }) + .collect() + }) + .expect("Fail to read WotDB"); + let compute_distances_duration = SystemTime::now() + .duration_since(compute_distances_begin) + .expect("duration_since error"); + if *reverse { + distances_datas.sort_unstable_by(|(_, d1), (_, d2)| d1.success.cmp(&d2.success)); + } else { + distances_datas.sort_unstable_by(|(_, d1), (_, d2)| d2.success.cmp(&d1.success)); + } + for (wot_id, distance_datas) in distances_datas { + let distance_percent: f64 = + f64::from(distance_datas.success) / f64::from(distance_datas.sentries) * 100.0; + println!( + "{} -> distance: {:.2}% ({}/{})", + wot_uid_index[&wot_id], + distance_percent, + distance_datas.success, + distance_datas.sentries + ); + } + println!( + "compute_distances_duration = {},{:03}.", + compute_distances_duration.as_secs(), + compute_distances_duration.subsec_nanos() / 1_000_000 + ); + } + DBExWotQuery::ExpireMembers(ref reverse, ref _csv) => { + // Open blockchain database + let blockchain_db = open_db::<LocalBlockchainV10Datas>(&db_path, "blockchain.db") + .expect("Fail to open blockchain db"); + // Get blocks_times + let (current_bc_time, blocks_times): (u64, HashMap<BlockId, u64>) = blockchain_db + .read(|db| { + ( + db[&BlockId(db.len() as u32 - 1)].block.median_time, + db.iter() + .map(|(block_id, dal_block)| (*block_id, dal_block.block.median_time)) + .collect(), + ) + }) + .expect("Fail to read blockchain db"); + // Get expire_dates + let min_created_ms_time = current_bc_time - currency_params.ms_validity; + let mut expire_dates: Vec<(NodeId, u64)> = wot_databases + .ms_db + .read(|db| { + let mut expire_dates = Vec::new(); + for (block_id, nodes_ids) in db { + let created_ms_time = blocks_times[&block_id]; + if created_ms_time > min_created_ms_time { + for node_id in nodes_ids { + expire_dates.push(( + *node_id, + created_ms_time + currency_params.ms_validity, + )); + } + } + } + expire_dates + }) + .expect("Fail to read ms db"); + if *reverse { + expire_dates.sort_unstable_by(|(_, d1), (_, d2)| d1.cmp(&d2)); + } else { + expire_dates.sort_unstable_by(|(_, d1), (_, d2)| d2.cmp(&d1)); + } + for (node_id, expire_date) in expire_dates { + println!("{}, {}", wot_uid_index[&node_id], expire_date); + } + } DBExWotQuery::MemberDatas(ref uid) => { + println!(" Members count = {}.", members_count); if let Some(pubkey) = duniter_dal::identity::get_pubkey_from_uid(&wot_databases.identities_db, uid) .expect("get_pubkey_from_uid() : DALError !") @@ -160,6 +276,26 @@ pub fn dbex_wot(conf: &DuniterConf, query: &DBExWotQuery) { wot_id.0, pubkey.to_string() ); + let distance_datas = wot_db + .read(|db| { + DISTANCE_CALCULATOR.compute_distance( + db, + WotDistanceParameters { + node: wot_id, + sentry_requirement: 5, + step_max: currency_params.step_max as u32, + x_percent: currency_params.x_percent, + }, + ) + }) + .expect("Fail to read WotDB") + .expect("Fail to get distance !"); + let distance_percent: f64 = + f64::from(distance_datas.success) / f64::from(distance_datas.sentries) * 100.0; + println!( + "Distance {:.2}% ({}/{})", + distance_percent, distance_datas.success, distance_datas.sentries + ); let sources = wot_db .read(|db| db.get_links_source(wot_id)) .expect("Fail to read WotDB") @@ -177,13 +313,6 @@ pub fn dbex_wot(conf: &DuniterConf, query: &DBExWotQuery) { println!("Uid \"{}\" not found !", uid); } } + _ => {} } - let req_process_duration = SystemTime::now() - .duration_since(req_process_begin) - .expect("duration_since error"); - println!( - "Request processed in {}.{:06} seconds.", - req_process_duration.as_secs(), - req_process_duration.subsec_nanos() / 1_000 - ); } diff --git a/blockchain/lib.rs b/blockchain/lib.rs index c7ef4ec4..5bf4bcf2 100644 --- a/blockchain/lib.rs +++ b/blockchain/lib.rs @@ -74,6 +74,7 @@ use duniter_network::{ NetworkBlock, NetworkDocument, NetworkEvent, NetworkRequest, NetworkResponse, NodeFullId, }; use duniter_wotb::data::rusty::RustyWebOfTrust; +use duniter_wotb::operations::distance::RustyDistanceCalculator; use duniter_wotb::{NodeId, WebOfTrust}; use rustbreak::backend::{Backend, FileBackend}; @@ -83,6 +84,8 @@ pub static CHUNK_SIZE: &'static u32 = &50; pub static INFINITE_SIG_STOCK: &'static usize = &4_000_000_000; /// The blocks are requested by packet groups. This constant sets the number of packets per group. pub static MAX_BLOCKS_REQUEST: &'static u32 = &500; +/// The distance calculator +pub static DISTANCE_CALCULATOR: &'static RustyDistanceCalculator = &RustyDistanceCalculator {}; /// Blockchain Module #[derive(Debug)] @@ -193,17 +196,6 @@ impl BlockchainModule { } /// Synchronize blockchain from a duniter-ts database pub fn sync_ts(conf: &DuniterConf, ts_profile: &str, cautious: bool) { - // get databases path - let db_path = duniter_conf::get_blockchain_db_path(&conf.profile(), &conf.currency()); - // Open blocks dbs - let blocks_dbs = BlocksV10DBs::open(&db_path, false); - // Get local current blockstamp - debug!("Get local current blockstamp..."); - let current_blockstamp: Blockstamp = duniter_dal::block::get_current_blockstamp( - &blocks_dbs, - ).expect("ForksV10DB : RustBreakError !") - .unwrap_or_default(); - debug!("Success to get local current blockstamp."); // get db_ts_path let mut db_ts_path = match env::home_dir() { Some(path) => path, @@ -215,7 +207,7 @@ impl BlockchainModule { if !db_ts_path.as_path().exists() { panic!("Fatal error : duniter-ts database don't exist !"); } - sync::sync_ts(conf, ¤t_blockstamp, db_ts_path, cautious); + sync::sync_ts(conf, db_ts_path, cautious); } /// Request chunk from network (chunk = group of blocks) fn request_chunk(&self, req_id: &ModuleReqId, from: u32) -> (ModuleReqId, NetworkRequest) { diff --git a/blockchain/revert_valid_block.rs b/blockchain/revert_valid_block.rs new file mode 100644 index 00000000..4126ec45 --- /dev/null +++ b/blockchain/revert_valid_block.rs @@ -0,0 +1,235 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +use duniter_crypto::keys::*; +use duniter_dal::block::DALBlock; +use duniter_dal::sources::SourceAmount; +use duniter_dal::writers::requests::*; +use duniter_dal::{BinDB, ForkId}; +use duniter_documents::blockchain::v10::documents::transaction::{TxAmount, TxBase}; +use duniter_documents::blockchain::v10::documents::BlockDocument; +use duniter_documents::blockchain::Document; +use duniter_documents::BlockId; +use duniter_wotb::data::NewLinkResult; +use duniter_wotb::{NodeId, WebOfTrust}; +use rustbreak::backend::Backend; +use std::collections::HashMap; +use std::fmt::Debug; + +#[derive(Debug)] +/// Stores all queries to apply in database to "apply" the block +pub struct ValidBlockRevertReqs( + pub BlocksDBsWriteQuery, + pub Vec<WotsDBsWriteQuery>, + pub Vec<CurrencyDBsWriteQuery>, +); + +#[derive(Debug, Copy, Clone)] +/// RevertValidBlockError +pub enum RevertValidBlockError { + ExcludeUnknowNodeId(), + RevokeUnknowNodeId(), +} + +pub fn revert_valid_block<W: WebOfTrust, B: Backend + Debug>( + dal_block: &DALBlock, + wot_index: &mut HashMap<PubKey, NodeId>, + wot_db: &BinDB<W, B>, + expire_certs: &HashMap<(NodeId, NodeId), BlockId>, + to_fork_id: Option<ForkId>, +) -> Result<ValidBlockRevertReqs, RevertValidBlockError> { + // Revert DALBlock + let mut block = dal_block.block.clone(); + let expire_certs = dal_block.expire_certs.cloned().expect("Try to get expire_certs of an uncompleted block !"); + block.revert_reduce(); + let previous_blockcstamp = block.previous_blockstamp(); + let block_hash = block + .hash + .expect("Try to get hash of an uncompleted or reduce block !"); + debug!( + "BlockchainModule : revert_valid_block({})", + block.blockstamp() + ); + let mut wot_dbs_requests = Vec::new(); + let mut currency_dbs_requests = Vec::new(); + let current_blockstamp = block.blockstamp(); + // Revert transactions + for tx in block.transactions.clone() { + currency_dbs_requests.push(CurrencyDBsWriteQuery::RevertTx(Box::new(tx.unwrap_doc()))); + } + // Revert DU + if let Some(du_amount) = block.dividend { + if du_amount > 0 { + let members_wot_ids = wot_db + .read(|db| db.get_enabled()) + .expect("Fail to read WotDB"); + let mut members_pubkeys = Vec::new(); + for (pubkey, wotb_id) in wot_index { + if members_wot_ids.contains(wotb_id) { + members_pubkeys.push(*pubkey); + } + } + currency_dbs_requests.push(CurrencyDBsWriteQuery::RevertDU( + SourceAmount(TxAmount(du_amount as isize), TxBase(block.unit_base)), + block.number, + members_pubkeys, + )); + } + } + // Revert expire_certs + for ((source, target), created_block_id) in expire_certs { + wot_dbs_requests.push(WotsDBsWriteQuery::RevertExpireCert( + *source, + *target, + *created_block_id, + )); + } + // Revert certifications + for certification in block.certifications.clone() { + trace!("stack_up_valid_block: apply cert..."); + let compact_cert = certification.to_compact_document(); + let wotb_node_from = wot_index[&compact_cert.issuer]; + let wotb_node_to = wot_index[&compact_cert.target]; + wot_db + .write(|db| { + let result = db.add_link(wotb_node_from, wotb_node_to); + match result { + NewLinkResult::Ok(_) => {} + _ => panic!( + "Fail to add_link {}->{} : {:?}", + wotb_node_from.0, wotb_node_to.0, result + ), + } + }) + .expect("Fail to read WotDB"); + wot_dbs_requests.push(WotsDBsWriteQuery::CreateCert( + compact_cert.issuer, + wotb_node_from, + wotb_node_to, + compact_cert.block_number, + block.median_time, + )); + trace!("stack_up_valid_block: apply cert...success."); + } + // Revert revocations + for revocation in block.revoked.clone() { + let compact_revoc = revocation.to_compact_document(); + let wot_id = if let Some(wot_id) = wot_index.get(&compact_revoc.issuer) { + wot_id + } else { + return Err(ApplyValidBlockError::RevokeUnknowNodeId()); + }; + wot_db + .write(|db| { + db.set_enabled(*wot_id, false); + }) + .expect("Fail to write in WotDB"); + wot_dbs_requests.push(WotsDBsWriteQuery::RevokeIdentity( + compact_revoc.issuer, + block.blockstamp(), + true, + )); + } + // Revert exclusions + for exclusion in block.excluded.clone() { + let wot_id = if let Some(wot_id) = wot_index.get(&exclusion) { + wot_id + } else { + return Err(ApplyValidBlockError::ExcludeUnknowNodeId()); + }; + wot_db + .write(|db| { + db.set_enabled(*wot_id, false); + }) + .expect("Fail to write in WotDB"); + wot_dbs_requests.push(WotsDBsWriteQuery::ExcludeIdentity( + exclusion, + block.blockstamp(), + )); + } + // Revert renewals + for active in block.actives.clone() { + let pubkey = active.issuers()[0]; + if !identities.contains_key(&pubkey) { + let wotb_id = wot_index[&pubkey]; + wot_db + .write(|db| { + db.set_enabled(wotb_id, true); + }) + .expect("Fail to write in WotDB"); + wot_dbs_requests.push(WotsDBsWriteQuery::RenewalIdentity( + pubkey, + wotb_id, + block.median_time, + active.blockstamp().id, + )); + } + } + // Revert joiners + for joiner in block.joiners.clone() { + let pubkey = joiner.clone().issuers()[0]; + if let Some(idty_doc) = identities.get(&pubkey) { + // Newcomer + let wotb_id = NodeId( + wot_db + .read(|db| db.size()) + .expect("Fatal error : fail to read WotDB !"), + ); + wot_db + .write(|db| { + db.add_node(); + }) + .expect("Fail to write in WotDB"); + wot_index.insert(pubkey, wotb_id); + wot_dbs_requests.push(WotsDBsWriteQuery::CreateIdentity( + wotb_id, + current_blockstamp, + block.median_time, + Box::new(idty_doc.clone()), + joiner.blockstamp().id, + )); + } else { + // Renewer + let wotb_id = wot_index[&joiner.issuers()[0]]; + wot_db + .write(|db| { + db.set_enabled(wotb_id, true); + }) + .expect("Fail to write in WotDB"); + wot_dbs_requests.push(WotsDBsWriteQuery::RenewalIdentity( + joiner.issuers()[0], + wotb_id, + block.median_time, + joiner.blockstamp().id, + )); + } + } + // Revert identities + let mut identities = HashMap::with_capacity(block.identities.len()); + for identity in block.identities.clone() { + identities.insert(identity.issuers()[0], identity); + } + // Return DBs requests + Ok(ValidBlockApplyReqs( + BlocksDBsWriteQuery::WriteBlock( + Box::new(dal_block), + to_fork_id, + previous_blockcstamp, + block_hash, + ), + wot_dbs_requests, + currency_dbs_requests, + )) +} diff --git a/blockchain/sync.rs b/blockchain/sync.rs index 2f5c2f0f..01381aea 100644 --- a/blockchain/sync.rs +++ b/blockchain/sync.rs @@ -67,23 +67,27 @@ enum SyncJobsMess { } /// Sync from a duniter-ts database -pub fn sync_ts( - conf: &DuniterConf, - current_blockstamp: &Blockstamp, - db_ts_path: PathBuf, - cautious: bool, -) { +pub fn sync_ts(conf: &DuniterConf, db_ts_path: PathBuf, cautious: bool) { // get profile and currency and current_blockstamp let profile = &conf.profile(); let currency = &conf.currency(); - let mut current_blockstamp = *current_blockstamp; - // Get wot path + // Get databases path let db_path = duniter_conf::get_blockchain_db_path(&profile, ¤cy); // Open wot db let wot_db = open_wot_db::<RustyWebOfTrust>(&db_path).expect("Fail to open WotDB !"); + // Open blocks databases + let databases = BlocksV10DBs::open(&db_path, false); + + // Get local current blockstamp + debug!("Get local current blockstamp..."); + let mut current_blockstamp: Blockstamp = duniter_dal::block::get_current_blockstamp(&databases) + .expect("ForksV10DB : RustBreakError !") + .unwrap_or_default(); + debug!("Success to get local current blockstamp."); + // Get verification level let _verif_level = if cautious { println!("Start cautious sync..."); @@ -275,14 +279,9 @@ pub fn sync_ts( let (sender_wot_thread, recv_wot_thread) = mpsc::channel(); // Launch blocks_worker thread - let profile_copy = conf.profile().clone(); - let currency_copy = conf.currency().clone(); let sender_sync_thread_clone = sender_sync_thread.clone(); pool.execute(move || { let blocks_job_begin = SystemTime::now(); - // Open databases - let db_path = duniter_conf::get_blockchain_db_path(&profile_copy, ¤cy_copy); - let databases = BlocksV10DBs::open(&db_path, false); // Listen db requets let mut chunk_index = 0; @@ -441,6 +440,11 @@ pub fn sync_ts( }); let main_job_begin = SystemTime::now(); + // Open currency_params_db + let dbs_path = duniter_conf::get_blockchain_db_path(&conf.profile(), &conf.currency()); + let currency_params_db = + open_db::<CurrencyParamsV10Datas>(&dbs_path, "params.db").expect("Fail to open params db"); + // Apply blocks let mut blocks_not_expiring = VecDeque::with_capacity(200_000); let mut last_block_expiring: isize = -1; @@ -467,6 +471,12 @@ pub fn sync_ts( if !get_currency_params { if block_doc.number.0 == 0 { if block_doc.parameters.is_some() { + currency_params_db + .write(|db| { + db.0 = block_doc.currency.clone(); + db.1 = block_doc.parameters.unwrap(); + }) + .expect("fail to write in params DB"); currency_params = CurrencyParameters::from(( block_doc.currency.clone(), block_doc.parameters.unwrap(), @@ -475,8 +485,6 @@ pub fn sync_ts( } else { panic!("The genesis block are None parameters !"); } - } else { - panic!("The first block is not genesis !"); } } // Push block median_time in blocks_not_expiring @@ -582,6 +590,9 @@ pub fn sync_ts( .expect("Sync : Fail to send End signal to writer worker !"); info!("Sync : send End signal to tx job."); + // Save params db + currency_params_db.save().expect("Fail to save params db"); + // Save wot file wot_db.save().expect("Fail to save wotb db"); diff --git a/core/cli/en.yml b/core/cli/en.yml index ff97559f..f2957807 100644 --- a/core/cli/en.yml +++ b/core/cli/en.yml @@ -43,9 +43,23 @@ subcommands: about: durs databases explorer version: "0.1.0" author: Elois L. <elois@duniter.org> + args: + - csv: + short: c + long: csv + help: csv output subcommands: + - distances: + about: durs databases explorer (distances datas) + version: "0.1.0" + author: Elois L. <elois@duniter.org> + args: + - reverse: + short: r + long: reverse + help: reverse order - member: - about: durs databases explorer (wot members datas) + about: durs databases explorer (wot member datas) version: "0.1.0" author: Elois L. <elois@duniter.org> args: @@ -53,6 +67,19 @@ subcommands: help : choose member uid index: 1 required: true + - members: + about: durs databases explorer (wot members datas) + version: "0.1.0" + author: Elois L. <elois@duniter.org> + args: + - expire: + short: e + long: expire + help: show members expire date + - reverse: + short: r + long: reverse + help: reverse order - balance: about: durs databases explorer (balances datas) version: "0.1.0" diff --git a/core/lib.rs b/core/lib.rs index 773a77f7..574bd781 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -125,12 +125,37 @@ impl DuniterCore { sync_ts(&conf, ts_profile, matches.is_present("cautious")); None } else if let Some(matches) = cli_args.subcommand_matches("dbex") { - if let Some(member_matches) = matches.subcommand_matches("member") { + let csv = matches.is_present("csv"); + if let Some(distances_matches) = matches.subcommand_matches("distances") { + dbex( + &conf, + &DBExQuery::WotQuery(DBExWotQuery::AllDistances( + distances_matches.is_present("reverse"), + )), + ); + } else if let Some(member_matches) = matches.subcommand_matches("member") { let uid = member_matches.value_of("UID").unwrap_or(""); dbex( &conf, &DBExQuery::WotQuery(DBExWotQuery::MemberDatas(String::from(uid))), ); + } else if let Some(members_matches) = matches.subcommand_matches("members") { + if members_matches.is_present("expire") { + dbex( + &conf, + &DBExQuery::WotQuery(DBExWotQuery::ExpireMembers( + members_matches.is_present("reverse"), + csv, + )), + ); + } else { + dbex( + &conf, + &DBExQuery::WotQuery(DBExWotQuery::ListMembers( + members_matches.is_present("reverse"), + )), + ); + } } else if let Some(balance_matches) = matches.subcommand_matches("balance") { let address = balance_matches.value_of("ADDRESS").unwrap_or(""); dbex( diff --git a/dal/identity.rs b/dal/identity.rs index 38ee0955..7f1f3edb 100644 --- a/dal/identity.rs +++ b/dal/identity.rs @@ -25,7 +25,7 @@ pub struct DALIdentity { pub expired_on: Option<Blockstamp>, pub revoked_on: Option<Blockstamp>, pub idty_doc: IdentityDocument, - pub wotb_id: NodeId, + pub wot_id: NodeId, pub ms_chainable_on: Vec<u64>, pub cert_chainable_on: Vec<u64>, } @@ -100,35 +100,13 @@ impl DALIdentity { Ok(identities_db.read(|db| { let mut wotb_index: HashMap<PubKey, NodeId> = HashMap::new(); for (pubkey, member_datas) in db { - let wotb_id = member_datas.wotb_id; + let wotb_id = member_datas.wot_id; wotb_index.insert(*pubkey, wotb_id); } wotb_index })?) } - pub fn create_identity( - currency_params: &CurrencyParameters, - idty_doc: &IdentityDocument, - wotb_id: NodeId, - current_blockstamp: Blockstamp, - current_bc_time: u64, - ) -> DALIdentity { - let mut idty_doc = idty_doc.clone(); - idty_doc.reduce(); - DALIdentity { - hash: "0".to_string(), - state: DALIdentityState::Member(vec![0]), - joined_on: current_blockstamp, - expired_on: None, - revoked_on: None, - idty_doc, - wotb_id, - ms_chainable_on: vec![current_bc_time + currency_params.ms_period], - cert_chainable_on: vec![], - } - } - pub fn revoke_identity<B: Backend + Debug>( identities_db: &BinDB<IdentitiesV10Datas, B>, pubkey: &PubKey, diff --git a/dal/lib.rs b/dal/lib.rs index 3704a8db..d6e4196a 100644 --- a/dal/lib.rs +++ b/dal/lib.rs @@ -50,6 +50,7 @@ pub mod tools; pub mod writers; use duniter_crypto::keys::*; +use duniter_documents::blockchain::v10::documents::block::{BlockV10Parameters, CurrencyName}; use duniter_documents::blockchain::v10::documents::transaction::*; use duniter_documents::{BlockHash, BlockId, Blockstamp, Hash, PreviousBlockstamp}; use duniter_wotb::{NodeId, WebOfTrust}; @@ -73,6 +74,7 @@ use writers::transaction::DALTxV10; /// Each fork has a unique identifier. The local blockchain (also called local branch) has ForkId equal to zero. pub struct ForkId(pub usize); +pub type CurrencyParamsV10Datas = (CurrencyName, BlockV10Parameters); pub type LocalBlockchainV10Datas = HashMap<BlockId, DALBlock>; pub type ForksV10Datas = HashMap<ForkId, HashMap<PreviousBlockstamp, BlockHash>>; pub type ForksBlocksV10Datas = HashMap<Blockstamp, DALBlock>; diff --git a/dal/writers/block.rs b/dal/writers/block.rs index e86bf9f6..3d8ae895 100644 --- a/dal/writers/block.rs +++ b/dal/writers/block.rs @@ -1,6 +1,6 @@ use block::DALBlock; use duniter_documents::blockchain::Document; -use duniter_documents::{BlockHash, BlockId, Blockstamp, PreviousBlockstamp}; +use duniter_documents::{BlockHash, BlockId, PreviousBlockstamp}; use std::collections::HashMap; use ForkId; use {BinFileDB, DALError, ForksBlocksV10Datas, ForksV10Datas, LocalBlockchainV10Datas}; @@ -11,41 +11,65 @@ pub fn write( forks_db: &BinFileDB<ForksV10Datas>, forks_blocks_db: &BinFileDB<ForksBlocksV10Datas>, dal_block: &DALBlock, - old_fork_id: Option<ForkId>, + from_to_fork_id: Option<ForkId>, sync: bool, + revert: bool, ) -> Result<(), DALError> { if dal_block.fork_id.0 == 0 { blockchain_db.write(|db| { - db.insert(dal_block.block.number, dal_block.clone()); + if revert { + db.remove(&dal_block.block.number); + } else { + db.insert(dal_block.block.number, dal_block.clone()); + } })?; - if old_fork_id.is_some() { + if from_to_fork_id.is_some() { forks_blocks_db.write(|db| { db.remove(&dal_block.block.blockstamp()); })?; } } - if let Some(old_fork_id) = old_fork_id { - forks_db.write(|db| { - let mut fork_meta_datas = db - .get(&old_fork_id) - .expect("old_fork_id don(t exist !") - .clone(); - let previous_blockstamp = Blockstamp { - id: BlockId(dal_block.block.blockstamp().id.0 - 1), - hash: dal_block - .block - .hash - .expect("Try to get hash of an uncompleted or reduce block !"), - }; - fork_meta_datas.remove(&previous_blockstamp); - db.insert(old_fork_id, fork_meta_datas); - if dal_block.fork_id.0 > 0 { - let mut fork_meta_datas = db.get(&dal_block.fork_id).unwrap().clone(); - fork_meta_datas.insert(previous_blockstamp, dal_block.block.hash.unwrap()); - db.insert(old_fork_id, fork_meta_datas); - } - })?; + // Move block in a fork + if revert { + if let Some(to_fork_id) = from_to_fork_id { + forks_db.write(|db| { + let previous_blockstamp = dal_block.block.previous_blockstamp(); + let mut fork_meta_datas = db.get(&to_fork_id).unwrap().clone(); + fork_meta_datas.insert( + previous_blockstamp, + dal_block + .block + .hash + .expect("Try to get hash of a reduce block !"), + ); + db.insert(to_fork_id, fork_meta_datas); + })?; + } + } else { + if let Some(from_fork_id) = from_to_fork_id { + // Remove block in fork origin + forks_db.write(|db| { + let mut fork_meta_datas = db + .get(&from_fork_id) + .expect("from_fork_id don(t exist !") + .clone(); + let previous_blockstamp = dal_block.block.previous_blockstamp(); + fork_meta_datas.remove(&previous_blockstamp); + db.insert(from_fork_id, fork_meta_datas); + if dal_block.fork_id.0 > 0 { + let mut fork_meta_datas = db.get(&dal_block.fork_id).unwrap().clone(); + fork_meta_datas.insert( + previous_blockstamp, + dal_block + .block + .hash + .expect("Try to get hash of a reduce block !"), + ); + db.insert(from_fork_id, fork_meta_datas); + } + })?; + } } if !sync { let mut blockchain_meta_datas: HashMap<PreviousBlockstamp, BlockHash> = forks_db diff --git a/dal/writers/certification.rs b/dal/writers/certification.rs index 5f593fcb..5393a855 100644 --- a/dal/writers/certification.rs +++ b/dal/writers/certification.rs @@ -32,6 +32,7 @@ pub fn write_certification( target: NodeId, created_block_id: BlockId, written_timestamp: u64, + _revert: bool, ) -> Result<(), DALError> { // Get cert_chainable_on let mut member_datas = identities_db.read(|db| { diff --git a/dal/writers/dividend.rs b/dal/writers/dividend.rs index 7f7a4a35..3071e6c6 100644 --- a/dal/writers/dividend.rs +++ b/dal/writers/dividend.rs @@ -28,12 +28,17 @@ pub fn create_du<B: Backend + Debug>( du_amount: &SourceAmount, du_block_id: &BlockId, members: &[PubKey], + revert: bool, ) -> Result<(), DALError> { - // Insert DU sources in DUsV10DB + // Insert/Remove DU sources in DUsV10DB du_db.write(|db| { for pubkey in members { let mut pubkey_dus = db.get(&pubkey).cloned().unwrap_or_default(); - pubkey_dus.insert(*du_block_id); + if revert { + pubkey_dus.remove(du_block_id); + } else { + pubkey_dus.insert(*du_block_id); + } db.insert(*pubkey, pubkey_dus); } })?; @@ -52,11 +57,15 @@ pub fn create_du<B: Backend + Debug>( } members_balances })?; - // Increment members balance + // Increase/Decrease members balance let members_balances: Vec<(PubKey, (SourceAmount, HashSet<UTXOIndexV10>))> = members_balances .iter() .map(|(pubkey, (balance, utxos_indexs))| { - let new_balance = *balance + *du_amount; + let new_balance = if revert { + *balance - *du_amount + } else { + *balance + *du_amount + }; (*pubkey, (new_balance, utxos_indexs.clone())) }) .collect(); diff --git a/dal/writers/identity.rs b/dal/writers/identity.rs index 214f4dbd..2bc5d5ce 100644 --- a/dal/writers/identity.rs +++ b/dal/writers/identity.rs @@ -1,16 +1,35 @@ -use super::super::identity::DALIdentity; +use currency_params::CurrencyParameters; +use duniter_documents::blockchain::v10::documents::IdentityDocument; use duniter_documents::blockchain::Document; -use duniter_documents::BlockId; +use duniter_documents::{BlockId, Blockstamp}; use duniter_wotb::NodeId; +use identity::{DALIdentity, DALIdentityState}; use {BinFileDB, DALError, IdentitiesV10Datas, MsExpirV10Datas}; -pub fn write( - idty: &DALIdentity, - idty_wot_id: NodeId, +pub fn create_identity( + currency_params: &CurrencyParameters, identities_db: &BinFileDB<IdentitiesV10Datas>, ms_db: &BinFileDB<MsExpirV10Datas>, + idty_doc: &IdentityDocument, ms_created_block_id: BlockId, + wot_id: NodeId, + current_blockstamp: Blockstamp, + current_bc_time: u64, + _revert: bool, ) -> Result<(), DALError> { + let mut idty_doc = idty_doc.clone(); + idty_doc.reduce(); + let idty = DALIdentity { + hash: "0".to_string(), + state: DALIdentityState::Member(vec![0]), + joined_on: current_blockstamp, + expired_on: None, + revoked_on: None, + idty_doc, + wot_id, + ms_chainable_on: vec![current_bc_time + currency_params.ms_period], + cert_chainable_on: vec![], + }; // Write Identity identities_db.write(|db| { db.insert(idty.idty_doc.issuers()[0], idty.clone()); @@ -18,7 +37,7 @@ pub fn write( // Update IdentitiesV10DB ms_db.write(|db| { let mut memberships = db.get(&ms_created_block_id).cloned().unwrap_or_default(); - memberships.insert(idty_wot_id); + memberships.insert(wot_id); db.insert(ms_created_block_id, memberships); })?; Ok(()) diff --git a/dal/writers/requests.rs b/dal/writers/requests.rs index ef5ca621..42152dc9 100644 --- a/dal/writers/requests.rs +++ b/dal/writers/requests.rs @@ -31,29 +31,50 @@ pub enum BlocksDBsWriteQuery { /// Write block WriteBlock(Box<DALBlock>, Option<ForkId>, PreviousBlockstamp, BlockHash), /// Revert block - RevertBlock(Box<DALBlock>), + RevertBlock(Box<DALBlock>, Option<ForkId>, PreviousBlockstamp, BlockHash), } impl BlocksDBsWriteQuery { pub fn apply(&self, databases: &BlocksV10DBs, sync: bool) -> Result<(), DALError> { - if let BlocksDBsWriteQuery::WriteBlock( - ref dal_block, - ref old_fork_id, - ref _previous_blockstamp, - ref _block_hash, - ) = *self - { - let dal_block = dal_block.deref(); - trace!("BlocksDBsWriteQuery::WriteBlock..."); - super::block::write( - &databases.blockchain_db, - &databases.forks_db, - &databases.forks_blocks_db, - &dal_block, - *old_fork_id, - sync, - )?; - trace!("BlocksDBsWriteQuery::WriteBlock...finish"); + match *self { + BlocksDBsWriteQuery::WriteBlock( + ref dal_block, + ref old_fork_id, + ref _previous_blockstamp, + ref _block_hash, + ) => { + let dal_block = dal_block.deref(); + trace!("BlocksDBsWriteQuery::WriteBlock..."); + super::block::write( + &databases.blockchain_db, + &databases.forks_db, + &databases.forks_blocks_db, + &dal_block, + *old_fork_id, + sync, + false, + )?; + trace!("BlocksDBsWriteQuery::WriteBlock...finish"); + } + BlocksDBsWriteQuery::RevertBlock( + ref dal_block, + ref old_fork_id, + ref _previous_blockstamp, + ref _block_hash, + ) => { + let dal_block = dal_block.deref(); + trace!("BlocksDBsWriteQuery::WriteBlock..."); + super::block::write( + &databases.blockchain_db, + &databases.forks_db, + &databases.forks_blocks_db, + &dal_block, + *old_fork_id, + sync, + true, + )?; + trace!("BlocksDBsWriteQuery::WriteBlock...finish"); + } } Ok(()) } @@ -64,16 +85,28 @@ impl BlocksDBsWriteQuery { pub enum WotsDBsWriteQuery { /// Newcomer (wotb_id, blockstamp, current_bc_time, idty_doc, ms_created_block_id) CreateIdentity(NodeId, Blockstamp, u64, Box<IdentityDocument>, BlockId), + /// Revert newcomer event (wotb_id, blockstamp, current_bc_time, idty_doc, ms_created_block_id) + RevertCreateIdentity(NodeId, Blockstamp, u64, Box<IdentityDocument>, BlockId), /// Active (pubKey, idty_wot_id, current_bc_time, ms_created_block_id) RenewalIdentity(PubKey, NodeId, u64, BlockId), + /// Revert active (pubKey, idty_wot_id, current_bc_time, ms_created_block_id) + RevertRenewalIdentity(PubKey, NodeId, u64, BlockId), /// Excluded ExcludeIdentity(PubKey, Blockstamp), + /// Revert exclusion + RevertExcludeIdentity(PubKey, Blockstamp), /// Revoked - RevokeIdentity(PubKey, Blockstamp), + RevokeIdentity(PubKey, Blockstamp, bool), + /// Revert revocation + RevertRevokeIdentity(PubKey, Blockstamp, bool), /// Certification (source_pubkey, source, target, created_block_id, median_time) CreateCert(PubKey, NodeId, NodeId, BlockId, u64), + /// Revert certification (source_pubkey, source, target, created_block_id, median_time) + RevertCert(PubKey, NodeId, NodeId, BlockId, u64), /// Certification expiry (source, target, created_block_id) ExpireCert(NodeId, NodeId, BlockId), + /// Revert certification expiry event (source, target, created_block_id) + RevertExpireCert(NodeId, NodeId, BlockId), } impl WotsDBsWriteQuery { @@ -90,22 +123,36 @@ impl WotsDBsWriteQuery { ref idty_doc, ref ms_created_block_id, ) => { - trace!("WotsDBsWriteQuery::CreateIdentity..."); - let idty = DALIdentity::create_identity( + writers::identity::create_identity( currency_params, + &databases.identities_db, + &databases.ms_db, idty_doc.deref(), + *ms_created_block_id, *wotb_id, *blockstamp, *current_bc_time, - ); - super::identity::write( - &idty, - *wotb_id, + false, + )?; + } + WotsDBsWriteQuery::RevertCreateIdentity( + ref wotb_id, + ref blockstamp, + ref current_bc_time, + ref idty_doc, + ref ms_created_block_id, + ) => { + writers::identity::create_identity( + currency_params, &databases.identities_db, &databases.ms_db, + idty_doc.deref(), *ms_created_block_id, + *wotb_id, + *blockstamp, + *current_bc_time, + true, )?; - trace!("WotsDBsWriteQuery::CreateIdentity...finish."); } WotsDBsWriteQuery::RenewalIdentity( ref pubkey, @@ -128,18 +175,49 @@ impl WotsDBsWriteQuery { )?; trace!("DBWrWotsDBsWriteQueryiteRequest::RenewalIdentity..."); } + WotsDBsWriteQuery::RevertRenewalIdentity( + ref pubkey, + ref idty_wot_id, + ref current_bc_time, + ms_created_block_id, + ) => { + let mut idty = DALIdentity::get_identity(&databases.identities_db, pubkey)? + .expect("Fatal error : impossible to renewal an identidy that don't exist !"); + idty.renewal_identity( + currency_params, + &databases.identities_db, + &databases.ms_db, + pubkey, + *idty_wot_id, + *current_bc_time, + ms_created_block_id, + true, + )?; + } WotsDBsWriteQuery::ExcludeIdentity(ref pubkey, ref blockstamp) => { DALIdentity::exclude_identity(&databases.identities_db, pubkey, blockstamp, false)?; } - WotsDBsWriteQuery::RevokeIdentity(ref pubkey, ref blockstamp) => { + WotsDBsWriteQuery::RevertExcludeIdentity(ref pubkey, ref blockstamp) => { + DALIdentity::exclude_identity(&databases.identities_db, pubkey, blockstamp, true)?; + } + WotsDBsWriteQuery::RevokeIdentity(ref pubkey, ref blockstamp, ref explicit) => { DALIdentity::revoke_identity( &databases.identities_db, pubkey, blockstamp, - true, + *explicit, false, )?; } + WotsDBsWriteQuery::RevertRevokeIdentity(ref pubkey, ref blockstamp, ref explicit) => { + DALIdentity::revoke_identity( + &databases.identities_db, + pubkey, + blockstamp, + *explicit, + true, + )?; + } WotsDBsWriteQuery::CreateCert( ref source_pubkey, ref source, @@ -157,6 +235,28 @@ impl WotsDBsWriteQuery { *target, *created_block_id, *median_time, + false, + )?; + trace!("WotsDBsWriteQuery::CreateCert...finish"); + } + WotsDBsWriteQuery::RevertCert( + ref source_pubkey, + ref source, + ref target, + ref created_block_id, + ref median_time, + ) => { + trace!("WotsDBsWriteQuery::CreateCert..."); + super::certification::write_certification( + currency_params, + &databases.identities_db, + &databases.certs_db, + *source_pubkey, + *source, + *target, + *created_block_id, + *median_time, + true, )?; trace!("WotsDBsWriteQuery::CreateCert...finish"); } @@ -166,6 +266,20 @@ impl WotsDBsWriteQuery { *source, *target, *created_block_id, + false, + )?;*/ + } + WotsDBsWriteQuery::RevertExpireCert( + ref _source, + ref _target, + ref _created_block_id, + ) => { + /*super::certification::expire_cert( + &databases.certs_db, + *source, + *target, + *created_block_id, + true, )?;*/ } } @@ -178,8 +292,12 @@ impl WotsDBsWriteQuery { pub enum CurrencyDBsWriteQuery { /// Write transaction WriteTx(Box<TransactionDocument>), + /// Revert transaction + RevertTx(Box<TransactionDocument>), /// Create dividend CreateDU(SourceAmount, BlockId, Vec<PubKey>), + /// Revert dividend + RevertDU(SourceAmount, BlockId, Vec<PubKey>), } impl CurrencyDBsWriteQuery { @@ -192,6 +310,17 @@ impl CurrencyDBsWriteQuery { &databases.du_db, &databases.balances_db, tx_doc.deref(), + false, + )?; + } + CurrencyDBsWriteQuery::RevertTx(ref tx_doc) => { + super::transaction::apply_and_write_tx::<B>( + &databases.tx_db, + &databases.utxos_db, + &databases.du_db, + &databases.balances_db, + tx_doc.deref(), + true, )?; } CurrencyDBsWriteQuery::CreateDU(ref du_amount, ref block_id, ref members) => { @@ -201,6 +330,17 @@ impl CurrencyDBsWriteQuery { du_amount, block_id, members, + false, + )?; + } + CurrencyDBsWriteQuery::RevertDU(ref du_amount, ref block_id, ref members) => { + super::dividend::create_du::<B>( + &databases.du_db, + &databases.balances_db, + du_amount, + block_id, + members, + true, )?; } } diff --git a/dal/writers/transaction.rs b/dal/writers/transaction.rs index 662dc171..f0320d1c 100644 --- a/dal/writers/transaction.rs +++ b/dal/writers/transaction.rs @@ -43,6 +43,7 @@ pub fn apply_and_write_tx<B: Backend + Debug>( dus_db: &BinDB<DUsV10Datas, B>, balances_db: &BinDB<BalancesV10Datas, B>, tx_doc: &TransactionDocument, + _revert: bool, ) -> Result<(), DALError> { let mut tx_doc = tx_doc.clone(); let tx_hash = tx_doc.get_hash(); @@ -274,6 +275,7 @@ mod tests { &SourceAmount(TxAmount(1000), TxBase(0)), &BlockId(1), &vec![tx_doc.issuers()[0], tortue_pubkey], + false, ).expect("Fail to create first g1 DU !"); // Check members balance let cgeek_new_balance = currency_dbs @@ -306,6 +308,7 @@ mod tests { ¤cy_dbs.du_db, ¤cy_dbs.balances_db, &tx_doc, + false, ).expect("Fail to apply first g1 tx"); // Check issuer new balance let cgeek_new_balance = currency_dbs diff --git a/documents/blockchain/v10/documents/block.rs b/documents/blockchain/v10/documents/block.rs index 5cc23ba3..10a3954b 100644 --- a/documents/blockchain/v10/documents/block.rs +++ b/documents/blockchain/v10/documents/block.rs @@ -34,6 +34,12 @@ use {BlockHash, BlockId, Blockstamp, Hash}; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct CurrencyName(pub String); +impl Default for CurrencyName { + fn default() -> CurrencyName { + CurrencyName(String::from("default_currency")) + } +} + impl Display for CurrencyName { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "{}", self.0) @@ -322,6 +328,19 @@ impl BlockDocument { self.leavers.iter_mut().map(|i| i.reduce()).collect::<()>(); self.transactions = self.transactions.iter_mut().map(|t| t.reduce()).collect(); } + /// Revert reduce method + pub fn revert_reduce(&mut self) { + /*self.identities + .iter_mut() + .map(|i| i.reduce()) + .collect::<()>(); + self.joiners.iter_mut().map(|i| i.reduce()).collect::<()>(); + self.actives.iter_mut().map(|i| i.reduce()).collect::<()>(); + self.leavers.iter_mut().map(|i| i.reduce()).collect::<()>(); + self.transactions = self.transactions.iter_mut().map(|t| t.reduce()).collect();*/ + self.compute_inner_hash(); + //self.hash = self.compute_hash(); + } /// Generate compact inner text (for compute inner_hash) pub fn generate_compact_inner_text(&self) -> String { let mut identities_str = String::from(""); diff --git a/documents/lib.rs b/documents/lib.rs index f39b5f5d..4d006cb6 100644 --- a/documents/lib.rs +++ b/documents/lib.rs @@ -43,7 +43,7 @@ use std::fmt::{Debug, Display, Error, Formatter}; pub mod blockchain; /// A block Id. -#[derive(Debug, Deserialize, Copy, Clone, Ord, PartialEq, PartialOrd, Eq, Hash, Serialize)] +#[derive(Copy, Clone, Debug, Deserialize, Ord, PartialEq, PartialOrd, Eq, Hash, Serialize)] pub struct BlockId(pub u32); impl Display for BlockId { diff --git a/src/main.rs b/src/main.rs index c9e127fb..ddf66d52 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,11 +24,11 @@ extern crate duniter_core; extern crate duniter_tui; -extern crate duniter_ws2p; +//extern crate duniter_ws2p; pub use duniter_core::DuniterCore; pub use duniter_tui::TuiModule; -pub use duniter_ws2p::WS2PModule; +//pub use duniter_ws2p::WS2PModule; /// Main function fn main() { @@ -38,7 +38,7 @@ fn main() { // Run duniter core if let Some(mut duniter_core) = DuniterCore::new(soft_name, soft_version) { - duniter_core.plug::<WS2PModule>(); + //duniter_core.plug::<WS2PModule>(); duniter_core.plug::<TuiModule>(); //duniter_core.plug::<PoolModule>(); //duniter_core.plug::<PowModule>(); diff --git a/wotb/data/mod.rs b/wotb/data/mod.rs index fe6beec4..e88b6933 100644 --- a/wotb/data/mod.rs +++ b/wotb/data/mod.rs @@ -19,14 +19,68 @@ pub mod rusty; -use serde::de::DeserializeOwned; -use serde::Serialize; -use std::fmt::Debug; +use serde::de::{self, Deserialize, DeserializeOwned, Deserializer, Visitor}; +use serde::{Serialize, Serializer}; +use std::fmt::{self, Debug}; /// Wrapper for a node id. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct NodeId(pub usize); +impl Serialize for NodeId { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_u32(self.0 as u32) + } +} + +struct NodeIdVisitor; + +impl<'de> Visitor<'de> for NodeIdVisitor { + type Value = NodeId; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an integer between -2^31 and 2^31") + } + + fn visit_u8<E>(self, value: u8) -> Result<NodeId, E> + where + E: de::Error, + { + Ok(NodeId(value as usize)) + } + + fn visit_u32<E>(self, value: u32) -> Result<NodeId, E> + where + E: de::Error, + { + Ok(NodeId(value as usize)) + } + + fn visit_u64<E>(self, value: u64) -> Result<NodeId, E> + where + E: de::Error, + { + use std::usize; + if value >= usize::MIN as u64 && value <= usize::MAX as u64 { + Ok(NodeId(value as usize)) + } else { + Err(E::custom(format!("u32 out of range: {}", value))) + } + } +} + +impl<'de> Deserialize<'de> for NodeId { + fn deserialize<D>(deserializer: D) -> Result<NodeId, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_u32(NodeIdVisitor) + } +} + /// Results of a certification, with the current certification count /// of the destination as parameter. #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/ws2p/Cargo.toml b/ws2p/Cargo.toml deleted file mode 100644 index 955f268c..00000000 --- a/ws2p/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "duniter-ws2p" -version = "0.1.0" -authors = ["librelois <elois@ifee.fr>"] -description = "WebSocketToPeer API for the Duniter project." -license = "AGPL-3.0" - -[lib] -path = "lib.rs" - -[dependencies] -duniter-conf = { path = "../conf" } -duniter-crypto = { path = "../crypto" } -duniter-dal = { path = "../dal" } -duniter-documents = { path = "../documents" } -duniter-message = { path = "../message" } -duniter-module = { path = "../module" } -duniter-network = { path = "../network" } -duniter-wotb = { path = "../wotb" } -lazy_static = "1.0.0" -log = "0.4.1" -rand = "0.4.2" -regex = "0.2.6" -rust-crypto = "0.2.36" -sqlite = "0.23.9" -serde = "1.0.24" -serde_derive = "1.0.24" -serde_json = "1.0.9" -websocket = "0.20.2" - -[features] -# Treat warnings as a build error. -strict = [] \ No newline at end of file diff --git a/ws2p/ack_message.rs b/ws2p/ack_message.rs deleted file mode 100644 index 23ba4fd2..00000000 --- a/ws2p/ack_message.rs +++ /dev/null @@ -1,67 +0,0 @@ -extern crate duniter_crypto; -extern crate serde; -extern crate serde_json; - -use self::serde::ser::{Serialize, SerializeStruct, Serializer}; -use super::WS2PMessage; -use duniter_crypto::keys::*; - -#[derive(Debug, Clone)] -pub struct WS2PAckMessageV1 { - pub currency: String, - pub pubkey: PubKey, - pub challenge: String, - pub signature: Option<Sig>, -} - -impl WS2PMessage for WS2PAckMessageV1 { - fn parse(v: &serde_json::Value, currency: String) -> Option<Self> { - let pubkey = match v.get("pub") { - Some(pubkey) => pubkey.as_str().unwrap().to_string(), - None => return None, - }; - let signature = match v.get("sig") { - Some(signature) => signature.as_str().unwrap().to_string(), - None => return None, - }; - let pubkey = PubKey::Ed25519(ed25519::PublicKey::from_base58(&pubkey).unwrap()); - let signature: Option<Sig> = Some(Sig::Ed25519( - ed25519::Signature::from_base64(&signature).unwrap(), - )); - Some(WS2PAckMessageV1 { - currency, - pubkey, - challenge: "".to_string(), - signature, - }) - } - fn to_raw(&self) -> String { - format!( - "WS2P:ACK:{}:{}:{}", - self.currency, self.pubkey, self.challenge - ) - } - fn verify(&self) -> bool { - self.pubkey - .verify(self.to_raw().as_bytes(), &self.signature.unwrap()) - } -} - -impl Serialize for WS2PAckMessageV1 { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - let mut connect_message_in_json = serializer.serialize_struct("message", 3)?; - connect_message_in_json.serialize_field("auth", "ACK")?; - connect_message_in_json.serialize_field("pub", &self.pubkey.to_string())?; - connect_message_in_json.serialize_field( - "sig", - &self - .signature - .expect("Fail to serialize ACK message : the signature field is set to None !") - .to_string(), - )?; - connect_message_in_json.end() - } -} diff --git a/ws2p/connect_message.rs b/ws2p/connect_message.rs deleted file mode 100644 index 30bb53da..00000000 --- a/ws2p/connect_message.rs +++ /dev/null @@ -1,72 +0,0 @@ -extern crate duniter_crypto; -extern crate serde; -extern crate serde_json; - -use self::serde::ser::{Serialize, SerializeStruct, Serializer}; -use super::WS2PMessage; -use duniter_crypto::keys::*; - -#[derive(Debug, Clone)] -pub struct WS2PConnectMessageV1 { - pub currency: String, - pub pubkey: PubKey, - pub challenge: String, - pub signature: Option<Sig>, -} - -impl WS2PMessage for WS2PConnectMessageV1 { - fn parse(v: &serde_json::Value, currency: String) -> Option<Self> { - let pubkey = match v.get("pub") { - Some(pubkey) => pubkey.as_str().unwrap().to_string(), - None => return None, - }; - let challenge = match v.get("challenge") { - Some(challenge) => challenge.as_str().unwrap().to_string(), - None => return None, - }; - let signature = match v.get("sig") { - Some(signature) => signature.as_str().unwrap().to_string(), - None => return None, - }; - let pubkey = PubKey::Ed25519(ed25519::PublicKey::from_base58(&pubkey).unwrap()); - let signature = Some(Sig::Ed25519( - ed25519::Signature::from_base64(&signature).unwrap(), - )); - Some(WS2PConnectMessageV1 { - currency, - pubkey, - challenge, - signature, - }) - } - fn to_raw(&self) -> String { - format!( - "WS2P:CONNECT:{}:{}:{}", - self.currency, self.pubkey, self.challenge - ) - } - fn verify(&self) -> bool { - self.pubkey - .verify(self.to_raw().as_bytes(), &self.signature.unwrap()) - } -} - -impl Serialize for WS2PConnectMessageV1 { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - let mut connect_message_in_json = serializer.serialize_struct("message", 4)?; - connect_message_in_json.serialize_field("auth", "CONNECT")?; - connect_message_in_json.serialize_field("pub", &self.pubkey.to_string())?; - connect_message_in_json.serialize_field("challenge", &self.challenge)?; - connect_message_in_json.serialize_field( - "sig", - &self - .signature - .expect("Fail to serialize CONNECT message : the signature field is set to None !") - .to_string(), - )?; - connect_message_in_json.end() - } -} diff --git a/ws2p/constants.rs b/ws2p/constants.rs deleted file mode 100644 index 7d33b80d..00000000 --- a/ws2p/constants.rs +++ /dev/null @@ -1,22 +0,0 @@ -extern crate regex; - -use self::regex::Regex; - -lazy_static! { - #[derive(Debug)] - pub static ref WS2P_V1_ENDPOINT_REGEX: Regex = Regex::new( - "^WS2P (?P<version>[1-9][0-9]* )?(?P<uuid>[a-f0-9]{6,8}) (?P<host>[a-z_][a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+) (?P<port>[0-9]+)(?: /?(?P<path>.+)?)? *$" - ).unwrap(); -} -pub static WS2P_OUTCOMING_INTERVAL_AT_STARTUP: &'static u64 = &75; -pub static WS2P_OUTCOMING_INTERVAL: &'static u64 = &300; -pub static WS2P_DEFAULT_OUTCOMING_QUOTA: &'static usize = &10; -pub static WS2P_NEGOTIATION_TIMEOUT: &'static u64 = &15; -//pub static WS2P_REQUEST_TIMEOUT : &'static u64 = &30; -pub static WS2P_CONNECTION_TIMEOUT: &'static u64 = &120; -pub static WS2P_SPAM_INTERVAL_IN_MILLI_SECS: &'static u64 = &80; -pub static WS2P_SPAM_LIMIT: &'static u64 = &6; -pub static WS2P_SPAM_SLEEP_TIME_IN_SEC: &'static u64 = &100; -pub static DURATION_BEFORE_RECORDING_ENDPOINT: &'static u64 = &180; -pub static BLOCKS_REQUEST_INTERVAL: &'static u64 = &60; -pub static PENDING_IDENTITIES_REQUEST_INTERVAL: &'static u64 = &40; diff --git a/ws2p/lib.rs b/ws2p/lib.rs deleted file mode 100644 index dc696d57..00000000 --- a/ws2p/lib.rs +++ /dev/null @@ -1,2009 +0,0 @@ -// Copyright (C) 2018 The Duniter Project Developers. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Crate containing Duniter-rust core. - -#![cfg_attr(feature = "strict", deny(warnings))] -#![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] -#![deny( - missing_debug_implementations, missing_copy_implementations, trivial_casts, unsafe_code, - unstable_features, unused_import_braces, unused_qualifications -)] -#![recursion_limit = "256"] - -#[macro_use] -extern crate lazy_static; - -#[macro_use] -extern crate log; - -#[macro_use] -extern crate serde_json; - -extern crate duniter_conf; -extern crate duniter_crypto; -extern crate duniter_dal; -extern crate duniter_documents; -extern crate duniter_message; -extern crate duniter_module; -extern crate duniter_network; -extern crate rand; -extern crate sqlite; -extern crate websocket; - -use std::collections::HashMap; -use std::ops::Deref; -use std::path::PathBuf; -use std::str::from_utf8; -use std::sync::mpsc; -use std::thread; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; - -use duniter_crypto::keys::*; -use duniter_dal::dal_event::DALEvent; -use duniter_dal::dal_requests::{DALReqBlockchain, DALRequest, DALResBlockchain, DALResponse}; -use duniter_documents::Blockstamp; -use duniter_message::DuniterMessage; -use duniter_module::*; -use duniter_network::network_endpoint::*; -use duniter_network::network_head::*; -use duniter_network::*; -use parsers::blocks::parse_json_block; -use websocket::{ClientBuilder, Message}; - -mod ack_message; -mod connect_message; -pub mod constants; -mod ok_message; -pub mod parsers; -pub mod serializer; -pub mod ws2p_connection; -pub mod ws2p_db; -pub mod ws2p_requests; - -use ack_message::WS2PAckMessageV1; -use connect_message::WS2PConnectMessageV1; -use constants::*; -use ok_message::WS2POkMessageV1; -use rand::Rng; -use ws2p_connection::*; -use ws2p_requests::network_request_to_json; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct WS2PConf { - pub node_id: NodeUUID, - pub outcoming_quota: usize, - pub sync_endpoints: Vec<NetworkEndpoint>, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum WS2PConfParseError { - UnknowError(), -} - -#[derive(Debug)] -pub enum WS2PSignal { - WSError(NodeFullId), - ConnectionEstablished(NodeFullId), - NegociationTimeout(NodeFullId), - Timeout(NodeFullId), - DalRequest(NodeFullId, ModuleReqId, serde_json::Value), - PeerCard(NodeFullId, serde_json::Value, Vec<NetworkEndpoint>), - Heads(NodeFullId, Vec<NetworkHead>), - Document(NodeFullId, NetworkDocument), - ReqResponse(ModuleReqId, NetworkRequest, NodeFullId, serde_json::Value), - Empty, - NoConnection, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum NetworkConsensusError { - InsufficientData(usize), - Fork, -} - -#[derive(Debug)] -pub enum SendRequestError { - RequestTypeMustNotBeTransmitted(), - WSError(usize, Vec<websocket::WebSocketError>), -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct WS2PModule {} - -#[derive(Debug)] -pub struct WS2PModuleDatas { - pub followers: Vec<mpsc::Sender<DuniterMessage>>, - pub currency: Option<String>, - pub key_pair: Option<KeyPairEnum>, - pub conf: Option<WS2PConf>, - pub main_thread_channel: ( - mpsc::Sender<WS2PThreadSignal>, - mpsc::Receiver<WS2PThreadSignal>, - ), - pub ws2p_endpoints: HashMap<NodeFullId, (NetworkEndpoint, WS2PConnectionState)>, - pub connections_meta_datas: HashMap<NodeFullId, WS2PConnectionMetaData>, - pub websockets: HashMap<NodeFullId, WebsocketSender>, - pub threads_senders_channels: HashMap<NodeFullId, mpsc::Sender<WS2POrderForListeningThread>>, - pub requests_awaiting_response: HashMap<ModuleReqId, (NetworkRequest, NodeFullId, SystemTime)>, - pub heads_cache: HashMap<NodeFullId, NetworkHead>, - pub my_head: Option<NetworkHead>, - pub uids_cache: HashMap<PubKey, String>, -} - -#[derive(Debug)] -pub enum WS2PThreadSignal { - DuniterMessage(Box<DuniterMessage>), - WS2PConnectionMessage(WS2PConnectionMessage), -} - -pub trait WS2PMessage: Sized { - fn parse(v: &serde_json::Value, currency: String) -> Option<Self>; - fn to_raw(&self) -> String; - fn sign(&self, key_pair: KeyPairEnum) -> Sig { - key_pair.sign(self.to_raw().as_bytes()) - } - fn verify(&self) -> bool; - //fn parse_and_verify(v: serde_json::Value, currency: String) -> bool; -} - -pub fn get_random_connection<S: ::std::hash::BuildHasher>( - connections: &HashMap<NodeFullId, (NetworkEndpoint, WS2PConnectionState), S>, -) -> NodeFullId { - let mut rng = rand::thread_rng(); - let mut loop_count = 0; - loop { - for (ws2p_full_id, (_ep, state)) in &(*connections) { - if loop_count > 10 { - return *ws2p_full_id; - } - if let WS2PConnectionState::Established = state { - if rng.gen::<bool>() { - return *ws2p_full_id; - } - } - } - loop_count += 1; - } -} - -impl Default for WS2PModule { - fn default() -> WS2PModule { - WS2PModule {} - } -} - -impl DuniterModule<DuniterMessage> for WS2PModule { - fn id() -> ModuleId { - ModuleId::Str("ws2p") - } - fn priority() -> ModulePriority { - ModulePriority::Essential() - } - fn ask_required_keys() -> RequiredKeys { - RequiredKeys::NetworkKeyPair() - } - fn default_conf() -> serde_json::Value { - json!({ - "sync_peers": [{ - "pubkey": "7v2J4badvfWQ6qwRdCwhhJfAsmKwoxRUNpJHiJHj7zef", - "ws2p_endpoints": ["WS2P b48824f0 g1.monnaielibreoccitanie.org 80 /ws2p"] - }] - }) - } - fn start( - soft_name: &str, - soft_version: &str, - keys: RequiredKeysContent, - duniter_conf: &DuniterConf, - module_conf: &serde_json::Value, - rooter_sender: mpsc::Sender<RooterThreadMessage<DuniterMessage>>, - load_conf_only: bool, - ) -> Result<(), ModuleInitError> { - let start_time = SystemTime::now(); - let mut ws2p_module = WS2PModuleDatas { - followers: Vec::new(), - key_pair: None, - currency: None, - conf: None, - main_thread_channel: mpsc::channel(), - ws2p_endpoints: HashMap::new(), - connections_meta_datas: HashMap::new(), - websockets: HashMap::new(), - threads_senders_channels: HashMap::new(), - requests_awaiting_response: HashMap::new(), - heads_cache: HashMap::new(), - my_head: None, - uids_cache: HashMap::new(), - }; - - // load conf - let key_pair = match keys { - RequiredKeysContent::NetworkKeyPair(key_pair) => key_pair, - _ => panic!("WS2PModule fatal error at load_conf() : keys != NetworkKeyPair"), - }; - let conf = WS2PModuleDatas::parse_ws2p_conf(duniter_conf, module_conf); - let mut ws2p_endpoints = HashMap::new(); - for ep in conf.sync_endpoints.clone() { - ws2p_endpoints.insert( - ep.node_full_id() - .expect("Fail to get endpoint node_full_id"), - (ep.clone(), WS2PConnectionState::Close), - ); - info!("Load sync endpoint {}", ep.raw()); - } - ws2p_module.key_pair = Some(key_pair); - ws2p_module.currency = Some(duniter_conf.currency().to_string()); - ws2p_module.conf = Some(conf.clone()); - ws2p_module.ws2p_endpoints = ws2p_endpoints; - - // Create ws2p main thread channel - let ws2p_sender_clone = ws2p_module.main_thread_channel.0.clone(); - - // Create proxy channel - let (proxy_sender, proxy_receiver): ( - mpsc::Sender<DuniterMessage>, - mpsc::Receiver<DuniterMessage>, - ) = mpsc::channel(); - let proxy_sender_clone = proxy_sender.clone(); - - // Launch a proxy thread that transform DuniterMessage to WS2PThreadSignal(DuniterMessage) - thread::spawn(move || { - // Send proxy sender to main - rooter_sender - .send(RooterThreadMessage::ModuleSender(proxy_sender_clone)) - .expect("Fatal error : ws2p module fail to send is sender channel !"); - debug!("Send ws2p sender to main thread."); - loop { - match proxy_receiver.recv() { - Ok(message) => { - ws2p_sender_clone - .send(WS2PThreadSignal::DuniterMessage(Box::new(message.clone()))) - .expect( - "Fatal error : fail to relay DuniterMessage to ws2p main thread !", - ); - if let DuniterMessage::Stop() = message { - break; - }; - } - Err(e) => panic!(format!("{}", e)), - } - } - }); - - // open ws2p bdd - let mut db_path = - duniter_conf::datas_path(duniter_conf.profile().as_str(), &duniter_conf.currency()); - db_path.push("ws2p.db"); - let db = WS2PModuleDatas::open_db(&db_path).expect("Fatal error : fail to open WS2P DB !"); - - // Get ws2p endpoints in BDD - let mut count = 0; - let dal_enpoints = - ws2p_db::get_endpoints_for_api(&db, &NetworkEndpointApi(String::from("WS2P"))); - for ep in dal_enpoints { - if ep.api() == NetworkEndpointApi(String::from("WS2P")) && ep.port() != 443 { - count += 1; - ws2p_module.ws2p_endpoints.insert( - ep.node_full_id() - .expect("WS2P: Fail to get ep.node_full_id() !"), - (ep.clone(), WS2PConnectionState::from(ep.status())), - ); - } - } - info!("Load {} endpoints from bdd !", count); - - // Stop here in load_conf_only mode - if load_conf_only { - return Ok(()); - } - - // Initialize variables - let mut last_ws2p_connecting_wave = SystemTime::now(); - let mut last_ws2p_connections_print = SystemTime::now(); - let mut endpoints_to_update_status: HashMap<NodeFullId, SystemTime> = HashMap::new(); - let mut last_identities_request = UNIX_EPOCH; - let mut current_blockstamp = Blockstamp::default(); - let mut next_receiver = 0; - - // Start - ws2p_module.connect_to_know_endpoints(); - loop { - match ws2p_module - .main_thread_channel - .1 - .recv_timeout(Duration::from_millis(200)) - { - Ok(message) => match message { - WS2PThreadSignal::DuniterMessage(ref duniter_mesage) => { - match *duniter_mesage.deref() { - DuniterMessage::Stop() => break, - DuniterMessage::Followers(ref new_followers) => { - info!("WS2P module receive followers !"); - for new_follower in new_followers { - debug!("WS2PModule : push one follower."); - ws2p_module.followers.push(new_follower.clone()); - if current_blockstamp == Blockstamp::default() { - // Request local current blockstamp - ws2p_module.send_dal_request( - &DALRequest::BlockchainRequest( - DALReqBlockchain::CurrentBlock(ModuleReqFullId( - WS2PModule::id(), - ModuleReqId(0), - )), - ), - ); - } else { - if ws2p_module.my_head.is_none() { - ws2p_module.my_head = - Some(WS2PModuleDatas::generate_my_head( - &key_pair, - &conf.clone(), - soft_name, - soft_version, - ¤t_blockstamp, - None, - )); - } - ws2p_module.send_network_event( - &NetworkEvent::ReceiveHeads(vec![ - ws2p_module.my_head.clone().unwrap(), - ]), - ); - } - } - } - DuniterMessage::NetworkRequest(ref request) => match *request { - NetworkRequest::GetBlocks( - ref req_id, - ref receiver, - ref count, - ref from, - ) => { - if *receiver == NodeFullId::default() { - let mut receiver_index = 0; - let mut real_receiver = NodeFullId::default(); - for (ws2p_full_id, (_ep, state)) in - ws2p_module.ws2p_endpoints.clone() - { - if let WS2PConnectionState::Established = state { - if receiver_index == next_receiver { - real_receiver = ws2p_full_id; - break; - } - receiver_index += 1; - } - } - if real_receiver == NodeFullId::default() { - next_receiver = 0; - for (ws2p_full_id, (_ep, state)) in - ws2p_module.ws2p_endpoints.clone() - { - if let WS2PConnectionState::Established = state { - real_receiver = ws2p_full_id; - break; - } - } - } else { - next_receiver += 1; - } - if real_receiver != NodeFullId::default() { - let _blocks_request_result = ws2p_module - .send_request_to_specific_node( - &real_receiver, - &NetworkRequest::GetBlocks( - *req_id, *receiver, *count, *from, - ), - ); - } else { - warn!("WS2PModule : No WS2P connections !"); - } - } else { - let _blocks_request_result = ws2p_module - .send_request_to_specific_node( - &receiver, - &NetworkRequest::GetBlocks( - *req_id, *receiver, *count, *from, - ), - ); - } - } - NetworkRequest::GetEndpoints(ref _request) => {} - _ => {} - }, - DuniterMessage::DALEvent(ref dal_event) => match *dal_event { - DALEvent::StackUpValidBlock(ref _block, ref blockstamp) => { - current_blockstamp = *blockstamp; - debug!( - "WS2PModule : current_blockstamp = {}", - current_blockstamp - ); - ws2p_module.my_head = Some(WS2PModuleDatas::generate_my_head( - &key_pair, - &conf.clone(), - soft_name, - soft_version, - ¤t_blockstamp, - None, - )); - ws2p_module.send_network_event(&NetworkEvent::ReceiveHeads( - vec![ws2p_module.my_head.clone().unwrap()], - )); - // Send my head to all connections - let my_json_head = serializer::serialize_head( - ws2p_module.my_head.clone().unwrap(), - ); - trace!("Send my HEAD: {:#?}", my_json_head); - let _results: Result< - (), - websocket::WebSocketError, - > = ws2p_module - .websockets - .iter_mut() - .map(|ws| { - (ws.1).0.send_message(&Message::text( - json!({ - "name": "HEAD", - "body": { - "heads": [my_json_head] - } - }).to_string(), - )) - }) - .collect(); - } - DALEvent::RevertBlocks(ref _blocks) => {} - _ => {} - }, - DuniterMessage::DALResponse(ref dal_res) => match *dal_res.deref() { - DALResponse::Blockchain(ref dal_res_bc) => { - match *dal_res_bc.deref() { - DALResBlockchain::CurrentBlock( - ref _requester_full_id, - ref current_block, - ref current_blockstamp_, - ) => { - let _current_block = current_block.deref(); - debug!( - "WS2PModule : receive DALResBc::CurrentBlock({})", - current_blockstamp - ); - current_blockstamp = *current_blockstamp_; - if ws2p_module.my_head.is_none() { - ws2p_module.my_head = - Some(WS2PModuleDatas::generate_my_head( - &key_pair, - &conf.clone(), - soft_name, - soft_version, - ¤t_blockstamp, - None, - )); - } - ws2p_module.send_network_event( - &NetworkEvent::ReceiveHeads(vec![ - ws2p_module.my_head.clone().unwrap(), - ]), - ); - } - DALResBlockchain::UIDs(ref uids) => { - // Add uids to heads - for head in ws2p_module.heads_cache.values_mut() { - if let Some(uid_option) = uids.get(&head.pubkey()) { - if let Some(ref uid) = *uid_option { - head.set_uid(uid); - ws2p_module - .uids_cache - .insert(head.pubkey(), uid.to_string()); - } else { - ws2p_module - .uids_cache - .remove(&head.pubkey()); - } - } - } - // Resent heads to other modules - ws2p_module.send_network_event( - &NetworkEvent::ReceiveHeads( - ws2p_module - .heads_cache - .values() - .cloned() - .collect(), - ), - ); - // Resent to other modules connections that match receive uids - for (node_full_id, (ep, conn_state)) in - ws2p_module.ws2p_endpoints.clone() - { - if let Some(uid_option) = uids.get(&node_full_id.1) - { - ws2p_module.send_network_event( - &NetworkEvent::ConnectionStateChange( - node_full_id, - conn_state as u32, - uid_option.clone(), - ep.get_url(false), - ), - ); - } - } - } - _ => {} - } - } - DALResponse::Pendings(_, _) => {} - }, - _ => {} - } - } - WS2PThreadSignal::WS2PConnectionMessage(ws2p_conn_message) => match ws2p_module - .ws2p_conn_message_pretreatment(ws2p_conn_message) - { - WS2PSignal::NoConnection => { - warn!("WS2PSignal::NoConnection"); - last_ws2p_connecting_wave = SystemTime::now(); - ws2p_module.connect_to_know_endpoints(); - } - WS2PSignal::ConnectionEstablished(ws2p_full_id) => { - let req_id = - ModuleReqId(ws2p_module.requests_awaiting_response.len() as u32); - let module_id = WS2PModule::id(); - let _current_request_result = ws2p_module - .send_request_to_specific_node( - &ws2p_full_id, - &NetworkRequest::GetCurrent( - ModuleReqFullId(module_id, req_id), - ws2p_full_id, - ), - ); - ws2p_module.send_network_event(&NetworkEvent::ConnectionStateChange( - ws2p_full_id, - WS2PConnectionState::Established as u32, - ws2p_module.uids_cache.get(&ws2p_full_id.1).cloned(), - ws2p_module.ws2p_endpoints[&ws2p_full_id].0.get_url(false), - )); - } - WS2PSignal::WSError(ws2p_full_id) => { - endpoints_to_update_status.insert(ws2p_full_id, SystemTime::now()); - ws2p_module.send_network_event(&NetworkEvent::ConnectionStateChange( - ws2p_full_id, - WS2PConnectionState::WSError as u32, - ws2p_module.uids_cache.get(&ws2p_full_id.1).cloned(), - ws2p_module.ws2p_endpoints[&ws2p_full_id].0.get_url(false), - )); - } - WS2PSignal::NegociationTimeout(ws2p_full_id) => { - endpoints_to_update_status.insert(ws2p_full_id, SystemTime::now()); - ws2p_module.send_network_event(&NetworkEvent::ConnectionStateChange( - ws2p_full_id, - WS2PConnectionState::Denial as u32, - ws2p_module.uids_cache.get(&ws2p_full_id.1).cloned(), - ws2p_module.ws2p_endpoints[&ws2p_full_id].0.get_url(false), - )); - } - WS2PSignal::Timeout(ws2p_full_id) => { - endpoints_to_update_status.insert(ws2p_full_id, SystemTime::now()); - ws2p_module.send_network_event(&NetworkEvent::ConnectionStateChange( - ws2p_full_id, - WS2PConnectionState::Close as u32, - ws2p_module.uids_cache.get(&ws2p_full_id.1).cloned(), - ws2p_module.ws2p_endpoints[&ws2p_full_id].0.get_url(false), - )); - } - WS2PSignal::PeerCard(_ws2p_full_id, _peer_card, ws2p_endpoints) => { - //trace!("WS2PSignal::PeerCard({})", ws2p_full_id); - //ws2p_module.send_network_event(NetworkEvent::ReceivePeers(_)); - for ep in ws2p_endpoints { - if ep.port() != 443 { - match ws2p_module.ws2p_endpoints.get( - &ep.node_full_id() - .expect("WS2P: Fail to get ep.node_full_id() !"), - ) { - Some(_) => {} - None => { - if let Some(_api) = - ws2p_db::string_to_api(&ep.api().0.clone()) - { - endpoints_to_update_status.insert( - ep.node_full_id().expect( - "WS2P: Fail to get ep.node_full_id() !", - ), - SystemTime::now(), - ); - } - ws2p_module.connect_to(&ep); - } - }; - } - } - } - WS2PSignal::Heads(ws2p_full_id, heads) => { - trace!("WS2PSignal::Heads({}, {:?})", ws2p_full_id, heads.len()); - ws2p_module.send_dal_request(&DALRequest::BlockchainRequest( - DALReqBlockchain::UIDs(heads.iter().map(|h| h.pubkey()).collect()), - )); - ws2p_module.send_network_event(&NetworkEvent::ReceiveHeads( - heads - .iter() - .map(|head| { - let mut new_head = head.clone(); - if let Some(uid) = - ws2p_module.uids_cache.get(&head.pubkey()) - { - new_head.set_uid(uid); - } - new_head - }) - .collect(), - )); - } - WS2PSignal::Document(ws2p_full_id, network_doc) => { - trace!("WS2PSignal::Document({})", ws2p_full_id); - ws2p_module.send_network_event(&NetworkEvent::ReceiveDocuments(vec![ - network_doc, - ])); - } - WS2PSignal::ReqResponse(req_id, req, recipient_full_id, response) => { - match req { - NetworkRequest::GetCurrent(ref _req_id, _receiver) => { - info!("WS2PSignal::ReceiveCurrent({}, {:?})", req_id.0, req); - if let Some(block) = parse_json_block(&response) { - ws2p_module.send_network_event(&NetworkEvent::ReqResponse( - Box::new(NetworkResponse::CurrentBlock( - ModuleReqFullId(WS2PModule::id(), req_id), - recipient_full_id, - Box::new(block), - )), - )); - } - /*if let Some(block) = BlockV10::from_json_value(&response) { - ws2p_module - .connections_meta_datas - .get_mut(&recipient_full_id) - .unwrap() - .current_blockstamp = Some((block.id, block.hash)); - }*/ - } - NetworkRequest::GetBlocks(ref _req_id, _receiver, _count, from) => { - info!("WS2PSignal::ReceiveChunk({}, {:?})", req_id.0, req); - if response.is_array() { - let mut chunk = Vec::new(); - for json_block in response.as_array().unwrap() { - if let Some(block) = parse_json_block(json_block) { - chunk.push(NetworkDocument::Block(block)); - } else { - warn!("WS2PModule: Error : fail to parse one json block !"); - } - } - debug!("Send chunk to followers : {}", from); - ws2p_module.send_network_event( - &NetworkEvent::ReceiveDocuments(chunk), - ); - } - } - NetworkRequest::GetRequirementsPending( - _req_id, - _receiver, - min_cert, - ) => { - info!( - "WS2PSignal::ReceiveRequirementsPending({}, {})", - req_id.0, min_cert - ); - debug!("----------------------------------------"); - debug!("- BEGIN IDENTITIES PENDING -"); - debug!("----------------------------------------"); - debug!("{:#?}", response); - debug!("----------------------------------------"); - debug!("- END IDENTITIES PENDING -"); - debug!("----------------------------------------"); - } - _ => {} - } - } - WS2PSignal::Empty => {} - _ => {} - }, - }, - Err(e) => match e { - mpsc::RecvTimeoutError::Disconnected => { - panic!("Disconnected ws2p module !"); - } - mpsc::RecvTimeoutError::Timeout => {} - }, - } - if SystemTime::now() - .duration_since(last_ws2p_connections_print) - .unwrap() > Duration::new(5, 0) - { - last_ws2p_connections_print = SystemTime::now(); - let mut connected_nodes = Vec::new(); - let mut denial_nodes = Vec::new(); - let mut disconnected_nodes = Vec::new(); - let mut unreachable_nodes = Vec::new(); - let mut ws_error_nodes = Vec::new(); - for (k, (_ep, state)) in ws2p_module.ws2p_endpoints.clone() { - match state { - WS2PConnectionState::NeverTry => { - //writeln!("Never try : {}", k); - } - WS2PConnectionState::TryToOpenWS => {}//writeln!("TryToOpenWS : {}", k), - WS2PConnectionState::WSError => { - ws_error_nodes.push(k); - } - WS2PConnectionState::TryToSendConnectMess => { - //writeln!("TryToSendConnectMess : {}", k) - } - WS2PConnectionState::Unreachable => { - unreachable_nodes.push(k); - } - WS2PConnectionState::WaitingConnectMess => { - //writeln!("WaitingConnectMess : {}", k) - } - WS2PConnectionState::NoResponse => {}//writeln!("NoResponse : {}", k), - WS2PConnectionState::AckMessOk - | WS2PConnectionState::ConnectMessOk - | WS2PConnectionState::OkMessOkWaitingAckMess => { - //writeln!("Ongoing negotiations : {}", k) - } - WS2PConnectionState::Denial => { - denial_nodes.push(k); - } - WS2PConnectionState::Established => { - connected_nodes.push(k); - } - WS2PConnectionState::Close => { - disconnected_nodes.push(k); - } - } - } - /*writeln!( - "Connected with {} nodes. (Denial : {}, Disconnected : {}, Unreachable: {}, WSError : {})", - connected_nodes.len(), - denial_nodes.len(), - disconnected_nodes.len(), - unreachable_nodes.len(), - ws_error_nodes.len() - );*/ - for _node in connected_nodes.clone() { - //writeln!("Connection established : {}", node); - } - for _node in denial_nodes { - //writeln!("Denial : {}", node); - } - for _node in disconnected_nodes { - //writeln!("Disconnected : {}", node); - } - for _node in unreachable_nodes { - //writeln!("Unreachable : {}", node); - } - // Print network consensus - match ws2p_module.get_network_consensus() { - Ok(consensus_blockstamp) => { - debug!( - "WS2PModule : get_network_consensus() = {:?}", - consensus_blockstamp - ); - if current_blockstamp.id.0 < (consensus_blockstamp.id.0 + 2) { - warn!("We probably are in a fork branch !"); - } - } - Err(e) => warn!("{:?}", e), - } - // Print current_blockstamp - info!( - "WS2PModule : current_blockstamp() = {:?}", - current_blockstamp - ); - // New WS2P connection wave - if connected_nodes.len() < ws2p_module.conf.clone().unwrap().outcoming_quota - && (SystemTime::now() - .duration_since(last_ws2p_connecting_wave) - .unwrap() - > Duration::new(*WS2P_OUTCOMING_INTERVAL, 0) - || (SystemTime::now() - .duration_since(last_ws2p_connecting_wave) - .unwrap() - > Duration::new(*WS2P_OUTCOMING_INTERVAL_AT_STARTUP, 0) - && SystemTime::now().duration_since(start_time).unwrap() - < Duration::new(*WS2P_OUTCOMING_INTERVAL, 0))) - { - last_ws2p_connecting_wave = SystemTime::now(); - info!("Connected to know endpoints..."); - ws2p_module.connect_to_know_endpoints(); - } - /*// Request blocks from network - if SystemTime::now() - .duration_since(last_blocks_request) - .unwrap() > Duration::new(*BLOCKS_REQUEST_INTERVAL, 0) - && SystemTime::now().duration_since(start_time).unwrap() > Duration::new(10, 0) - { - let mut request_blocks_from = current_blockstamp.id.0; - if request_blocks_from > 0 { - request_blocks_from += 1; - } - info!("get chunks from all connections..."); - let module_id = WS2PModule::id(); - let _blocks_request_result = - ws2p_module.send_request_to_all_connections(&NetworkRequest::GetBlocks( - ModuleReqFullId(module_id, ModuleReqId(0 as u32)), - NodeFullId::default(), - 50, - request_blocks_from, - )); - last_blocks_request = SystemTime::now(); - }*/ - // Request pending_identities from network - if SystemTime::now() - .duration_since(last_identities_request) - .unwrap() - > Duration::new(*PENDING_IDENTITIES_REQUEST_INTERVAL, 0) - && SystemTime::now().duration_since(start_time).unwrap() > Duration::new(10, 0) - { - /*info!("get pending_identities from all connections..."); - let _blocks_request_result = ws2p_module.send_request_to_all_connections( - &NetworkRequest::GetRequirementsPending(ModuleReqId(0 as u32), 5), - );*/ - last_identities_request = SystemTime::now(); - } - // Write pending endpoints - for (ep_full_id, received_time) in endpoints_to_update_status.clone() { - if SystemTime::now().duration_since(received_time).unwrap() - > Duration::new(*DURATION_BEFORE_RECORDING_ENDPOINT, 0) - { - if let Some(&(ref ep, ref state)) = - ws2p_module.ws2p_endpoints.get(&ep_full_id) - { - /*let dal_endpoint = duniter_dal::endpoint::DALEndpoint::new( - state.clone() as u32, - ep.node_uuid().unwrap().0, - ep.pubkey(), - duniter_dal::endpoint::string_to_api(&ep.api().0).unwrap(), - 1, - ep.to_string(), - received_time.duration_since(UNIX_EPOCH).unwrap(), - );*/ - ws2p_db::write_endpoint( - &db, - &ep, - state.to_u32(), - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs(), - ); - } - endpoints_to_update_status.remove(&ep_full_id); - } else { - info!( - "Write {} endpoint in {} secs.", - ep_full_id, - *DURATION_BEFORE_RECORDING_ENDPOINT - - SystemTime::now() - .duration_since(received_time) - .unwrap() - .as_secs() - ); - } - } - // .. - } - } - Ok(()) - } -} - -impl WS2PModuleDatas { - fn open_db(db_path: &PathBuf) -> Result<sqlite::Connection, sqlite::Error> { - let conn: sqlite::Connection; - if !db_path.as_path().exists() { - conn = sqlite::open(db_path.as_path())?; - conn.execute( - "CREATE TABLE endpoints (hash_full_id TEXT, status INTEGER, node_id INTEGER, pubkey TEXT, - api INTEGER, version INTEGER, endpoint TEXT, last_check INTEGER);", - )?; - } else { - conn = sqlite::open(db_path.as_path())?; - } - Ok(conn) - } - pub fn parse_ws2p_conf( - duniter_conf: &DuniterConf, - ws2p_json_conf: &serde_json::Value, - ) -> WS2PConf { - let mut sync_endpoints = Vec::new(); - match ws2p_json_conf.get("sync_peers") { - Some(peers) => { - let array_peers = peers.as_array().expect("Conf: Fail to parse conf file !"); - for peer in array_peers { - let pubkey = match peer.get("pubkey") { - Some(pubkey) => PubKey::Ed25519( - ed25519::PublicKey::from_base58( - pubkey - .as_str() - .expect("WS2PConf Error : fail to parse sync endpoint pubkey"), - ).expect("WS2PConf Error : fail to parse sync endpoint pubkey"), - ), - None => panic!( - "Fail to load ws2p conf : \ - WrongFormat : not found pubkey field !" - ), - }; - match peer.get("ws2p_endpoints") { - Some(endpoints) => { - let array_endpoints = endpoints - .as_array() - .expect("Conf: Fail to parse conf file !"); - for endpoint in array_endpoints { - sync_endpoints.push( - NetworkEndpoint::parse_from_raw( - endpoint.as_str().expect("WS2P: Fail to get ep.as_str() !"), - pubkey, - 0, - 0, - ).expect(&format!( - "WS2PConf Error : fail to parse sync Endpoint = {:?}", - endpoint.as_str().expect("WS2P: Fail to get ep.as_str() !") - )), - ); - } - } - None => panic!( - "Fail to load conf : \ - WrongFormat : not found ws2p_endpoints field !" - ), - }; - } - } - None => panic!( - "Configuration Error : \ - You must declare at least one node on which to synchronize !" - ), - }; - WS2PConf { - outcoming_quota: *WS2P_DEFAULT_OUTCOMING_QUOTA, - node_id: NodeUUID(duniter_conf.my_node_id()), - sync_endpoints, - } - } - pub fn send_dal_request(&self, req: &DALRequest) { - for follower in &self.followers { - if follower - .send(DuniterMessage::DALRequest(req.clone())) - .is_err() - { - // handle error - } - } - } - pub fn send_network_event(&self, event: &NetworkEvent) { - for follower in &self.followers { - match follower.send(DuniterMessage::NetworkEvent(event.clone())) { - Ok(_) => { - debug!("Send NetworkEvent to one follower."); - } - Err(_) => { - warn!("Fail to send NetworkEvent to one follower !"); - } - } - } - } - pub fn generate_my_head( - network_keypair: &KeyPairEnum, - conf: &WS2PConf, - soft_name: &str, - soft_version: &str, - my_current_blockstamp: &Blockstamp, - my_uid: Option<String>, - ) -> NetworkHead { - let message = NetworkHeadMessage::V2(NetworkHeadMessageV2 { - api: String::from("WS2POCA"), - version: 1, - pubkey: network_keypair.public_key(), - blockstamp: *my_current_blockstamp, - node_uuid: conf.node_id, - software: String::from(soft_name), - soft_version: String::from(soft_version), - prefix: 1, - free_member_room: None, - free_mirror_room: None, - }); - let message_v2 = NetworkHeadMessage::V2(NetworkHeadMessageV2 { - api: String::from("WS2POCA"), - version: 2, - pubkey: network_keypair.public_key(), - blockstamp: *my_current_blockstamp, - node_uuid: conf.node_id, - software: String::from(soft_name), - soft_version: String::from(soft_version), - prefix: 1, - free_member_room: Some(0), - free_mirror_room: Some(0), - }); - NetworkHead::V2(Box::new(NetworkHeadV2 { - message: message.clone(), - sig: network_keypair - .private_key() - .sign(message.to_string().as_bytes()), - message_v2: message_v2.clone(), - sig_v2: network_keypair - .private_key() - .sign(message_v2.to_string().as_bytes()), - step: 0, - uid: my_uid, - })) - } - pub fn get_network_consensus(&self) -> Result<Blockstamp, NetworkConsensusError> { - let mut count_known_blockstamps = 0; - let mut farthest_blockstamp = Blockstamp::default(); - let mut blockstamps_occurences: HashMap<Blockstamp, usize> = - HashMap::with_capacity(*WS2P_DEFAULT_OUTCOMING_QUOTA); - let mut dominant_blockstamp = Blockstamp::default(); - let mut dominant_blockstamp_occurences = 0; - for (_ws2p_full_id, head) in self.heads_cache.clone() { - count_known_blockstamps += 1; - let blockstamps_occurences_copy = blockstamps_occurences.clone(); - match blockstamps_occurences_copy.get(&head.blockstamp()) { - Some(occurences) => { - let mut occurences_mut = blockstamps_occurences - .get_mut(&head.blockstamp()) - .expect("WS2P: Fail to get_mut blockstamps_occurences !"); - *occurences_mut += 1; - if *occurences > dominant_blockstamp_occurences { - dominant_blockstamp_occurences = *occurences; - dominant_blockstamp = head.blockstamp(); - } - } - None => { - blockstamps_occurences.insert(head.blockstamp(), 0); - } - } - if head.blockstamp().id.0 > farthest_blockstamp.id.0 { - farthest_blockstamp = head.blockstamp(); - } - } - if count_known_blockstamps < 5 { - return Err(NetworkConsensusError::InsufficientData( - count_known_blockstamps, - )); - } else if farthest_blockstamp == dominant_blockstamp { - return Ok(dominant_blockstamp); - } - Err(NetworkConsensusError::Fork) - } - fn count_established_connections(&self) -> usize { - let mut count_established_connections = 0; - for (_ws2p_full_id, (_ep, state)) in self.ws2p_endpoints.clone() { - if let WS2PConnectionState::Established = state { - count_established_connections += 1; - } - } - count_established_connections - } - pub fn connect_to_know_endpoints(&mut self) -> () { - let mut count_established_connections = 0; - let mut reachable_endpoints = Vec::new(); - let mut unreachable_endpoints = Vec::new(); - for (_ws2p_full_id, (ep, state)) in self.ws2p_endpoints.clone() { - match state { - WS2PConnectionState::Established => count_established_connections += 1, - WS2PConnectionState::NeverTry - | WS2PConnectionState::Close - | WS2PConnectionState::Denial => reachable_endpoints.push(ep), - _ => unreachable_endpoints.push(ep), - } - } - let mut free_outcoming_rooms = self - .conf - .clone() - .expect("WS2P: Fail to get conf !") - .outcoming_quota - count_established_connections; - while free_outcoming_rooms > 0 { - let ep = if !reachable_endpoints.is_empty() { - reachable_endpoints - .pop() - .expect("WS2P: Fail to pop() reachable_endpoints !") - } else if !unreachable_endpoints.is_empty() { - unreachable_endpoints - .pop() - .expect("WS2P: Fail to pop() unreachable_endpoints !") - } else { - break; - }; - self.connect_to_without_checking_quotas(&ep); - free_outcoming_rooms -= 1; - } - } - pub fn connect_to(&mut self, endpoint: &NetworkEndpoint) -> () { - // Add endpoint to endpoints list (if there isn't already) - match self.ws2p_endpoints.get( - &endpoint - .node_full_id() - .expect("WS2P: Fail to get ep.node_full_id() !"), - ) { - Some(_) => { - self.ws2p_endpoints - .get_mut( - &endpoint - .node_full_id() - .expect("WS2P: Fail to get ep.node_full_id() !"), - ) - .expect("WS2P: Fail to get_mut() a ws2p_endpoint !") - .1 = WS2PConnectionState::NeverTry; - } - None => { - self.ws2p_endpoints.insert( - endpoint - .node_full_id() - .expect("WS2P: Fail to get ep.node_full_id() !"), - (endpoint.clone(), WS2PConnectionState::NeverTry), - ); - } - }; - if self - .conf - .clone() - .expect("WS2P: Fail to get conf !") - .outcoming_quota > self.count_established_connections() - { - self.connect_to_without_checking_quotas(&endpoint); - } - } - fn close_connection(&mut self, ws2p_full_id: &NodeFullId, reason: WS2PCloseConnectionReason) { - match reason { - WS2PCloseConnectionReason::NegociationTimeout => {} - WS2PCloseConnectionReason::AuthMessInvalidSig - | WS2PCloseConnectionReason::Timeout - | WS2PCloseConnectionReason::Unknow => { - self.ws2p_endpoints - .get_mut(ws2p_full_id) - .expect("Failure : attempt to delete a non-existent connection !") - .1 = WS2PConnectionState::Close - } - } - self.connections_meta_datas.remove(ws2p_full_id); - self.websockets.remove(ws2p_full_id).expect(&format!( - "Fatal error : no websocket for {} !", - ws2p_full_id - )); - self.threads_senders_channels.remove(ws2p_full_id); - } - pub fn ws2p_conn_message_pretreatment(&mut self, message: WS2PConnectionMessage) -> WS2PSignal { - let connections_count = self.connections_meta_datas.len(); - if connections_count == 0 { - return WS2PSignal::NoConnection; - } - let ws2p_full_id = message.0; - match message.1 { - WS2PConnectionMessagePayload::WrongUrl - | WS2PConnectionMessagePayload::FailOpenWS - | WS2PConnectionMessagePayload::FailToSplitWS => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to get mut ep !") - .1 = WS2PConnectionState::WSError; - return WS2PSignal::WSError(ws2p_full_id); - } - WS2PConnectionMessagePayload::TryToSendConnectMess => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to get mut ep !") - .1 = WS2PConnectionState::TryToSendConnectMess; - } - WS2PConnectionMessagePayload::FailSendConnectMess => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to mut ep !") - .1 = WS2PConnectionState::Unreachable; - } - WS2PConnectionMessagePayload::WebsocketOk(sender) => { - self.websockets.insert(ws2p_full_id, sender); - } - WS2PConnectionMessagePayload::ValidConnectMessage(response, new_con_state) => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to get mut ep !") - .1 = new_con_state; - if let WS2PConnectionState::ConnectMessOk = self.ws2p_endpoints[&ws2p_full_id].1 { - trace!("Send: {:#?}", response); - self.websockets - .get_mut(&ws2p_full_id) - .expect(&format!( - "Fatal error : no websocket for {} !", - ws2p_full_id - )) - .0 - .send_message(&Message::text(response)) - .expect("WS2P: Fail to send OK Message !"); - } - } - WS2PConnectionMessagePayload::ValidAckMessage(r, new_con_state) => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to get mut ep !") - .1 = new_con_state; - if let WS2PConnectionState::AckMessOk = self.ws2p_endpoints[&ws2p_full_id].1 { - trace!("DEBUG : Send: {:#?}", r); - self.websockets - .get_mut(&ws2p_full_id) - .expect(&format!( - "Fatal error : no websocket for {} !", - ws2p_full_id - )) - .0 - .send_message(&Message::text(r)) - .expect("WS2P: Fail to send Message in websocket !"); - } - } - WS2PConnectionMessagePayload::ValidOk(new_con_state) => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to get mut ep !") - .1 = new_con_state; - match self.ws2p_endpoints[&ws2p_full_id].1 { - WS2PConnectionState::OkMessOkWaitingAckMess => {} - WS2PConnectionState::Established => { - return WS2PSignal::ConnectionEstablished(ws2p_full_id) - } - _ => { - self.threads_senders_channels[&ws2p_full_id] - .send(WS2POrderForListeningThread::Close) - .expect("WS2P: Fail to send Close signel to connections threads !"); - self.close_connection(&ws2p_full_id, WS2PCloseConnectionReason::Unknow); - return WS2PSignal::Empty; - } - } - } - WS2PConnectionMessagePayload::DalRequest(req_id, req_body) => { - return WS2PSignal::DalRequest(ws2p_full_id, req_id, req_body); - } - WS2PConnectionMessagePayload::PeerCard(body, ws2p_endpoints) => { - return WS2PSignal::PeerCard(ws2p_full_id, body, ws2p_endpoints); - } - WS2PConnectionMessagePayload::Heads(heads) => { - let mut applied_heads = Vec::with_capacity(heads.len()); - for head in heads { - if let Some(head) = NetworkHead::from_json_value(&head) { - if head.verify() - && (self.my_head.is_none() - || head.node_full_id() - != self - .my_head - .clone() - .expect("WS2P: Fail to clone my_head") - .node_full_id()) - && head.apply(&mut self.heads_cache) - { - applied_heads.push(head); - } - } - } - return WS2PSignal::Heads(ws2p_full_id, applied_heads); - } - WS2PConnectionMessagePayload::Document(network_doc) => { - return WS2PSignal::Document(ws2p_full_id, network_doc); - } - WS2PConnectionMessagePayload::ReqResponse(req_id, response) => { - if self.requests_awaiting_response.len() > req_id.0 as usize { - if let Some((ref ws2p_request, ref recipient_fulld_id, ref _timestamp)) = - self.requests_awaiting_response.remove(&req_id) - { - return WS2PSignal::ReqResponse( - req_id, - *ws2p_request, - *recipient_fulld_id, - response, - ); - } - } - } - WS2PConnectionMessagePayload::NegociationTimeout => { - match self.ws2p_endpoints[&ws2p_full_id].1 { - WS2PConnectionState::AckMessOk | WS2PConnectionState::ConnectMessOk => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to get mut ep !") - .1 = WS2PConnectionState::Denial - } - WS2PConnectionState::WaitingConnectMess => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to get mut ep !") - .1 = WS2PConnectionState::NoResponse - } - _ => { - self.ws2p_endpoints - .get_mut(&ws2p_full_id) - .expect("WS2P: Fail to get mut ep !") - .1 = WS2PConnectionState::Unreachable - } - } - self.close_connection(&ws2p_full_id, WS2PCloseConnectionReason::NegociationTimeout); - return WS2PSignal::NegociationTimeout(ws2p_full_id); - } - WS2PConnectionMessagePayload::Timeout => { - self.close_connection(&ws2p_full_id, WS2PCloseConnectionReason::Timeout); - return WS2PSignal::Timeout(ws2p_full_id); - } - WS2PConnectionMessagePayload::UnknowMessage => warn!( - "WS2P : Receive Unknow Message from {}.", - &self.connections_meta_datas[&ws2p_full_id] - .remote_pubkey - .expect("WS2P: UnknowMessage : Fail to get remote_pubkey !") - ), - WS2PConnectionMessagePayload::WrongFormatMessage => warn!( - "WS2P : Receive Wrong Format Message from {}.", - &self.connections_meta_datas[&ws2p_full_id] - .remote_pubkey - .expect("WS2P: WrongFormatMessage : Fail to get remote_pubkey !") - ), - WS2PConnectionMessagePayload::InvalidMessage => return WS2PSignal::Empty, - WS2PConnectionMessagePayload::Close => { - self.close_connection(&ws2p_full_id, WS2PCloseConnectionReason::AuthMessInvalidSig) - } - } - // Detect timeout requests - let mut requests_timeout = Vec::new(); - for &(ref req, ref _ws2p_full_id, ref timestamp) in - self.requests_awaiting_response.clone().values() - { - if SystemTime::now().duration_since(*timestamp).unwrap() > Duration::new(20, 0) { - requests_timeout.push(req.get_req_full_id()); - warn!("request timeout : {:?}", req); - } - } - // Delete (and resend) timeout requests - for req_id in requests_timeout { - //let ws2p_endpoints = self.ws2p_endpoints.clone(); - let _request_option = self.requests_awaiting_response.remove(&req_id.1); - /*if let Some((request, _, _)) = request_option { - let _request_result = self.send_request_to_specific_node( - &get_random_connection(&ws2p_endpoints), - &request, - ); - }*/ - } - WS2PSignal::Empty - } - - pub fn send_request_to_all_connections( - &mut self, - ws2p_request: &NetworkRequest, - ) -> Result<(), SendRequestError> { - let mut count_successful_sending: usize = 0; - let mut errors: Vec<websocket::WebSocketError> = Vec::new(); - match *ws2p_request { - NetworkRequest::GetCurrent(req_full_id, _receiver) => { - for (ws2p_full_id, (_ep, state)) in self.ws2p_endpoints.clone() { - if let WS2PConnectionState::Established = state { - let ws2p_request = NetworkRequest::GetCurrent( - ModuleReqFullId( - req_full_id.0, - ModuleReqId( - (self.requests_awaiting_response.len() - + count_successful_sending) - as u32, - ), - ), - ws2p_full_id, - ); - match self.send_request_to_specific_node(&ws2p_full_id, &ws2p_request) { - Ok(_) => count_successful_sending += 1, - Err(e) => errors.push(e), - }; - } - } - } - /* NetworkRequest::GetBlock(req_full_id, number) => {} */ - NetworkRequest::GetBlocks(_req_full_id, _receiver, _count, _from_number) => {} - NetworkRequest::GetRequirementsPending(req_full_id, _receiver, min_cert) => { - for (ws2p_full_id, (_ep, state)) in self.ws2p_endpoints.clone() { - if let WS2PConnectionState::Established = state { - let ws2p_request = NetworkRequest::GetRequirementsPending( - ModuleReqFullId( - req_full_id.0, - ModuleReqId(self.requests_awaiting_response.len() as u32), - ), - ws2p_full_id, - min_cert, - ); - match self.send_request_to_specific_node(&ws2p_full_id, &ws2p_request) { - Ok(_) => count_successful_sending += 1, - Err(e) => errors.push(e), - }; - } - } - } - _ => { - return Err(SendRequestError::RequestTypeMustNotBeTransmitted()); - } - } - debug!("count_successful_sending = {}", count_successful_sending); - if !errors.is_empty() { - return Err(SendRequestError::WSError(count_successful_sending, errors)); - } - Ok(()) - } - - pub fn send_request_to_specific_node( - &mut self, - receiver_ws2p_full_id: &NodeFullId, - ws2p_request: &NetworkRequest, - ) -> Result<(), websocket::WebSocketError> { - self.websockets - .get_mut(receiver_ws2p_full_id) - .expect("WS2P: Fail to get mut websocket !") - .0 - .send_message(&Message::text( - network_request_to_json(ws2p_request).to_string(), - ))?; - self.requests_awaiting_response.insert( - ws2p_request.get_req_id(), - (*ws2p_request, *receiver_ws2p_full_id, SystemTime::now()), - ); - debug!( - "send request {} to {}", - network_request_to_json(ws2p_request).to_string(), - receiver_ws2p_full_id - ); - Ok(()) - } - - fn connect_to_without_checking_quotas(&mut self, endpoint: &NetworkEndpoint) -> () { - // update connection state - self.ws2p_endpoints - .get_mut( - &endpoint - .node_full_id() - .expect("WS2P: Fail to get ep.node_full_id() !"), - ) - .expect("Fatal error: try to connect to unlisted endpoint ! ") - .1 = WS2PConnectionState::TryToOpenWS; - - // get endpoint url - let ws_url = endpoint.get_url(true); - - // Create WS2PConnection - let mut conn_meta_datas = WS2PConnectionMetaData::new( - "b60a14fd-0826-4ae0-83eb-1a92cd59fd5308535fd3-78f2-4678-9315-cd6e3b7871b1".to_string(), - ); - conn_meta_datas.remote_pubkey = Some(endpoint.pubkey()); - conn_meta_datas.remote_uuid = Some( - endpoint - .node_uuid() - .expect("WS2P: Fail to get ep.node_uuid() !"), - ); - - // Prepare datas for listening thread - let mut datas_for_listening_thread = WS2PDatasForListeningThread { - conn_meta_datas: conn_meta_datas.clone(), - currency: self.currency.clone().expect("WS2P: Fail to get currency !"), - key_pair: self.key_pair.expect("WS2P: Fail to get key_pair!"), - }; - - // Create CONNECT Message - let mut connect_message = WS2PConnectMessageV1 { - currency: self.currency.clone().expect("WS2P: Fail to getcurrency !"), - pubkey: self - .key_pair - .expect("WS2P: Fail to get key_pair!") - .public_key(), - challenge: conn_meta_datas.challenge.clone(), - signature: None, - }; - connect_message.signature = - Some(connect_message.sign(self.key_pair.expect("WS2P: Fail to get key_pair !"))); - let json_connect_message = - serde_json::to_string(&connect_message).expect("Fail to serialize CONNECT message !"); - - // Log - trace!("Try connection to {} ...", ws_url); - - // Listen incoming messages into a thread - let sender_to_main_thread: mpsc::Sender<WS2PThreadSignal> = - mpsc::Sender::clone(&self.main_thread_channel.0); - let (tx2, rx2) = mpsc::channel(); - self.connections_meta_datas - .insert(conn_meta_datas.node_full_id(), conn_meta_datas.clone()); - self.threads_senders_channels - .insert(conn_meta_datas.node_full_id(), tx2); - thread::spawn(move || { - // Open websocket - let open_ws_time = SystemTime::now(); - let client = match ClientBuilder::new(&ws_url) { - Ok(mut client_builder) => match client_builder.connect_insecure() { - Ok(c) => c, - Err(_) => { - debug!("WS2PConnectResult::FailOpenWS"); - sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread.conn_meta_datas.node_full_id(), - WS2PConnectionMessagePayload::FailOpenWS, - ), - )) - .unwrap_or(()); - return (); - } - }, - Err(_) => { - warn!("WS2PConnectResult::WrongUrl : {}", ws_url); - sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread.conn_meta_datas.node_full_id(), - WS2PConnectionMessagePayload::WrongUrl, - ), - )) - .unwrap_or(()); - - return (); - } - }; - let (mut receiver, mut sender) = match client.split() { - Ok((mut r, mut s)) => (r, s), - Err(_) => { - sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread.conn_meta_datas.node_full_id(), - WS2PConnectionMessagePayload::FailToSplitWS, - ), - )) - .unwrap_or(()); - return (); - } - }; - - // Send CONNECT Message - sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread.conn_meta_datas.node_full_id(), - WS2PConnectionMessagePayload::TryToSendConnectMess, - ), - )) - .unwrap_or(()); - match sender.send_message(&Message::text(json_connect_message)) { - Ok(_) => { - sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread.conn_meta_datas.node_full_id(), - WS2PConnectionMessagePayload::WebsocketOk(WebsocketSender(sender)), - ), - )) - .unwrap_or(()); - } - Err(_) => { - receiver.shutdown_all().unwrap_or(()); - sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread.conn_meta_datas.node_full_id(), - WS2PConnectionMessagePayload::FailSendConnectMess, - ), - )) - .unwrap_or(()); - return (); - } - } - - let mut last_mess_time = SystemTime::now(); - let mut spam_interval = false; - let mut spam_counter = 0; - for incoming_message in receiver.incoming_messages() { - // Spam ? - if SystemTime::now().duration_since(last_mess_time).unwrap() - > Duration::new(*WS2P_SPAM_INTERVAL_IN_MILLI_SECS, 0) - { - if spam_interval { - spam_counter += 1; - } else { - spam_interval = true; - spam_counter = 2; - } - } else { - spam_interval = false; - spam_counter = 0; - } - // Spam ? - if spam_counter >= *WS2P_SPAM_LIMIT { - thread::sleep(Duration::from_millis(*WS2P_SPAM_SLEEP_TIME_IN_SEC)); - last_mess_time = SystemTime::now(); - } else { - // Negociation timeout ? - if datas_for_listening_thread.conn_meta_datas.state - != WS2PConnectionState::Established - && SystemTime::now().duration_since(open_ws_time).unwrap() - > Duration::new(*WS2P_NEGOTIATION_TIMEOUT, 0) - { - sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread.conn_meta_datas.node_full_id(), - WS2PConnectionMessagePayload::NegociationTimeout, - ), - )) - .unwrap_or(()); - break; - } - // Connection timeout ? - else if SystemTime::now().duration_since(last_mess_time).unwrap() - > Duration::new(*WS2P_CONNECTION_TIMEOUT, 0) - { - sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread.conn_meta_datas.node_full_id(), - WS2PConnectionMessagePayload::Timeout, - ), - )) - .unwrap_or(()); - break; - } - last_mess_time = SystemTime::now(); - match rx2.recv_timeout(Duration::from_millis(40)) { - Ok(s) => match s { - WS2POrderForListeningThread::Close => break, - }, - Err(e) => { - match e { - mpsc::RecvTimeoutError::Timeout => { - match incoming_message { - Ok(message) => { - if message.is_close() { - if sender_to_main_thread - .send(WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread - .conn_meta_datas - .node_full_id(), - WS2PConnectionMessagePayload::Close, - ), - )) - .is_ok() - { - break; - } - } else if message.is_data() { - // Parse message - let m = Message::from(message); - let s: String = from_utf8(&m.payload) - .expect("WS2P: Fail to convert message payload to String !") - .to_string(); - let message: serde_json::Value = - serde_json::from_str(&s) - .expect("WS2P: Fail to convert string message ton json value !"); - let result = sender_to_main_thread.send( - WS2PThreadSignal::WS2PConnectionMessage( - WS2PConnectionMessage( - datas_for_listening_thread - .conn_meta_datas - .node_full_id(), - datas_for_listening_thread - .conn_meta_datas - .parse_and_check_incoming_message( - &datas_for_listening_thread - .currency, - datas_for_listening_thread - .key_pair, - &message, - ), - ), - ), - ); - if result.is_err() { - debug!("Close ws2p connection because ws2p main thread is unrechable !"); - break; - } - } - } - Err(e) => { - warn!("WebSocketError : {} ! Close ", e); - //receiver.shutdown_all().unwrap_or(()); - break; - } - }; - } - mpsc::RecvTimeoutError::Disconnected => { - break; - } - } - } - }; - } - } - }); - } -} - -#[cfg(test)] -mod tests { - extern crate duniter_conf; - extern crate duniter_crypto; - extern crate duniter_dal; - extern crate duniter_documents; - extern crate duniter_message; - extern crate duniter_module; - extern crate duniter_network; - - use super::parsers::blocks::parse_json_block; - use super::*; - use duniter_crypto::keys::PublicKey; - use duniter_documents::blockchain::v10::documents::BlockDocument; - use duniter_module::DuniterModule; - use duniter_network::network_endpoint::{NetworkEndpoint, NetworkEndpointApi}; - use duniter_network::NetworkBlock; - use std::fs; - use std::path::PathBuf; - use std::time::{SystemTime, UNIX_EPOCH}; - - #[test] - fn test_parse_json_block() { - let json_block = json!({ - "fork": false, - "version": 10, - "nonce": 10500000059239 as u64, - "number": 109966, - "powMin": 88, - "time": 1523300656, - "medianTime": 1523295259, - "membersCount": 933, - "monetaryMass": 146881563, - "unitbase": 0, - "issuersCount": 44, - "issuersFrame": 221, - "issuersFrameVar": 0, - "currency": "g1", - "issuer": "GRBPV3Y7PQnB9LaZhSGuS3BqBJbSHyibzYq65kTh1nQ4", - "signature": "GCg2Lti3TdxWlhA8JF8pRI+dRQ0XZVtcC4BqO/COTpjTQFdWG6qmUNVvdeYCtR/lu1JQe3N/IhrbyV6L/6I+Cg==", - "hash": "000000EF5B2AA849F4C3AF3D35E1284EA1F34A9F617EA806CE8371619023DC74", - "parameters": "", - "previousHash": "000004C00602F8A27AE078DE6351C0DDA1EA0974A78D2BEFA7DFBE7B7C3146FD", - "previousIssuer": "5SwfQubSat5SunNafCsunEGTY93nVM4kLSsuprNqQb6S", - "inner_hash": "61F02B1A6AE2E4B9A1FD66CE673258B4B21C0076795571EE3C9DC440DD06C46C", - "dividend": null, - "identities": [], - "joiners": [], - "actives": [], - "leavers": [], - "revoked": [], - "excluded": [], - "certifications": [ - "Hm5qjaNuHogNRdGZ4vgnLA9DMZVUu5YWzVup5mubuxCc:8AmdBsimcLziXaCS4AcVUfPx7rkjeic7482dLbBkuZw6:109964:yHKBGMeuxyIqFb295gVNK6neRC+U0tmsX1Zed3TLjS3ZZHYYycE1piLcYsTKll4ifNVp6rm+hd/CLdHYB+29CA==", - "BncjgJeFpGsMCCsUfzNLEexjsbuX3V2mg9P67ov2LkwK:DyBUBNpzpfvjtwYYSaVMM6ST6t2DNg3NCE9CU9bRQFhF:105864:cJEGW9WxJwlMA2+4LNAK4YieyseUy1WIkFh1YLYD+JJtJEoCSnIQRXzhiAoRpGaj0bRz8sTpwI6PRkuVoDJJDQ==" - ], - "transactions": [ - { - "version": 10, - "currency": "g1", - "locktime": 0, - "hash": "80FE1E83DC4D0B722CA5F8363EFC6A3E29071032EBB71C1E0DF8D4FEA589C698", - "blockstamp": "109964-00000168105D4A8A8BC8C0DC70033F45ABE472782C75A7F2074D0F4D4A3B7B2B", - "blockstampTime": 0, - "issuers": [ - "6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT" - ], - "inputs": [ - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:98284", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:98519", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:98779", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:99054", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:99326", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:99599", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:99884", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:100174", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:100469", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:100746", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:101036", - "1001:0:D:6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT:101327" - ], - "outputs": [ - "12000:0:SIG(HmH5beJqKGMeotcQUrSW7Wo5tKvAksHmfYXfiSQ9EbWz)", - "12:0:SIG(6PiqcuUWhyiBF3Lgcht8c1yfk6gMfQzcUc46CqrJfeLT)" - ], - "unlocks": [ - "0:SIG(0)", - "1:SIG(0)", - "2:SIG(0)", - "3:SIG(0)", - "4:SIG(0)", - "5:SIG(0)", - "6:SIG(0)", - "7:SIG(0)", - "8:SIG(0)", - "9:SIG(0)", - "10:SIG(0)", - "11:SIG(0)" - ], - "signatures": [ - "MZxoKxYgwufh/s5mwLCsYEZXtIsP1hEKCyAzLipJsvCbR9xj7wXUw0C/ahwvZfBtR7+QVPIfLmwYEol1JcHjDw==" - ], - "comment": "Adhesion 2018" - }, - { - "version": 10, - "currency": "g1", - "locktime": 0, - "hash": "B80507412B35BD5EB437AE0D3EB97E60E3A4974F5CDEA1AF7E2127C0E943481F", - "blockstamp": "109964-00000168105D4A8A8BC8C0DC70033F45ABE472782C75A7F2074D0F4D4A3B7B2B", - "blockstampTime": 0, - "issuers": [ - "8gundJEbfm73Kx3jjw8YivJyz8qD2igjf6baCBLFCxPU" - ], - "inputs": [ - "1001:0:D:8gundJEbfm73Kx3jjw8YivJyz8qD2igjf6baCBLFCxPU:91560", - "1001:0:D:8gundJEbfm73Kx3jjw8YivJyz8qD2igjf6baCBLFCxPU:91850", - "1001:0:D:8gundJEbfm73Kx3jjw8YivJyz8qD2igjf6baCBLFCxPU:92111", - "1001:0:D:8gundJEbfm73Kx3jjw8YivJyz8qD2igjf6baCBLFCxPU:92385", - "1001:0:D:8gundJEbfm73Kx3jjw8YivJyz8qD2igjf6baCBLFCxPU:92635" - ], - "outputs": [ - "5000:0:SIG(BzHnbec1Gov7dLSt1EzJS7vikoQCECeuvZs4wamZAcT1)", - "5:0:SIG(8gundJEbfm73Kx3jjw8YivJyz8qD2igjf6baCBLFCxPU)" - ], - "unlocks": [ - "0:SIG(0)", - "1:SIG(0)", - "2:SIG(0)", - "3:SIG(0)", - "4:SIG(0)" - ], - "signatures": [ - "A+ukwRvLWs1gZQ0KAqAnknEgmRQHdrnOvNuBx/WZqje17BAPrVxSxKpqwU6MiajU+ppigsYp6Bu0FdPf/tGnCQ==" - ], - "comment": "" - }, - { - "version": 10, - "currency": "g1", - "locktime": 0, - "hash": "D8970E6629C0381A78534EEDD86803E9215A7EC4C494BAEA79EB19425F9B4D31", - "blockstamp": "109964-00000168105D4A8A8BC8C0DC70033F45ABE472782C75A7F2074D0F4D4A3B7B2B", - "blockstampTime": 0, - "issuers": [ - "FnSXE7QyBfs4ozoYAt5NEewWhHEPorf38cNXu3kX9xsg" - ], - "inputs": [ - "1000:0:D:FnSXE7QyBfs4ozoYAt5NEewWhHEPorf38cNXu3kX9xsg:36597", - "1000:0:D:FnSXE7QyBfs4ozoYAt5NEewWhHEPorf38cNXu3kX9xsg:36880", - "1000:0:D:FnSXE7QyBfs4ozoYAt5NEewWhHEPorf38cNXu3kX9xsg:37082" - ], - "outputs": [ - "3000:0:SIG(BBC8Rnh4CWN1wBrPLevK7GRFFVDVw7Lu24YNMUmhqoHU)" - ], - "unlocks": [ - "0:SIG(0)", - "1:SIG(0)", - "2:SIG(0)" - ], - "signatures": [ - "OpiF/oQfIigOeAtsteukU0w9FPSELE+BVTxhmsQ8bEeYGlwovG2VF8ZFiJkLLPi6vFuKgwzULJfjNGd97twZCw==" - ], - "comment": "1 billet pour une seance.pour un chouette film" - } - ], - }); - let mut block: BlockDocument = - match parse_json_block(&json_block).expect("Fail to parse test json block !") { - NetworkBlock::V10(network_block_v10) => network_block_v10.uncompleted_block_doc, - _ => { - panic!("Test block must be a v10 block !"); - } - }; - assert_eq!( - block - .inner_hash - .expect("Try to get inner_hash of an uncompleted or reduce block !") - .to_hex(), - "61F02B1A6AE2E4B9A1FD66CE673258B4B21C0076795571EE3C9DC440DD06C46C" - ); - block.compute_hash(); - assert_eq!( - block - .hash - .expect("Try to get hash of an uncompleted or reduce block !") - .0 - .to_hex(), - "000000EF5B2AA849F4C3AF3D35E1284EA1F34A9F617EA806CE8371619023DC74" - ); - } - - #[test] - fn endpoint_db_tests() { - let test_db_path = PathBuf::from("test.db"); - if test_db_path.as_path().exists() { - fs::remove_file(&test_db_path).unwrap(); - } - let db = WS2PModuleDatas::open_db(&test_db_path).unwrap(); - - let current_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); - - let mut endpoint = NetworkEndpoint::parse_from_raw( - "WS2P cb06a19b g1.imirhil.fr 53012 /", - PubKey::Ed25519( - ed25519::PublicKey::from_base58("5gJYnQp8v7bWwk7EWRoL8vCLof1r3y9c6VDdnGSM1GLv") - .unwrap(), - ), - 1, - current_time.as_secs(), - ).expect("Failt to parse test endpoint !"); - - ws2p_db::write_endpoint(&db, &endpoint, 1, current_time.as_secs()); - let mut written_endpoints = - ws2p_db::get_endpoints_for_api(&db, &NetworkEndpointApi(String::from("WS2P"))); - assert_eq!(endpoint, written_endpoints.pop().unwrap()); - - // Test status update - endpoint.set_status(3); - ws2p_db::write_endpoint(&db, &endpoint, 3, current_time.as_secs()); - let mut written_endpoints = - ws2p_db::get_endpoints_for_api(&db, &NetworkEndpointApi(String::from("WS2P"))); - assert_eq!(endpoint, written_endpoints.pop().unwrap()); - } - - #[test] - fn ws2p_requests() { - let module_id = WS2PModule::id(); - let request = NetworkRequest::GetBlocks( - ModuleReqFullId(module_id, ModuleReqId(58)), - NodeFullId::default(), - 50, - 0, - ); - assert_eq!( - network_request_to_json(&request), - json!({ - "reqId": format!("{:x}", 58), - "body": { - "name": "BLOCKS_CHUNK", - "params": { - "count": 50, - "fromNumber": 0 - } - } - }) - ); - assert_eq!( - network_request_to_json(&request).to_string(), - "{\"body\":{\"name\":\"BLOCKS_CHUNK\",\"params\":{\"count\":50,\"fromNumber\":0}},\"reqId\":\"3a\"}" - ); - } - - #[test] - fn ws2p_parse_head() { - let head = json!({ - "message": "WS2POTMIC:HEAD:1:D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:104512-0000051B9CE9C1CA89F269375A6751FB88B9E88DE47A36506057E5BFBCFBB276:c1c39a0a:duniter:1.6.21:3", - "sig": "trtK9GXvTdfND995ohWEderpO3NkIqi1X6mBeVvMcaHckq+lIGqjWvJ9t9Vccz5t+VGaSmGUihDl4q6eldIYBw==", - "messageV2": "WS2POTMIC:HEAD:2:D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:104512-0000051B9CE9C1CA89F269375A6751FB88B9E88DE47A36506057E5BFBCFBB276:c1c39a0a:duniter:1.6.21:3:25:22", - "sigV2": "x6ehPMuYjGY+z7wEGnJGyMBxMKUdu01RWaF0b0XCtoVjg67cCvT4H0V/Qcxn4bAGqzy5ux2fA7NiI+81bBnqDw==", - "step": 0 - }); - let mut heads_count = 0; - if let Some(head) = NetworkHead::from_json_value(&head) { - if let NetworkHead::V2(ref head_v2) = head { - heads_count += 1; - assert_eq!( - head_v2.message.to_string(), - String::from("WS2POTMIC:HEAD:1:D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:104512-0000051B9CE9C1CA89F269375A6751FB88B9E88DE47A36506057E5BFBCFBB276:c1c39a0a:duniter:1.6.21:3") - ); - } - assert_eq!(head.verify(), true); - } - assert_eq!(heads_count, 1); - } -} diff --git a/ws2p/ok_message.rs b/ws2p/ok_message.rs deleted file mode 100644 index e0c5c54a..00000000 --- a/ws2p/ok_message.rs +++ /dev/null @@ -1,69 +0,0 @@ -extern crate duniter_crypto; -extern crate serde; -extern crate serde_json; - -use self::serde::ser::{Serialize, SerializeStruct, Serializer}; -use super::WS2PMessage; -use duniter_crypto::keys::*; - -#[derive(Debug, Clone)] -pub struct WS2POkMessageV1 { - pub currency: String, - pub pubkey: PubKey, - pub challenge: String, - pub signature: Option<Sig>, -} - -impl WS2PMessage for WS2POkMessageV1 { - fn parse(v: &serde_json::Value, currency: String) -> Option<Self> { - let signature = match v.get("sig") { - Some(signature) => signature - .as_str() - .expect("Parsing of OK message : fail to convert sig to str") - .to_string(), - None => return None, - }; - let pubkey: PubKey = PubKey::Ed25519( - ed25519::PublicKey::from_base58("969qRJs8KhsnkyzqarpL4RKZGMdVKNbZgu8fhsigM7Lj") - .expect("fail to create default pubkey !"), - ); - let signature: Option<Sig> = Some(Sig::Ed25519( - duniter_crypto::keys::Signature::from_base64(&signature) - .expect("fail to parse signature of OK message !"), - )); - Some(WS2POkMessageV1 { - currency, - pubkey, - challenge: "".to_string(), - signature, - }) - } - fn to_raw(&self) -> String { - format!( - "WS2P:OK:{}:{}:{}", - self.currency, self.pubkey, self.challenge - ) - } - fn verify(&self) -> bool { - self.pubkey - .verify(self.to_raw().as_bytes(), &self.signature.unwrap()) - } -} - -impl Serialize for WS2POkMessageV1 { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - let mut connect_message_in_json = serializer.serialize_struct("message", 2)?; - connect_message_in_json.serialize_field("auth", "OK")?; - connect_message_in_json.serialize_field( - "sig", - &self - .signature - .expect("Fail to serialize OK message : the signature field is set to None !") - .to_string(), - )?; - connect_message_in_json.end() - } -} diff --git a/ws2p/parsers/blocks.rs b/ws2p/parsers/blocks.rs deleted file mode 100644 index 1d08cc31..00000000 --- a/ws2p/parsers/blocks.rs +++ /dev/null @@ -1,149 +0,0 @@ -extern crate serde_json; - -use super::excluded::parse_exclusions_from_json_value; -use super::identities::parse_compact_identity; -use super::transactions::parse_transaction; -use duniter_crypto::keys::*; -use duniter_documents::blockchain::v10::documents::block::{ - BlockV10Parameters, CurrencyName, TxDocOrTxHash, -}; -use duniter_documents::blockchain::v10::documents::membership::*; -use duniter_documents::blockchain::v10::documents::BlockDocument; -use duniter_documents::{BlockHash, BlockId, Hash}; -use duniter_network::{NetworkBlock, NetworkBlockV10}; -use std::str::FromStr; - -fn parse_previous_hash(block_number: &BlockId, source: &serde_json::Value) -> Option<Hash> { - match source.get("previousHash")?.as_str() { - Some(hash_str) => match Hash::from_hex(hash_str) { - Ok(hash) => Some(hash), - Err(_) => None, - }, - None => if block_number.0 > 0 { - None - } else { - Some(Hash::default()) - }, - } -} - -fn parse_previous_issuer(source: &serde_json::Value) -> Option<PubKey> { - match source.get("previousIssuer")?.as_str() { - Some(pubkey_str) => match ed25519::PublicKey::from_base58(pubkey_str) { - Ok(pubkey) => Some(PubKey::Ed25519(pubkey)), - Err(_) => None, - }, - None => None, - } -} - -fn parse_memberships( - currency: &str, - membership_type: MembershipType, - json_memberships: &serde_json::Value, -) -> Option<Vec<MembershipDocument>> { - let mut memberships = Vec::new(); - for membership in super::memberships::parse_memberships_from_json_value( - currency, - membership_type, - &json_memberships.as_array()?, - ) { - if let Ok(membership) = membership { - memberships.push(membership); - } else { - warn!("dal::parsers::blocks::parse_memberships() : MembershipParseError !") - } - } - Some(memberships) -} - -pub fn parse_json_block(source: &serde_json::Value) -> Option<NetworkBlock> { - let number = BlockId(source.get("number")?.as_u64()? as u32); - let currency = source.get("currency")?.as_str()?.to_string(); - let issuer = match ed25519::PublicKey::from_base58(source.get("issuer")?.as_str()?) { - Ok(pubkey) => PubKey::Ed25519(pubkey), - Err(_) => return None, - }; - let sig = match ed25519::Signature::from_base64(source.get("signature")?.as_str()?) { - Ok(sig) => Sig::Ed25519(sig), - Err(_) => return None, - }; - let hash = match Hash::from_hex(source.get("hash")?.as_str()?) { - Ok(hash) => hash, - Err(_) => return None, - }; - let parameters = if let Some(params_json) = source.get("parameters") { - if let Ok(params) = BlockV10Parameters::from_str(params_json.as_str()?) { - Some(params) - } else { - None - } - } else { - None - }; - let previous_hash = parse_previous_hash(&number, source)?; - let previous_issuer = parse_previous_issuer(source); - let inner_hash = match Hash::from_hex(source.get("inner_hash")?.as_str()?) { - Ok(hash) => Some(hash), - Err(_) => return None, - }; - let dividend = match source.get("dividend")?.as_u64() { - Some(dividend) => Some(dividend as usize), - None => None, - }; - let mut identities = Vec::new(); - for raw_idty in source.get("identities")?.as_array()? { - identities.push(parse_compact_identity(¤cy, &raw_idty)?); - } - let joiners = parse_memberships(¤cy, MembershipType::In(), source.get("joiners")?)?; - let actives = parse_memberships(¤cy, MembershipType::In(), source.get("actives")?)?; - let leavers = parse_memberships(¤cy, MembershipType::Out(), source.get("actives")?)?; - let mut transactions = Vec::new(); - for json_tx in source.get("transactions")?.as_array()? { - transactions.push(TxDocOrTxHash::TxDoc(Box::new(parse_transaction( - "g1", &json_tx, - )?))); - } - let block_doc = BlockDocument { - nonce: source.get("nonce")?.as_i64()? as u64, - number: BlockId(source.get("number")?.as_u64()? as u32), - pow_min: source.get("powMin")?.as_u64()? as usize, - time: source.get("time")?.as_u64()?, - median_time: source.get("medianTime")?.as_u64()?, - members_count: source.get("membersCount")?.as_u64()? as usize, - monetary_mass: source.get("monetaryMass")?.as_u64()? as usize, - unit_base: source.get("unitbase")?.as_u64()? as usize, - issuers_count: source.get("issuersCount")?.as_u64()? as usize, - issuers_frame: source.get("issuersFrame")?.as_i64()? as isize, - issuers_frame_var: source.get("issuersFrameVar")?.as_i64()? as isize, - currency: CurrencyName(currency), - issuers: vec![issuer], - signatures: vec![sig], - hash: Some(BlockHash(hash)), - parameters, - previous_hash, - previous_issuer, - inner_hash, - dividend, - identities, - joiners, - actives, - leavers, - revoked: Vec::with_capacity(0), - excluded: parse_exclusions_from_json_value(&source.get("excluded")?.as_array()?), - certifications: Vec::with_capacity(0), - transactions, - inner_hash_and_nonce_str: format!( - "InnerHash: {}\nNonce: {}\n", - inner_hash - .expect("Try to get inner_hash of an uncompleted or reduce block !") - .to_hex(), - source.get("nonce")?.as_u64()? - ), - }; - Some(NetworkBlock::V10(Box::new(NetworkBlockV10 { - uncompleted_block_doc: block_doc, - revoked: source.get("revoked")?.as_array()?.clone(), - certifications: source.get("certifications")?.as_array()?.clone(), - }))) -} diff --git a/ws2p/parsers/excluded.rs b/ws2p/parsers/excluded.rs deleted file mode 100644 index 645f3bc5..00000000 --- a/ws2p/parsers/excluded.rs +++ /dev/null @@ -1,27 +0,0 @@ -extern crate serde; -extern crate serde_json; - -use duniter_crypto::keys::ed25519; -use duniter_crypto::keys::*; - -pub fn parse_exclusions(json_datas: &str) -> Option<Vec<PubKey>> { - let raw_exclusions: serde_json::Value = serde_json::from_str(json_datas).unwrap(); - - if raw_exclusions.is_array() { - Some(parse_exclusions_from_json_value( - raw_exclusions.as_array().unwrap(), - )) - } else { - None - } -} - -pub fn parse_exclusions_from_json_value(array_exclusions: &[serde_json::Value]) -> Vec<PubKey> { - let mut exclusions: Vec<PubKey> = Vec::new(); - for exclusion in array_exclusions.iter() { - exclusions.push(PubKey::Ed25519( - ed25519::PublicKey::from_base58(exclusion.as_str().unwrap()).unwrap(), - )); - } - exclusions -} diff --git a/ws2p/parsers/identities.rs b/ws2p/parsers/identities.rs deleted file mode 100644 index ef623354..00000000 --- a/ws2p/parsers/identities.rs +++ /dev/null @@ -1,87 +0,0 @@ -extern crate serde_json; - -use duniter_crypto::keys::*; -use duniter_documents::blockchain::v10::documents::identity::IdentityDocumentBuilder; -use duniter_documents::blockchain::v10::documents::IdentityDocument; -use duniter_documents::blockchain::DocumentBuilder; -use duniter_documents::Blockstamp; - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum IdentityParseError { - WrongFormat(), -} - -pub fn parse_identities(currency: &str, json_datas: &str) -> Option<Vec<IdentityDocument>> { - let raw_idties: serde_json::Value = serde_json::from_str(json_datas).unwrap(); - if raw_idties.is_array() { - return Some( - parse_identities_from_json_value(currency, raw_idties.as_array().unwrap()) - .iter() - .map(|i| { - i.clone() - .expect("Fatal error : Fail to parse identity from local DB !") - }) - .collect(), - ); - } - None -} - -pub fn parse_identities_from_json_value( - currency: &str, - array_identities: &[serde_json::Value], -) -> Vec<Result<IdentityDocument, IdentityParseError>> { - array_identities - .iter() - .map(|idty| { - let idty_datas: Vec<&str> = idty.as_str().unwrap().split(':').collect(); - if idty_datas.len() == 4 { - let idty_doc_builder = IdentityDocumentBuilder { - currency, - issuer: &PubKey::Ed25519( - ed25519::PublicKey::from_base58(idty_datas[0]).unwrap(), - ), - blockstamp: &Blockstamp::from_string(idty_datas[2]).unwrap(), - username: idty_datas[3], - }; - let idty_sig = - Sig::Ed25519(ed25519::Signature::from_base64(idty_datas[1]).unwrap()); - //memberships.push(membership_doc_builder.build_with_signature(vec![membership_sig])); - Ok(idty_doc_builder.build_with_signature(vec![idty_sig])) - } else { - Err(IdentityParseError::WrongFormat()) - } - }) - .collect() -} - -pub fn parse_compact_identity( - currency: &str, - source: &serde_json::Value, -) -> Option<IdentityDocument> { - if source.is_string() { - let idty_elements: Vec<&str> = source.as_str().unwrap().split(':').collect(); - let issuer = match ed25519::PublicKey::from_base58(idty_elements[0]) { - Ok(pubkey) => PubKey::Ed25519(pubkey), - Err(_) => return None, - }; - let signature = match ed25519::Signature::from_base64(idty_elements[1]) { - Ok(sig) => Sig::Ed25519(sig), - Err(_) => return None, - }; - let blockstamp = match Blockstamp::from_string(idty_elements[2]) { - Ok(blockstamp) => blockstamp, - Err(_) => return None, - }; - let username = idty_elements[3]; - let idty_doc_builder = IdentityDocumentBuilder { - currency, - username, - blockstamp: &blockstamp, - issuer: &issuer, - }; - Some(idty_doc_builder.build_with_signature(vec![signature])) - } else { - None - } -} diff --git a/ws2p/parsers/memberships.rs b/ws2p/parsers/memberships.rs deleted file mode 100644 index 51704255..00000000 --- a/ws2p/parsers/memberships.rs +++ /dev/null @@ -1,68 +0,0 @@ -extern crate serde_json; - -use duniter_crypto::keys::*; -use duniter_documents::blockchain::v10::documents::membership::{ - MembershipDocumentBuilder, MembershipType, -}; -use duniter_documents::blockchain::v10::documents::MembershipDocument; -use duniter_documents::blockchain::DocumentBuilder; -use duniter_documents::Blockstamp; - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum MembershipParseError { - WrongFormat(), -} - -pub fn parse_memberships( - currency: &str, - membership_type: MembershipType, - json_datas: &str, -) -> Option<Vec<MembershipDocument>> { - let raw_memberships: serde_json::Value = serde_json::from_str(json_datas).unwrap(); - if raw_memberships.is_array() { - return Some( - parse_memberships_from_json_value( - currency, - membership_type, - raw_memberships.as_array().unwrap(), - ).iter() - .map(|m| { - m.clone() - .expect("Fatal error : Fail to parse membership from local DB !") - }) - .collect(), - ); - } - None -} - -pub fn parse_memberships_from_json_value( - currency: &str, - membership_type: MembershipType, - array_memberships: &[serde_json::Value], -) -> Vec<Result<MembershipDocument, MembershipParseError>> { - //let memberships: Vec<MembershipDocument> = Vec::new(); - array_memberships - .iter() - .map(|membership| { - let membership_datas: Vec<&str> = membership.as_str().unwrap().split(':').collect(); - if membership_datas.len() == 5 { - let membership_doc_builder = MembershipDocumentBuilder { - currency, - issuer: &PubKey::Ed25519( - ed25519::PublicKey::from_base58(membership_datas[0]).unwrap(), - ), - blockstamp: &Blockstamp::from_string(membership_datas[2]).unwrap(), - membership: membership_type, - identity_username: membership_datas[4], - identity_blockstamp: &Blockstamp::from_string(membership_datas[3]).unwrap(), - }; - let membership_sig = - Sig::Ed25519(ed25519::Signature::from_base64(membership_datas[1]).unwrap()); - Ok(membership_doc_builder.build_with_signature(vec![membership_sig])) - } else { - Err(MembershipParseError::WrongFormat()) - } - }) - .collect() -} diff --git a/ws2p/parsers/mod.rs b/ws2p/parsers/mod.rs deleted file mode 100644 index 74de7390..00000000 --- a/ws2p/parsers/mod.rs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (C) 2018 The Duniter Project Developers. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -pub mod blocks; -pub mod excluded; -pub mod identities; -pub mod memberships; -pub mod transactions; - -#[cfg(test)] -mod tests { - use super::transactions::*; - use duniter_crypto::keys::*; - use duniter_documents::blockchain::v10::documents::transaction::*; - use duniter_documents::blockchain::DocumentBuilder; - use duniter_documents::Blockstamp; - - #[test] - fn parse_json_tx() { - let tx_json = json!({ - "version": 10, - "currency": "g1", - "locktime": 0, - "hash": "3424206EF64C69E5F8C3906AAE571E378A498FCDAE0B85E9405A5205D7148EFE", - "blockstamp": "112533-000002150F2E805E604D9B31212D079570AAD8D3A4D8BB75F2C15A94A345B6B1", - "blockstampTime": 0, - "issuers": [ - "51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2" - ], - "inputs": [ - "1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496" - ], - "outputs": [ - "1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)" - ], - "unlocks": [ - "0:SIG(0)" - ], - "signatures": [ - "5olrjFylTCsVq8I5Yr7FpXeviynICyvIwe1yG5N0RJF+VZb+bCFBnLAMpmMCU2qzUvK7z41UXOrMRybXiLa2Dw==" - ], - "comment": "Merci pour la calligraphie ;) de Liam" - }); - - let tx_builder = TransactionDocumentBuilder { - currency: "g1", - blockstamp: &Blockstamp::from_string( - "112533-000002150F2E805E604D9B31212D079570AAD8D3A4D8BB75F2C15A94A345B6B1", - ).unwrap(), - locktime: &0, - issuers: &vec![PubKey::Ed25519( - ed25519::PublicKey::from_base58("51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2") - .unwrap(), - )], - inputs: &vec![ - TransactionInput::parse_from_str( - "1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496", - ).unwrap(), - ], - outputs: &vec![ - TransactionOutput::parse_from_str( - "1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)", - ).unwrap(), - ], - unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()], - comment: "Merci pour la calligraphie ;) de Liam", - }; - - assert_eq!( - parse_transaction("g1", &tx_json).expect("Fail to parse transaction !"), - tx_builder.build_with_signature(vec![Sig::Ed25519(ed25519::Signature::from_base64("5olrjFylTCsVq8I5Yr7FpXeviynICyvIwe1yG5N0RJF+VZb+bCFBnLAMpmMCU2qzUvK7z41UXOrMRybXiLa2Dw==").unwrap())]) - ); - } - - #[test] - fn parse_json_tx2() { - let tx_json = json!({ - "version": 10, - "currency": "g1", - "locktime": 0, - "hash": "F98BF7A8BF82E76F5B69E70CEF0A07A08BFDB03561955EC57B254DB1E958529C", - "blockstamp": "58-00005B9167EBA1E32C6EAD42AE7F72D8F14B765D3C9E47D233B553D47C5AEE0C", - "blockstampTime": 1488990541, - "issuers": [ - "FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD" - ], - "inputs": [ - "1000:0:D:FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD:1" - ], - "outputs": [ - "3:0:SIG(7vU9BMDhN6fBuRa2iK3JRbC6pqQKb4qDMGsFcQuT5cz)", - "997:0:SIG(FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD)" - ], - "unlocks": [ - "0:SIG(0)" - ], - "signatures": [ - "VWbvsiybM4L2X5+o+6lIiuKNw5KrD1yGZqmV+lHtA28XoRUFzochSIgfoUqBsTAaYEHY45vSX917LDXudTEzBg==" - ], - "comment": "Un petit cafe ;-)" - }); - - let tx_builder = TransactionDocumentBuilder { - currency: "g1", - blockstamp: &Blockstamp::from_string( - "58-00005B9167EBA1E32C6EAD42AE7F72D8F14B765D3C9E47D233B553D47C5AEE0C", - ).unwrap(), - locktime: &0, - issuers: &vec![PubKey::Ed25519( - ed25519::PublicKey::from_base58("FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD") - .unwrap(), - )], - inputs: &vec![ - TransactionInput::parse_from_str( - "1000:0:D:FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD:1", - ).unwrap(), - ], - outputs: &vec![ - TransactionOutput::parse_from_str( - "3:0:SIG(7vU9BMDhN6fBuRa2iK3JRbC6pqQKb4qDMGsFcQuT5cz)", - ).unwrap(), - TransactionOutput::parse_from_str( - "997:0:SIG(FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD)", - ).unwrap(), - ], - unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()], - comment: "Un petit cafe ;-)", - }; - - assert_eq!( - parse_transaction("g1", &tx_json).expect("Fail to parse transaction !"), - tx_builder.build_with_signature(vec![Sig::Ed25519(ed25519::Signature::from_base64("VWbvsiybM4L2X5+o+6lIiuKNw5KrD1yGZqmV+lHtA28XoRUFzochSIgfoUqBsTAaYEHY45vSX917LDXudTEzBg==").unwrap())]) - ); - } -} diff --git a/ws2p/parsers/transactions.rs b/ws2p/parsers/transactions.rs deleted file mode 100644 index e4b21fa4..00000000 --- a/ws2p/parsers/transactions.rs +++ /dev/null @@ -1,234 +0,0 @@ -extern crate serde; -extern crate serde_json; - -use duniter_crypto::keys::*; -use duniter_documents::blockchain::v10::documents::transaction::{ - TransactionDocument, TransactionDocumentBuilder, TransactionInput, TransactionInputUnlocks, - TransactionOutput, -}; -use duniter_documents::blockchain::DocumentBuilder; -use duniter_documents::Blockstamp; - -pub fn parse_compact_transactions( - currency: &str, - json_datas: &str, -) -> Option<Vec<TransactionDocument>> { - let raw_transactions: serde_json::Value = - serde_json::from_str(json_datas).expect("Fatal error : fail to jsonifie tx from DB !"); - - if raw_transactions.is_array() { - let mut transactions = Vec::new(); - for transaction in raw_transactions.as_array().unwrap() { - let transaction_lines: Vec<&str> = transaction - .as_str() - .expect("Fail to parse tx from DB !") - .split('$') - .collect(); - let tx_headers: Vec<&str> = transaction_lines[0].split(':').collect(); - let issuers_count = tx_headers[2] - .parse() - .expect("Fail to parse tx header NB_ISSUERS !"); - let inputs_count = tx_headers[3] - .parse() - .expect("Fail to parse tx header NB_INPUTS !"); - let unlocks_count = tx_headers[4] - .parse() - .expect("Fail to parse tx header NB_UNLOCKS !"); - let outputs_count = tx_headers[5] - .parse() - .expect("Fail to parse tx header NB_OUTPUTS !"); - let has_comment: usize = tx_headers[6] - .parse() - .expect("Fail to parse tx header HAS_COMMENT !"); - let locktime = tx_headers[7] - .parse() - .expect("Fail to parse tx header LOCKTIME !"); - let blockstamp = Blockstamp::from_string(transaction_lines[1]) - .expect("Fail to parse tx BLOCKSTAMP !"); - let mut line = 2; - let mut issuers = Vec::new(); - for _ in 0..issuers_count { - issuers.push(PubKey::Ed25519( - ed25519::PublicKey::from_base58(transaction_lines[line]) - .expect("Fail to parse tx issuer !"), - )); - line += 1; - } - let mut inputs = Vec::new(); - for _ in 0..inputs_count { - inputs.push( - TransactionInput::parse_from_str(transaction_lines[line]) - .expect("Fail to parse tx issuer !"), - ); - line += 1; - } - let mut unlocks = Vec::new(); - for _ in 0..unlocks_count { - unlocks.push( - TransactionInputUnlocks::parse_from_str(transaction_lines[line]) - .expect("Fail to parse tx issuer !"), - ); - line += 1; - } - let mut outputs = Vec::new(); - for _ in 0..outputs_count { - outputs.push( - TransactionOutput::parse_from_str(transaction_lines[line]) - .expect("Fail to parse tx issuer !"), - ); - line += 1; - } - let mut comment = ""; - if has_comment == 1 { - comment = transaction_lines[line]; - line += 1; - } - let mut signatures = Vec::new(); - for _ in 0..issuers_count { - signatures.push(Sig::Ed25519( - ed25519::Signature::from_base64(transaction_lines[line]) - .expect("Fail to parse tx signature !"), - )); - line += 1; - } - let tx_doc_builder = TransactionDocumentBuilder { - currency, - blockstamp: &blockstamp, - locktime: &locktime, - issuers: &issuers, - inputs: &inputs, - unlocks: &unlocks, - outputs: &outputs, - comment, - }; - transactions.push(tx_doc_builder.build_with_signature(signatures)); - } - Some(transactions) - } else { - None - } -} - -pub fn parse_transaction( - currency: &str, - source: &serde_json::Value, -) -> Option<TransactionDocument> { - //debug!("transaction={:#?}", source); - let blockstamp = match Blockstamp::from_string(source.get("blockstamp")?.as_str()?) { - Ok(blockstamp) => blockstamp, - Err(_) => { - return None; - } - }; - let locktime = source.get("locktime")?.as_i64()? as u64; - let issuers_array = source.get("issuers")?.as_array()?; - let mut issuers = Vec::with_capacity(issuers_array.len()); - for issuer in issuers_array { - match ed25519::PublicKey::from_base58(issuer.as_str()?) { - Ok(pubkey) => issuers.push(PubKey::Ed25519(pubkey)), - Err(_) => { - return None; - } - } - } - let inputs_array = source.get("inputs")?.as_array()?; - let mut inputs = Vec::with_capacity(inputs_array.len()); - for input in inputs_array { - let input_str = input.as_str()?; - match TransactionInput::parse_from_str(input_str) { - Ok(input) => inputs.push(input), - Err(_) => { - return None; - } - } - } - let unlocks_array = source.get("unlocks")?.as_array()?; - let mut unlocks = Vec::with_capacity(unlocks_array.len()); - for unlock in unlocks_array { - match TransactionInputUnlocks::parse_from_str(unlock.as_str()?) { - Ok(unlock) => unlocks.push(unlock), - Err(_) => { - return None; - } - } - } - let outputs_array = source.get("outputs")?.as_array()?; - let mut outputs = Vec::with_capacity(outputs_array.len()); - for output in outputs_array { - match TransactionOutput::parse_from_str(output.as_str()?) { - Ok(output) => outputs.push(output), - Err(_) => { - return None; - } - } - } - let signatures_array = source.get("signatures")?.as_array()?; - let mut signatures = Vec::with_capacity(signatures_array.len()); - for signature in signatures_array { - match ed25519::Signature::from_base64(signature.as_str()?) { - Ok(signature) => signatures.push(Sig::Ed25519(signature)), - Err(_) => { - return None; - } - } - } - let comment = source.get("comment")?.as_str()?; - - let tx_doc_builder = TransactionDocumentBuilder { - currency, - blockstamp: &blockstamp, - locktime: &locktime, - issuers: &issuers, - inputs: &inputs, - unlocks: &unlocks, - outputs: &outputs, - comment, - }; - Some(tx_doc_builder.build_with_signature(signatures)) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parse_compact_tx() { - let compact_txs = "[\"TX:10:1:1:1:1:1:0$\ -112533-000002150F2E805E604D9B31212D079570AAD8D3A4D8BB75F2C15A94A345B6B1$\ -51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2$\ -1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496$\ -0:SIG(0)$\ -1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)$\ -Merci pour la calligraphie ;) de Liam$\ -5olrjFylTCsVq8I5Yr7FpXeviynICyvIwe1yG5N0RJF+VZb+bCFBnLAMpmMCU2qzUvK7z41UXOrMRybXiLa2Dw==\"]"; - - let tx_builder = TransactionDocumentBuilder { - currency: "g1", - blockstamp: &Blockstamp::from_string( - "112533-000002150F2E805E604D9B31212D079570AAD8D3A4D8BB75F2C15A94A345B6B1", - ).unwrap(), - locktime: &0, - issuers: &vec![PubKey::Ed25519( - ed25519::PublicKey::from_base58("51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2") - .unwrap(), - )], - inputs: &vec![ - TransactionInput::parse_from_str( - "1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496", - ).unwrap(), - ], - outputs: &vec![ - TransactionOutput::parse_from_str( - "1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)", - ).unwrap(), - ], - unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()], - comment: "Merci pour la calligraphie ;) de Liam", - }; - - assert_eq!( - parse_compact_transactions("g1", compact_txs).expect("Fail to parse compact transactions !"), - vec![tx_builder.build_with_signature(vec![Sig::Ed25519(ed25519::Signature::from_base64("5olrjFylTCsVq8I5Yr7FpXeviynICyvIwe1yG5N0RJF+VZb+bCFBnLAMpmMCU2qzUvK7z41UXOrMRybXiLa2Dw==").unwrap())])] - ); - } -} diff --git a/ws2p/serializer.rs b/ws2p/serializer.rs deleted file mode 100644 index f7800068..00000000 --- a/ws2p/serializer.rs +++ /dev/null @@ -1,21 +0,0 @@ -extern crate serde_json; - -use duniter_network::network_head::*; - -use std::ops::Deref; - -pub fn serialize_head(head: NetworkHead) -> serde_json::Value { - match head { - NetworkHead::V2(box_head_v2) => { - let head_v2 = box_head_v2.deref(); - json!({ - "message": head_v2.message.to_string(), - "sig": head_v2.sig.to_string(), - "messageV2": head_v2.message_v2.to_string(), - "sigV2": head_v2.sig_v2.to_string(), - "step": head_v2.step + 1 - }) - } - _ => panic!("HEAD version not supported !"), - } -} diff --git a/ws2p/ws2p_connection.rs b/ws2p/ws2p_connection.rs deleted file mode 100644 index 84578ca8..00000000 --- a/ws2p/ws2p_connection.rs +++ /dev/null @@ -1,399 +0,0 @@ -extern crate serde_json; -extern crate websocket; - -use duniter_crypto::keys::*; -use duniter_module::ModuleReqId; -use duniter_network::network_endpoint::{NetworkEndpoint, NetworkEndpointApi}; -use duniter_network::{NetworkDocument, NodeUUID}; -use parsers::blocks::parse_json_block; -use std::fmt::Debug; -use std::net::TcpStream; - -use super::{NodeFullId, WS2PAckMessageV1, WS2PConnectMessageV1, WS2PMessage, WS2POkMessageV1}; - -#[derive(Debug, Copy, Clone)] -pub enum WS2POrderForListeningThread { - Close, -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum WS2PConnectionState { - NeverTry = 0, - TryToOpenWS = 1, - WSError = 2, - TryToSendConnectMess = 3, - Unreachable = 4, - WaitingConnectMess = 5, - NoResponse = 6, - ConnectMessOk = 7, - OkMessOkWaitingAckMess = 8, - AckMessOk = 9, - Denial = 10, - Close = 11, - Established = 12, -} - -impl From<u32> for WS2PConnectionState { - fn from(integer: u32) -> Self { - match integer { - 1 | 2 => WS2PConnectionState::WSError, - 3 | 4 => WS2PConnectionState::Unreachable, - 5 | 6 => WS2PConnectionState::NoResponse, - 7 | 8 | 9 | 10 => WS2PConnectionState::Denial, - 11 | 12 => WS2PConnectionState::Close, - _ => WS2PConnectionState::NeverTry, - } - } -} - -impl WS2PConnectionState { - pub fn from_u32(integer: u32, from_db: bool) -> Self { - if from_db { - WS2PConnectionState::from(integer) - } else { - match integer { - 1 => WS2PConnectionState::TryToOpenWS, - 2 => WS2PConnectionState::WSError, - 3 | 4 => WS2PConnectionState::Unreachable, - 5 | 6 => WS2PConnectionState::NoResponse, - 7 => WS2PConnectionState::ConnectMessOk, - 8 => WS2PConnectionState::OkMessOkWaitingAckMess, - 9 => WS2PConnectionState::AckMessOk, - 10 => WS2PConnectionState::Denial, - 11 => WS2PConnectionState::Close, - 12 => WS2PConnectionState::Established, - _ => WS2PConnectionState::NeverTry, - } - } - } - pub fn to_u32(&self) -> u32 { - match *self { - WS2PConnectionState::NeverTry => 0, - _ => 1, - } - } -} - -pub struct WebsocketSender(pub websocket::sender::Writer<TcpStream>); - -impl Debug for WebsocketSender { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "WebsocketSender {{ }}") - } -} - -#[derive(Debug)] -pub enum WS2PConnectionMessagePayload { - FailOpenWS, - WrongUrl, - FailToSplitWS, - TryToSendConnectMess, - FailSendConnectMess, - WebsocketOk(WebsocketSender), - NegociationTimeout, - ValidConnectMessage(String, WS2PConnectionState), - ValidAckMessage(String, WS2PConnectionState), - ValidOk(WS2PConnectionState), - DalRequest(ModuleReqId, serde_json::Value), - PeerCard(serde_json::Value, Vec<NetworkEndpoint>), - Heads(Vec<serde_json::Value>), - Document(NetworkDocument), - ReqResponse(ModuleReqId, serde_json::Value), - InvalidMessage, - WrongFormatMessage, - UnknowMessage, - Timeout, - Close, -} - -#[derive(Debug)] -pub struct WS2PConnectionMessage(pub NodeFullId, pub WS2PConnectionMessagePayload); - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum WS2PCloseConnectionReason { - AuthMessInvalidSig, - NegociationTimeout, - Timeout, - Unknow, -} - -#[derive(Debug, Clone)] -pub struct WS2PConnectionMetaData { - pub state: WS2PConnectionState, - pub remote_uuid: Option<NodeUUID>, - pub remote_pubkey: Option<PubKey>, - pub challenge: String, - pub remote_challenge: String, - pub current_blockstamp: Option<(u32, String)>, -} - -#[derive(Debug, Clone)] -pub struct WS2PDatasForListeningThread { - pub conn_meta_datas: WS2PConnectionMetaData, - pub currency: String, - pub key_pair: KeyPairEnum, -} - -impl WS2PConnectionMetaData { - pub fn new(challenge: String) -> Self { - WS2PConnectionMetaData { - state: WS2PConnectionState::WaitingConnectMess, - remote_uuid: None, - remote_pubkey: None, - challenge, - remote_challenge: "".to_string(), - current_blockstamp: None, - } - } - - pub fn node_full_id(&self) -> NodeFullId { - NodeFullId( - self.clone() - .remote_uuid - .expect("Fail to get NodeFullId : remote_uuid is None !"), - self.remote_pubkey - .expect("Fail to get NodeFullId : remote_pubkey is None !"), - ) - } - pub fn parse_and_check_incoming_message( - &mut self, - currency: &str, - key_pair: KeyPairEnum, - m: &serde_json::Value, - ) -> WS2PConnectionMessagePayload { - if let Some(s) = m.get("auth") { - if s.is_string() { - match s.as_str().unwrap() { - "CONNECT" => { - let message = WS2PConnectMessageV1::parse(m, currency.to_string()) - .expect("Failed to parsing CONNECT Message !"); - if message.verify() && message.pubkey == self.remote_pubkey.unwrap() { - match self.state { - WS2PConnectionState::WaitingConnectMess => { - trace!("CONNECT sig is valid."); - self.state = WS2PConnectionState::ConnectMessOk; - self.remote_challenge = message.challenge.clone(); - let mut response = WS2PAckMessageV1 { - currency: currency.to_string(), - pubkey: key_pair.public_key(), - challenge: self.remote_challenge.clone(), - signature: None, - }; - response.signature = Some(response.sign(key_pair)); - return WS2PConnectionMessagePayload::ValidConnectMessage( - serde_json::to_string(&response).unwrap(), - self.state, - ); - } - _ => return WS2PConnectionMessagePayload::InvalidMessage, - } - } else { - warn!("The signature of message CONNECT is invalid !") - } - } - "ACK" => { - let mut message = WS2PAckMessageV1::parse(m, currency.to_string()) - .expect("Failed to parsing ACK Message !"); - message.challenge = self.challenge.to_string(); - if message.verify() { - trace!("ACK sig is valid."); - self.state = match self.state { - WS2PConnectionState::ConnectMessOk => { - WS2PConnectionState::AckMessOk - } - WS2PConnectionState::OkMessOkWaitingAckMess => { - WS2PConnectionState::Established - } - _ => return WS2PConnectionMessagePayload::InvalidMessage, - }; - let mut response = WS2POkMessageV1 { - currency: currency.to_string(), - pubkey: key_pair.public_key(), - challenge: self.challenge.to_string(), - signature: None, - }; - response.signature = Some(response.sign(key_pair)); - return WS2PConnectionMessagePayload::ValidAckMessage( - serde_json::to_string(&response).unwrap(), - self.state, - ); - } else { - warn!("The signature of message ACK is invalid !") - } - } - "OK" => { - let mut message = WS2POkMessageV1::parse(m, currency.to_string()) - .expect("Failed to parsing OK Message !"); - trace!("Received OK"); - message.challenge = self.remote_challenge.to_string(); - message.pubkey = self.remote_pubkey.expect("fail to get remote pubkey !"); - if message.verify() { - trace!("OK sig is valid."); - match self.state { - WS2PConnectionState::ConnectMessOk => { - self.state = WS2PConnectionState::OkMessOkWaitingAckMess; - return WS2PConnectionMessagePayload::ValidOk(self.state); - } - WS2PConnectionState::AckMessOk => { - info!( - "WS2P Connection established with the key {}", - self.remote_pubkey.expect("fail to get remote pubkey !") - ); - self.state = WS2PConnectionState::Established; - return WS2PConnectionMessagePayload::ValidOk(self.state); - } - _ => { - warn!("WS2P Error : OK message not expected !"); - return WS2PConnectionMessagePayload::InvalidMessage; - } - } - } else { - warn!("The signature of message OK is invalid !"); - return WS2PConnectionMessagePayload::InvalidMessage; - } - } - &_ => debug!("unknow message"), - }; - } - }; - if let Some(req_id) = m.get("reqId") { - match req_id.as_str() { - Some(req_id) => match m.get("body") { - Some(body) => { - trace!("WS2P : Receive DAL Request from {}.", self.node_full_id()); - match u32::from_str_radix(req_id, 16) { - Ok(req_id) => { - return WS2PConnectionMessagePayload::DalRequest( - ModuleReqId(req_id), - body.clone(), - ); - } - Err(_) => return WS2PConnectionMessagePayload::WrongFormatMessage, - } - } - None => { - warn!("WS2P Error : invalid format : Request must contain a field body !"); - return WS2PConnectionMessagePayload::WrongFormatMessage; - } - }, - None => { - warn!("WS2P Error : invalid format : Request must contain a field body !"); - return WS2PConnectionMessagePayload::WrongFormatMessage; - } - } - } - if let Some(req_id) = m.get("resId") { - match req_id.as_str() { - Some(req_id_str) => match m.get("body") { - Some(body) => match u32::from_str_radix(req_id_str, 16) { - Ok(req_id) => { - return WS2PConnectionMessagePayload::ReqResponse( - ModuleReqId(req_id), - body.clone(), - ) - } - Err(_) => return WS2PConnectionMessagePayload::WrongFormatMessage, - }, - None => match m.get("err") { - Some(err) => warn!("Error in req : {:?}", err), - None => return WS2PConnectionMessagePayload::WrongFormatMessage, - }, - }, - None => return WS2PConnectionMessagePayload::WrongFormatMessage, - } - } - if let Some(body) = m.get("body") { - match body.get("name") { - Some(s) => if s.is_string() { - match s.as_str().unwrap() { - "BLOCK" => match body.get("block") { - Some(block) => { - if let Some(network_block) = parse_json_block(&block) { - return WS2PConnectionMessagePayload::Document( - NetworkDocument::Block(network_block), - ); - } else { - info!("WS2PSignal: receive invalid block (wrong format)."); - }; - } - None => return WS2PConnectionMessagePayload::WrongFormatMessage, - }, - "HEAD" => match body.get("heads") { - Some(heads) => match heads.as_array() { - Some(heads_array) => { - return WS2PConnectionMessagePayload::Heads(heads_array.clone()) - } - None => return WS2PConnectionMessagePayload::WrongFormatMessage, - }, - None => return WS2PConnectionMessagePayload::WrongFormatMessage, - }, - "PEER" => return self.parse_and_check_peer_message(body), - "CERTIFICATION" => { - trace!("WS2P : Receive CERTIFICATION from {}.", self.node_full_id()); - /*return WS2PConnectionMessagePayload::Document( - NetworkDocument::Certification(_) - );*/ - } - _ => { - /*trace!( - "WS2P : Receive Unknow Message from {}.", - self.node_full_id() - );*/ - return WS2PConnectionMessagePayload::UnknowMessage; - } - }; - }, - None => { - warn!("WS2P Error : invalid format : Body must contain a field name !"); - return WS2PConnectionMessagePayload::WrongFormatMessage; - } - } - }; - WS2PConnectionMessagePayload::UnknowMessage - } - - pub fn parse_and_check_peer_message( - &mut self, - body: &serde_json::Value, - ) -> WS2PConnectionMessagePayload { - match body.get("peer") { - Some(peer) => match peer.get("pubkey") { - Some(raw_pubkey) => match ed25519::PublicKey::from_base58( - raw_pubkey.as_str().unwrap_or(""), - ) { - Ok(pubkey) => { - let mut ws2p_endpoints: Vec<NetworkEndpoint> = Vec::new(); - match peer.get("endpoints") { - Some(endpoints) => match endpoints.as_array() { - Some(array_endpoints) => { - for endpoint in array_endpoints { - if let Some(ep) = NetworkEndpoint::parse_from_raw( - endpoint.as_str().unwrap_or(""), - PubKey::Ed25519(pubkey), - 0, - 0, - ) { - if ep.api() == NetworkEndpointApi(String::from("WS2P")) - { - ws2p_endpoints.push(ep); - } - } - } - WS2PConnectionMessagePayload::PeerCard( - body.clone(), - ws2p_endpoints, - ) - } - None => WS2PConnectionMessagePayload::WrongFormatMessage, - }, - None => WS2PConnectionMessagePayload::WrongFormatMessage, - } - } - Err(_) => WS2PConnectionMessagePayload::WrongFormatMessage, - }, - None => WS2PConnectionMessagePayload::WrongFormatMessage, - }, - None => WS2PConnectionMessagePayload::WrongFormatMessage, - } - } -} diff --git a/ws2p/ws2p_db.rs b/ws2p/ws2p_db.rs deleted file mode 100644 index 5ffad9a7..00000000 --- a/ws2p/ws2p_db.rs +++ /dev/null @@ -1,137 +0,0 @@ -extern crate duniter_crypto; -extern crate duniter_documents; -extern crate duniter_message; -extern crate duniter_module; -extern crate duniter_network; -extern crate serde_json; -extern crate sqlite; -extern crate websocket; - -use duniter_crypto::keys::*; -use duniter_network::network_endpoint::{NetworkEndpoint, NetworkEndpointApi}; - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum EndpointApi { - WS2P, - //WS2PS, - //WS2PTOR, - //DASA, - //BMA, - //BMAS, -} - -impl From<u32> for EndpointApi { - fn from(integer: u32) -> Self { - match integer { - _ => EndpointApi::WS2P, - } - } -} - -pub fn string_to_api(api: &str) -> Option<EndpointApi> { - match api { - "WS2P" => Some(EndpointApi::WS2P), - //"WS2PS" => Some(EndpointApi::WS2PS), - //"WS2PTOR" => Some(EndpointApi::WS2PTOR), - //"DASA" => Some(EndpointApi::DASA), - //"BASIC_MERKLED_API" => Some(EndpointApi::BMA), - //"BMAS" => Some(EndpointApi::BMAS), - &_ => None, - } -} - -pub fn api_to_integer(api: &NetworkEndpointApi) -> i64 { - match api.0.as_str() { - "WS2P" => 1, - //EndpointApi::WS2PS => 2, - //EndpointApi::WS2PTOR => 3, - //EndpointApi::DASA => 4, - //EndpointApi::BMA => 5, - //EndpointApi::BMAS => 6, - _ => 0, - } -} - -pub fn get_endpoints_for_api( - db: &sqlite::Connection, - api: &NetworkEndpointApi, -) -> Vec<NetworkEndpoint> { - let mut cursor:sqlite::Cursor = db - .prepare("SELECT hash_full_id, status, node_id, pubkey, api, version, endpoint, last_check FROM endpoints WHERE api=? ORDER BY status DESC;") - .expect("get_endpoints_for_api() : Error in SQL request !") - .cursor(); - - cursor - .bind(&[sqlite::Value::Integer(api_to_integer(&api))]) - .expect("get_endpoints_for_api() : Error in cursor binding !"); - let mut endpoints = Vec::new(); - while let Some(row) = cursor - .next() - .expect("get_endpoints_for_api() : Error in cursor.next()") - { - let raw_ep = row[6].as_string().unwrap().to_string(); - let ep_issuer = - PubKey::Ed25519(ed25519::PublicKey::from_base58(row[3].as_string().unwrap()).unwrap()); - let mut ep = match NetworkEndpoint::parse_from_raw( - &raw_ep, - ep_issuer, - row[1].as_integer().unwrap() as u32, - row[7].as_integer().unwrap() as u64, - ) { - Some(ep) => ep, - None => panic!(format!("Fail to parse endpoint : {}", raw_ep)), - }; - ep.set_status(row[1].as_integer().unwrap() as u32); - ep.set_last_check(row[7].as_integer().unwrap() as u64); - - endpoints.push(ep); - } - endpoints -} - -pub fn write_endpoint( - db: &sqlite::Connection, - endpoint: &NetworkEndpoint, - new_status: u32, - new_last_check: u64, -) { - let hash_full_id = endpoint - .node_full_id() - .expect("Fail to write endpoint : node_full_id() return None !") - .sha256(); - // Check if endpoint it's already written - let mut cursor: sqlite::Cursor = db - .prepare("SELECT status FROM endpoints WHERE hash_full_id=? ORDER BY status DESC;") - .expect("write_endpoint() : Error in SQL request !") - .cursor(); - cursor - .bind(&[sqlite::Value::String(hash_full_id.to_string())]) - .expect("write_endpoint() : Error in cursor binding !"); - - // If endpoint it's already written, update status - if let Some(row) = cursor - .next() - .expect("write_endpoint() : Error in cursor.next()") - { - if row[0].as_integer().expect("fail to read ep status !") as u32 != endpoint.status() { - db.execute(format!( - "UPDATE endpoints SET status={} WHERE hash_full_id='{}'", - endpoint.status(), - hash_full_id - )).expect("Fail to parse SQL request update endpoint status !"); - } - } else if let NetworkEndpoint::V1(ref ep_v1) = *endpoint { - db - .execute( - format!( - "INSERT INTO endpoints (hash_full_id, status, node_id, pubkey, api, version, endpoint, last_check) VALUES ('{}', {}, {}, '{}', {}, {}, '{}', {});", - ep_v1.hash_full_id.expect("ep_v1.hash_full_id = None"), new_status, ep_v1.node_id.expect("ep_v1.node_id = None").0, - ep_v1.issuer.to_string(), api_to_integer(&ep_v1.api), - ep_v1.version, ep_v1.raw_endpoint, new_last_check - ) - ) - .expect("Fail to parse SQL request INSERT endpoint !"); - } else { - panic!("write_endpoint() : Endpoint version is not supported !") - } -} diff --git a/ws2p/ws2p_requests.rs b/ws2p/ws2p_requests.rs deleted file mode 100644 index 722b0154..00000000 --- a/ws2p/ws2p_requests.rs +++ /dev/null @@ -1,44 +0,0 @@ -extern crate duniter_crypto; -extern crate duniter_network; -extern crate serde; -extern crate serde_json; - -use duniter_network::NetworkRequest; - -pub fn network_request_to_json(request: &NetworkRequest) -> serde_json::Value { - let (request_id, request_type, request_params) = match *request { - NetworkRequest::GetCurrent(ref req_full_id, _receiver) => { - (req_full_id.1, "CURRENT", json!({})) - } - NetworkRequest::GetBlocks(ref req_full_id, _receiver, count, from_mumber) => ( - req_full_id.1, - "BLOCKS_CHUNK", - json!({ - "count": count, - "fromNumber": from_mumber - }), - ), - NetworkRequest::GetRequirementsPending(ref req_full_id, _receiver, min_cert) => ( - req_full_id.1, - "WOT_REQUIREMENTS_OF_PENDING", - json!({ "minCert": min_cert }), - ), - NetworkRequest::GetConsensus(_) => { - panic!("GetConsensus() request must be not convert to json !"); - } - NetworkRequest::GetHeadsCache(_) => { - panic!("GetHeadsCache() request must be not convert to json !"); - } - NetworkRequest::GetEndpoints(_) => { - panic!("GetEndpoints() request must be not convert to json !"); - } - }; - - json!({ - "reqId": request_id, - "body" : { - "name": request_type, - "params": request_params - } - }) -} -- GitLab