diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..9f026fc --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1317 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aead" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aead" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "922b33332f54fc0ad13fa3e514601e8d30fb54e1f3eadc36643f6526db645621" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher 0.2.5", +] + +[[package]] +name = "aes-gcm" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" +dependencies = [ + "aead 0.3.2", + "aes", + "cipher 0.2.5", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "alfis" +version = "0.6.0" +dependencies = [ + "base64", + "bincode", + "blakeout", + "byteorder", + "chacha20poly1305", + "chrono", + "derive_more", + "digest", + "ecies-ed25519", + "ed25519-dalek", + "getopts", + "lazy_static", + "log", + "mio", + "num-bigint", + "num-traits", + "num_cpus", + "open", + "rand 0.7.3", + "rand 0.8.3", + "serde", + "serde_bytes", + "serde_cbor", + "serde_derive", + "serde_json", + "sha2", + "signature", + "simplelog", + "sqlite", + "thread-priority", + "tinyfiledialogs", + "toml", + "uuid", + "web-view", + "winapi", + "winres", + "x25519-dalek", +] + +[[package]] +name = "atk-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f530e4af131d94cc4fa15c5c9d0348f0ef28bac64ba660b6b2a1cf2605dedfce" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "blake2" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a5720225ef5daecf08657f23791354e1685a8c91a4c60c7f3d3b2892f978f4" +dependencies = [ + "crypto-mac 0.8.0", + "digest", + "opaque-debug", +] + +[[package]] +name = "blakeout" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81efe7c4220f454dd7fb0eeea7f44f0eb7785dae55115c8fad02b52ef578ac37" +dependencies = [ + "blake2", + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "boxfnonce" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cairo-sys-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ed2639b9ad5f1d6efa76de95558e11339e7318426d84ac4890b86c03e828ca7" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "cc" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee7ad89dc1128635074c268ee661f90c3f7e83d9fd12910608c36b47d6c3412" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1580317203210c517b6d44794abfbe600698276db18127e37ad3e69bf5e848e5" +dependencies = [ + "aead 0.4.1", + "chacha20", + "cipher 0.3.0", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "serde", + "time", + "winapi", +] + +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cpufeatures" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8" +dependencies = [ + "libc", +] + +[[package]] +name = "cpuid-bool" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" +dependencies = [ + "cipher 0.2.5", +] + +[[package]] +name = "curve25519-dalek" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "639891fde0dbea823fc3d798a0fdf9d2f9440a42d64a78ab3488b0ca025117b3" +dependencies = [ + "byteorder", + "digest", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "derive_more" +version = "0.99.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "ecies-ed25519" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a882353828f086290bedd0b598e18863a4d2135f8e632c4325ed89a4e5535db" +dependencies = [ + "aes-gcm", + "curve25519-dalek", + "digest", + "hex", + "hkdf", + "rand 0.7.3", + "sha2", + "thiserror", + "zeroize", +] + +[[package]] +name = "ed25519" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c66a534cbb46ab4ea03477eae19d5c22c01da8258030280b7bd9d8433fb6ef" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "serde", + "sha2", + "zeroize", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bfe468a7f43e97b8d193a762b6c5cf67a7d36cacbc0b9291dbcae24bfea1e8f" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a9653cfc500fd268015b1ac055ddbc3df7a5c9ea3f4ccef147b3957bd140d69" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "gio-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e24fb752f8f5d2cf6bbc2c606fd2bc989c81c5e2fe321ab974d54f8b6344eac" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "gobject-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "952133b60c318a62bf82ee75b93acc7e84028a093e06b9e27981c2b6fe68218c" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89acda6f084863307d948ba64a4b1ef674e8527dddab147ee4cdcc194c880457" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "half" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" + +[[package]] +name = "heck" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac 0.10.0", + "digest", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + +[[package]] +name = "javascriptcore-rs-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f46ada8a08dcd75a10afae872fbfb51275df4a8ae0d46b8cc7c708f08dd2998" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "mio" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "open" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1711eb4b31ce4ad35b0f316d8dfba4fe5c7ad601c448446d84aae7a896627b20" +dependencies = [ + "which", + "winapi", +] + +[[package]] +name = "pango-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d2650c8b62d116c020abd0cea26a4ed96526afda89b1c4ea567131fdefc890" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "poly1305" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe800695325da85083cd23b56826fccb2e2dc29b218e7811a6f33bc93f414be" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" +dependencies = [ + "cpuid-bool", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "proc-macro2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha 0.3.0", + "rand_core 0.6.2", + "rand_hc 0.3.0", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.2", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom 0.2.2", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core 0.6.2", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "serde" +version = "1.0.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_cbor" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "signature" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68" + +[[package]] +name = "simplelog" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59d0fe306a0ced1c88a58042dc22fc2ddd000982c26d75f6aa09a394547c41e0" +dependencies = [ + "chrono", + "log", + "termcolor", +] + +[[package]] +name = "soup-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7adf08565630bbb71f955f11f8a68464817ded2703a3549747c235b58a13e" +dependencies = [ + "bitflags", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "sqlite" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1a534c07ec276fbbe0e55a1c00814d8563da3a2f4d9d9d4c802bd1278db6a" +dependencies = [ + "libc", + "sqlite3-sys", +] + +[[package]] +name = "sqlite3-src" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a260b07ce75a0644c6f5891f34f46db9869e731838e95293469ab17999abcfa3" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "sqlite3-sys" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04d2f028faeb14352df7934b4771806f60d61ce61be1928ec92396d7492e2e54" +dependencies = [ + "libc", + "sqlite3-src", +] + +[[package]] +name = "strum" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" + +[[package]] +name = "strum_macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "subtle" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" + +[[package]] +name = "syn" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" +dependencies = [ + "heck", + "pkg-config", + "strum", + "strum_macros", + "thiserror", + "toml", + "version-compare", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread-priority" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff8073d6382f78367078270c65b5e96cd7f6afc49c42562188e02fea28bfd1" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "tinyfiledialogs" +version = "3.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c45fb26c3f37d9a8b556e51f6d7f13f685af766017030af56e9247e638aa6194" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "typenum" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" + +[[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "universal-hash" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "urlencoding" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.2", + "serde", +] + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "web-view" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee1da6aa5f232e7a4f17ae4549772d2e35d0f4ade03e7527b25c4c0b00abafea" +dependencies = [ + "boxfnonce", + "tinyfiledialogs", + "urlencoding", + "webview-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389e5138c85a0d111b9bda05b59efa8562315e1d657d72451410e12c858f0619" +dependencies = [ + "atk-sys", + "bitflags", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pango-sys", + "pkg-config", + "soup-sys", +] + +[[package]] +name = "webview-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0001f025c1425ffe36270a81cb091eade87dd8d29ac773735ae47e1a8c8066c9" +dependencies = [ + "cc", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "webkit2gtk-sys", +] + +[[package]] +name = "which" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe" +dependencies = [ + "either", + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winres" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4fb510bbfe5b8992ff15f77a2e6fe6cf062878f0eda00c0f44963a807ca5dc" +dependencies = [ + "toml", +] + +[[package]] +name = "x25519-dalek" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" +dependencies = [ + "curve25519-dalek", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/Cargo.toml b/Cargo.toml index 3cb27c5..2109bc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alfis" -version = "0.5.9" +version = "0.6.0" authors = ["Revertron "] edition = "2018" build = "build.rs" @@ -18,7 +18,9 @@ toml = "0.5.8" digest = "0.9.0" sha2 = "0.9.5" ed25519-dalek = "1.0.1" +x25519-dalek = "1.1.1" ecies-ed25519 = "0.5.1" +chacha20poly1305 = "0.8.0" signature = "1.3.0" blakeout = "0.3.0" num_cpus = "1.13.0" @@ -26,6 +28,7 @@ byteorder = "1.4.3" serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.64" bincode = "1.3.3" +serde_cbor = "0.11.1" base64 = "0.13.0" num-bigint = "0.4.0" num-traits = "0.2.14" diff --git a/src/blockchain/block.rs b/src/blockchain/block.rs index 8f64901..7decddb 100644 --- a/src/blockchain/block.rs +++ b/src/blockchain/block.rs @@ -61,13 +61,23 @@ impl Block { } } + pub fn from_bytes(data: &[u8]) -> serde_cbor::Result { + serde_cbor::from_slice(data) + } + pub fn is_genesis(&self) -> bool { self.index == 1 && matches!(Transaction::get_type(&self.transaction), TransactionType::Origin) && self.prev_block_hash == Bytes::default() } + /// Serializes block to CBOR for network pub fn as_bytes(&self) -> Vec { + serde_cbor::to_vec(&self).unwrap() + } + + /// Serializes block to bincode format for hashing. + pub fn as_bytes_compact(&self) -> Vec { bincode::serialize(&self).unwrap() } diff --git a/src/blockchain/chain.rs b/src/blockchain/chain.rs index 07a20f1..10908f5 100644 --- a/src/blockchain/chain.rs +++ b/src/blockchain/chain.rs @@ -1010,8 +1010,10 @@ impl SignersCache { pub mod tests { use log::LevelFilter; use simplelog::{ColorChoice, ConfigBuilder, TerminalMode, TermLogger}; + #[allow(unused_imports)] + use log::{debug, error, info, trace, warn}; - use crate::{Chain, Settings}; + use crate::{Chain, Settings, Block}; fn init_logger() { let config = ConfigBuilder::new() @@ -1035,4 +1037,28 @@ pub mod tests { chain.check_chain(u64::MAX); assert_eq!(chain.get_height(), 149); } + + #[test] + pub fn check_serde() { + let settings = Settings::default(); + let chain = Chain::new(&settings, "./tests/blockchain.db"); + + // Check the first block, its transaction doesn't have identity + let block = chain.get_block(1).unwrap(); + let buf = serde_cbor::to_vec(&block).unwrap(); + let block2: Block = serde_cbor::from_slice(&buf[..]).unwrap(); + assert_eq!(block, block2); + + // Check second block, it is common "full" block with domain + let block = chain.get_block(2).unwrap(); + let buf = serde_cbor::to_vec(&block).unwrap(); + let block2: Block = serde_cbor::from_slice(&buf[..]).unwrap(); + assert_eq!(block, block2); + + // Check block 36, it is an "empty" block, used to sign full blocks + let block = chain.get_block(36).unwrap(); + let buf = serde_cbor::to_vec(&block).unwrap(); + let block2: Block = serde_cbor::from_slice(&buf[..]).unwrap(); + assert_eq!(block, block2); + } } \ No newline at end of file diff --git a/src/blockchain/hash_utils.rs b/src/blockchain/hash_utils.rs index b731e62..e8d9251 100644 --- a/src/blockchain/hash_utils.rs +++ b/src/blockchain/hash_utils.rs @@ -9,7 +9,7 @@ pub fn check_block_hash(block: &Block) -> bool { let mut copy: Block = block.clone(); copy.hash = Bytes::default(); copy.signature = Bytes::default(); - blakeout_data(©.as_bytes()) == block.hash + blakeout_data(©.as_bytes_compact()) == block.hash } /// Hashes data by given hasher @@ -23,7 +23,7 @@ pub fn blakeout_data(data: &[u8]) -> Bytes { pub fn check_block_signature(block: &Block) -> bool { let mut copy = block.clone(); copy.signature = Bytes::default(); - Keystore::check(©.as_bytes(), ©.pub_key, &block.signature) + Keystore::check(©.as_bytes_compact(), ©.pub_key, &block.signature) } /// Hashes some identity (domain in case of DNS). If you give it a public key, it will hash with it as well. diff --git a/src/blockchain/transaction.rs b/src/blockchain/transaction.rs index 1897448..8712d32 100644 --- a/src/blockchain/transaction.rs +++ b/src/blockchain/transaction.rs @@ -49,11 +49,6 @@ impl Transaction { } } - pub fn get_bytes(&self) -> Vec { - // Let it panic if something is not okay - serde_json::to_vec(&self).unwrap() - } - pub fn to_string(&self) -> String { // Let it panic if something is not okay serde_json::to_string(&self).unwrap() diff --git a/src/commons/mod.rs b/src/commons/mod.rs index ec40f7a..f944411 100644 --- a/src/commons/mod.rs +++ b/src/commons/mod.rs @@ -1,7 +1,6 @@ use std::net::IpAddr; use std::num; -use mio::Token; use rand::Rng; #[cfg(not(target_os = "macos"))] use thread_priority::*; @@ -116,13 +115,6 @@ pub fn is_yggdrasil(addr: &IpAddr) -> bool { false } -/// Gets new token from old token, mutating the last -pub fn next(current: &mut Token) -> Token { - let next = current.0; - current.0 += 1; - Token(next) -} - /// Checks if this record has IP from Yggdrasil network /// https://yggdrasil-network.github.io pub fn is_yggdrasil_record(record: &DnsRecord) -> bool { diff --git a/src/crypto/chacha.rs b/src/crypto/chacha.rs new file mode 100644 index 0000000..0cca1c4 --- /dev/null +++ b/src/crypto/chacha.rs @@ -0,0 +1,66 @@ +use chacha20poly1305::{ChaCha20Poly1305, Key, Nonce}; +use chacha20poly1305::aead::{Aead, NewAead}; +use std::fmt::{Debug, Formatter}; +use std::fmt; + +pub const ZERO_NONCE: [u8; 12] = [0u8; 12]; +const FAILURE: &str = "encryption failure!"; + +/// A small wrap-up to use Chacha20 encryption for domain names. +#[derive(Clone)] +pub struct Chacha { + cipher: ChaCha20Poly1305, + nonce: [u8; 12] +} + +impl Chacha { + pub fn new(key: &[u8], nonce: &[u8]) -> Self { + let key = Key::from_slice(key); + let cipher = ChaCha20Poly1305::new(key); + let mut buf = [0u8; 12]; + buf.copy_from_slice(nonce); + Chacha { cipher, nonce: buf } + } + + pub fn encrypt(&self, data: &[u8]) -> Vec { + let nonce = Nonce::from(self.nonce.clone()); + self.cipher.encrypt(&nonce, data.as_ref()).expect(FAILURE) + } + + pub fn decrypt(&self, data: &[u8]) -> Vec { + let nonce = Nonce::from(self.nonce.clone()); + self.cipher.decrypt(&nonce, data.as_ref()).expect(FAILURE) + } + + pub fn get_nonce(&self) -> &[u8; 12] { + &self.nonce + } +} + +impl Debug for Chacha { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + fmt.write_str("ChaCha20Poly1305") + } +} + +#[cfg(test)] +mod tests { + use crate::crypto::Chacha; + use crate::{to_hex}; + + #[test] + pub fn test_chacha() { + let buf = b"178135D209C697625E3EC71DA5C760382E54936F824EE5083908DA66B14ECE18"; + let chacha1 = Chacha::new(b"178135D209C697625E3EC71DA5C76038", &buf[..12]); + let bytes1 = chacha1.encrypt(b"TEST"); + println!("{}", to_hex(&bytes1)); + + let chacha2 = Chacha::new(b"178135D209C697625E3EC71DA5C76038", &buf[..12]); + let bytes2 = chacha2.decrypt(&bytes1); + assert_eq!(String::from_utf8(bytes2).unwrap(), "TEST"); + + let bytes2 = chacha2.encrypt(b"TEST"); + + assert_eq!(bytes1, bytes2); + } +} \ No newline at end of file diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index 25839bb..9ab04b9 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -1,3 +1,6 @@ mod crypto_box; +mod chacha; -pub use crypto_box::CryptoBox; \ No newline at end of file +pub use crypto_box::CryptoBox; +pub use chacha::Chacha; +pub use chacha::ZERO_NONCE; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1dbf756..6098d96 100644 --- a/src/main.rs +++ b/src/main.rs @@ -184,7 +184,11 @@ fn main() { let miner: Arc> = Arc::new(Mutex::new(miner_obj)); let mut network = Network::new(Arc::clone(&context)); - network.start().expect("Error starting network component"); + thread::spawn(move || { + // Give UI some time to appear :) + thread::sleep(Duration::from_millis(1000)); + network.start(); + }); create_genesis_if_needed(&context, &miner); if no_gui { diff --git a/src/miner.rs b/src/miner.rs index 83dbeff..d00559d 100644 --- a/src/miner.rs +++ b/src/miner.rs @@ -280,7 +280,7 @@ impl Miner { Some(mut block) => { let index = block.index; let mut context = context.lock().unwrap(); - block.signature = Bytes::from_bytes(&job.keystore.sign(&block.as_bytes())); + block.signature = Bytes::from_bytes(&job.keystore.sign(&block.as_bytes_compact())); let mut success = false; if context.chain.check_new_block(&block) != BlockQuality::Good { warn!("Error adding mined block!"); @@ -341,7 +341,7 @@ fn find_hash(context: Arc>, mut block: Block, running: Arc= target_diff { block.hash = Bytes::from_bytes(digest.result()); diff --git a/src/p2p/message.rs b/src/p2p/message.rs index 9ec261e..67bf335 100644 --- a/src/p2p/message.rs +++ b/src/p2p/message.rs @@ -7,8 +7,8 @@ use crate::Bytes; #[derive(Debug, Serialize, Deserialize)] pub enum Message { Error, - Hand { #[serde(default = "default_version")] app_version: String, origin: String, version: u32, public: bool, #[serde(default)] rand: String }, - Shake { #[serde(default = "default_version")] app_version: String, origin: String, version: u32, ok: bool, height: u64 }, + Hand { app_version: String, origin: String, version: u32, public: bool, rand_id: String, }, + Shake { app_version: String, origin: String, version: u32, public: bool, rand_id: String, height: u64 }, Ping { height: u64, hash: Bytes }, Pong { height: u64, hash: Bytes }, Twin, @@ -16,24 +16,23 @@ pub enum Message { GetPeers, Peers { peers: Vec }, GetBlock { index: u64 }, - Block { index: u64, block: String }, + Block { index: u64, block: Vec }, } impl Message { pub fn from_bytes(bytes: Vec) -> Result { - let text = String::from_utf8(bytes).unwrap_or(String::from("Error{}")); - match serde_json::from_str(&text) { + match serde_cbor::from_slice(bytes.as_slice()) { Ok(cmd) => Ok(cmd), Err(_) => Err(()) } } - pub fn hand(app_version: &str, origin: &str, version: u32, public: bool, rand: &str) -> Self { - Message::Hand { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand: rand.to_owned() } + pub fn hand(app_version: &str, origin: &str, version: u32, public: bool, rand_id: &str) -> Self { + Message::Hand { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand_id: rand_id.to_owned() } } - pub fn shake(app_version: &str, origin: &str, version: u32, ok: bool, height: u64) -> Self { - Message::Shake { app_version: app_version.to_owned(), origin: origin.to_owned(), version, ok, height } + pub fn shake(app_version: &str, origin: &str, version: u32, public: bool, rand_id: &str, height: u64) -> Self { + Message::Shake { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand_id: rand_id.to_owned(), height } } pub fn ping(height: u64, hash: Bytes) -> Self { @@ -44,24 +43,7 @@ impl Message { Message::Pong { height, hash } } - pub fn block(height: u64, str: String) -> Self { - Message::Block { index: height, block: str } + pub fn block(height: u64, block: Vec) -> Self { + Message::Block { index: height, block } } -} - -fn default_version() -> String { - String::from("0.0.0") -} - -#[cfg(test)] -mod tests { - use crate::p2p::Message; - - #[test] - pub fn test_hand() { - assert!(serde_json::from_str::("\"Error\"").is_ok()); - assert!(serde_json::from_str::("{\"Hand\":{\"origin\":\"\",\"version\":1,\"public\":false,\"rand\":\"123\"}}").is_ok()); - assert!(serde_json::from_str::("{\"Hand\":{\"origin\":\"\",\"version\":1,\"public\":false}}").is_ok()); - } - } \ No newline at end of file diff --git a/src/p2p/network.rs b/src/p2p/network.rs index 7886ab4..a149415 100644 --- a/src/p2p/network.rs +++ b/src/p2p/network.rs @@ -3,7 +3,7 @@ extern crate serde_json; use std::{io, thread}; use std::cmp::max; -use std::io::{Read, Write}; +use std::io::{Read, Write, Error}; use std::net::{IpAddr, Shutdown, SocketAddr, SocketAddrV4}; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicBool, Ordering}; @@ -15,25 +15,38 @@ use log::{debug, error, info, trace, warn}; use mio::{Events, Interest, Poll, Registry, Token}; use mio::event::Event; use mio::net::{TcpListener, TcpStream}; -use rand::random; +use rand::{random, RngCore, Rng}; +use rand_old::prelude::thread_rng; +use x25519_dalek::{StaticSecret, PublicKey}; use crate::{Block, Context, p2p::Message, p2p::Peer, p2p::Peers, p2p::State}; use crate::blockchain::types::BlockQuality; use crate::commons::*; use crate::eventbus::{register, post}; +use crate::crypto::Chacha; const SERVER: Token = Token(0); pub struct Network { - context: Arc> + context: Arc>, + secret_key: StaticSecret, + public_key: PublicKey, + token: Token, + // States of peer connections, and some data to send when sockets become writable + peers: Peers, } impl Network { pub fn new(context: Arc>) -> Self { - Network { context } + // P2P encryption primitives + let mut thread_rng = thread_rng(); + let secret_key = StaticSecret::new(&mut thread_rng); + let public_key = PublicKey::from(&secret_key); + let peers = Peers::new(); + Network { context, secret_key, public_key, token: Token(1), peers } } - pub fn start(&mut self) -> Result<(), String> { + pub fn start(&mut self) { let (listen_addr, peers_addrs, yggdrasil_only) = { let c = self.context.lock().unwrap(); (c.settings.net.listen.clone(), c.settings.net.peers.clone(), c.settings.net.yggdrasil_only) @@ -47,145 +60,564 @@ impl Network { let mut server = TcpListener::bind(addr).expect("Can't bind to address"); debug!("Started node listener on {}", server.local_addr().unwrap()); - let mut events = Events::with_capacity(1024); + let mut events = Events::with_capacity(64); let mut poll = Poll::new().expect("Unable to create poll"); poll.registry().register(&mut server, SERVER, Interest::READABLE).expect("Error registering poll"); - let context = Arc::clone(&self.context); - thread::spawn(move || { - // Give UI some time to appear :) - thread::sleep(Duration::from_millis(2000)); - // Unique token for each incoming connection. - let mut unique_token = Token(SERVER.0 + 1); - // States of peer connections, and some data to send when sockets become writable - let mut peers = Peers::new(); - // Starting peer connections to bootstrap nodes - peers.connect_peers(&peers_addrs, &poll.registry(), &mut unique_token, yggdrasil_only); - let mut ui_timer = Instant::now(); - let mut log_timer = Instant::now(); - let mut bootstrap_timer = Instant::now(); - let mut connect_timer = Instant::now(); - let mut last_events_time = Instant::now(); - loop { - if peers.get_peers_count() == 0 && bootstrap_timer.elapsed().as_secs() > 60 { - warn!("Restarting swarm connections..."); - // Starting peer connections to bootstrap nodes - peers.connect_peers(&peers_addrs, &poll.registry(), &mut unique_token, yggdrasil_only); - bootstrap_timer = Instant::now(); - last_events_time = Instant::now(); - } - // Poll Mio for events, blocking until we get an event. - poll.poll(&mut events, POLL_TIMEOUT).expect("Error polling sockets"); - if !running.load(Ordering::SeqCst) { - break; - } + // Starting peer connections to bootstrap nodes + self.peers.connect_peers(&peers_addrs, &poll.registry(), &mut self.token, yggdrasil_only); - // Process each event. - for event in events.iter() { - //trace!("Event for socket {} is {:?}", event.token().0, &event); - // We can use the token we previously provided to `register` to determine for which socket the event is. - match event.token() { - SERVER => { - //debug!("Event for server socket {} is {:?}", event.token().0, &event); - // If this is an event for the server, it means a connection is ready to be accepted. - let connection = server.accept(); - match connection { - Ok((mut stream, mut address)) => { - // Checking if it is an ipv4-mapped ipv6 if yes convert to ipv4 - if address.is_ipv6() { - if let IpAddr::V6(ipv6) = address.ip() { - if let Some(ipv4) = ipv6.to_ipv4() { - address = SocketAddr::V4(SocketAddrV4::new(ipv4, address.port())) - } + let mut ui_timer = Instant::now(); + let mut log_timer = Instant::now(); + let mut bootstrap_timer = Instant::now(); + let mut connect_timer = Instant::now(); + let mut last_events_time = Instant::now(); + loop { + if self.peers.get_peers_count() == 0 && bootstrap_timer.elapsed().as_secs() > 60 { + warn!("Restarting swarm connections..."); + // Starting peer connections to bootstrap nodes + self.peers.connect_peers(&peers_addrs, &poll.registry(), &mut self.token, yggdrasil_only); + bootstrap_timer = Instant::now(); + last_events_time = Instant::now(); + } + // Poll Mio for events, blocking until we get an event. + poll.poll(&mut events, POLL_TIMEOUT).expect("Error polling sockets"); + if !running.load(Ordering::SeqCst) { + break; + } + + // Process each event. + for event in events.iter() { + //trace!("Event for socket {} is {:?}", event.token().0, &event); + // We can use the token we previously provided to `register` to determine for which socket the event is. + match event.token() { + SERVER => { + //debug!("Event for server socket {} is {:?}", event.token().0, &event); + // If this is an event for the server, it means a connection is ready to be accepted. + let connection = server.accept(); + match connection { + Ok((mut stream, mut address)) => { + // Checking if it is an ipv4-mapped ipv6 if yes convert to ipv4 + if address.is_ipv6() { + if let IpAddr::V6(ipv6) = address.ip() { + if let Some(ipv4) = ipv6.to_ipv4() { + address = SocketAddr::V4(SocketAddrV4::new(ipv4, address.port())) } } - - if peers.is_ignored(&address.ip()) { - debug!("Ignoring connection from banned {:?}", &address.ip()); - continue; - } - - if yggdrasil_only && !is_yggdrasil(&address.ip()) { - debug!("Dropping connection from Internet"); - stream.shutdown(Shutdown::Both).unwrap_or_else(|e|{ warn!("Error in shutdown, {}", e); }); - let _ = poll.registry().reregister(&mut server, SERVER, Interest::READABLE); - continue; - } - - //debug!("Accepted connection from: {} to local IP: {}", address, local_ip); - let token = next(&mut unique_token); - poll.registry().register(&mut stream, token, Interest::READABLE).expect("Error registering poll"); - peers.add_peer(token, Peer::new(address, stream, State::Connected, true)); } - Err(_) => {} - } - match poll.registry().reregister(&mut server, SERVER, Interest::READABLE) { - Ok(_) => {} - Err(e) => { - panic!("Error reregistering server token!\n{}", e); + + if self.peers.is_ignored(&address.ip()) { + debug!("Ignoring connection from banned {:?}", &address.ip()); + continue; } + + if yggdrasil_only && !is_yggdrasil(&address.ip()) { + debug!("Dropping connection from Internet"); + stream.shutdown(Shutdown::Both).unwrap_or_else(|e|{ warn!("Error in shutdown, {}", e); }); + let _ = poll.registry().reregister(&mut server, SERVER, Interest::READABLE); + continue; + } + + //debug!("Accepted connection from: {} to local IP: {}", address, local_ip); + let token = self.next_token(); + poll.registry().register(&mut stream, token, Interest::READABLE).expect("Error registering poll"); + let peer = Peer::new(address, stream, State::Connected, true); + self.peers.add_peer(token, peer); } + Err(_) => {} } - token => { - if !handle_connection_event(Arc::clone(&context), &mut peers, &poll.registry(), &event) { - let _ = peers.close_peer(poll.registry(), &token); - let blocks = context.lock().unwrap().chain.get_height(); - let keys = context.lock().unwrap().chain.get_users_count(); - let domains = context.lock().unwrap().chain.get_domains_count(); - post(crate::event::Event::NetworkStatus { blocks, domains, keys, nodes: peers.get_peers_active_count() }); - } + if let Err(e) = poll.registry().reregister(&mut server, SERVER, Interest::READABLE) { + panic!("Error reregistering server token!\n{}", e); } } - } - if !events.is_empty() { - last_events_time = Instant::now(); - } else if last_events_time.elapsed().as_secs() > MAX_IDLE_SECONDS { - if peers.get_peers_count() > 0 { - warn!("Something is wrong with swarm connections, closing all."); - peers.close_all_peers(poll.registry()); - continue; - } else { - thread::sleep(POLL_TIMEOUT.unwrap()); + token => { + if !self.handle_connection_event(&poll.registry(), &event) { + let _ = self.peers.close_peer(poll.registry(), &token); + let blocks = self.context.lock().unwrap().chain.get_height(); + let keys = self.context.lock().unwrap().chain.get_users_count(); + let domains = self.context.lock().unwrap().chain.get_domains_count(); + post(crate::event::Event::NetworkStatus { blocks, domains, keys, nodes: self.peers.get_peers_active_count() }); + } } } - - if ui_timer.elapsed().as_millis() > UI_REFRESH_DELAY_MS { - // Send pings to idle peers - let (height, hash) = { - let context = context.lock().unwrap(); - let blocks = context.chain.get_height(); - let nodes = peers.get_peers_active_count(); - let banned = peers.get_peers_banned_count(); - - let keys = context.chain.get_users_count(); - let domains = context.chain.get_domains_count(); - post(crate::event::Event::NetworkStatus { blocks, domains, keys, nodes }); - - if log_timer.elapsed().as_secs() > LOG_REFRESH_DELAY_SEC { - info!("Active nodes count: {}, banned count: {}, blocks count: {}", nodes, banned, blocks); - let elapsed = last_events_time.elapsed().as_secs(); - if elapsed >= 10 { - warn!("Last network events time {} seconds ago", elapsed); - } - log_timer = Instant::now(); - } - if nodes < MAX_NODES && connect_timer.elapsed().as_secs() >= 5 { - peers.connect_new_peers(poll.registry(), &mut unique_token, yggdrasil_only); - connect_timer = Instant::now(); - } - (blocks, context.chain.get_last_hash()) - }; - peers.update(poll.registry(), height, hash); - ui_timer = Instant::now(); - } } - if !running.load(Ordering::SeqCst) { - info!("Network loop finished"); + if !events.is_empty() { + last_events_time = Instant::now(); + } else if last_events_time.elapsed().as_secs() > MAX_IDLE_SECONDS { + if self.peers.get_peers_count() > 0 { + warn!("Something is wrong with swarm connections, closing all."); + self.peers.close_all_peers(poll.registry()); + continue; + } else { + thread::sleep(POLL_TIMEOUT.unwrap()); + } + } + + if ui_timer.elapsed().as_millis() > UI_REFRESH_DELAY_MS { + // Send pings to idle peers + let (height, hash) = { + let context = self.context.lock().unwrap(); + let blocks = context.chain.get_height(); + let nodes = self.peers.get_peers_active_count(); + let banned = self.peers.get_peers_banned_count(); + + let keys = context.chain.get_users_count(); + let domains = context.chain.get_domains_count(); + post(crate::event::Event::NetworkStatus { blocks, domains, keys, nodes }); + + if log_timer.elapsed().as_secs() > LOG_REFRESH_DELAY_SEC { + info!("Active nodes count: {}, banned count: {}, blocks count: {}", nodes, banned, blocks); + let elapsed = last_events_time.elapsed().as_secs(); + if elapsed >= 10 { + warn!("Last network events time {} seconds ago", elapsed); + } + log_timer = Instant::now(); + } + if nodes < MAX_NODES && connect_timer.elapsed().as_secs() >= 5 { + self.peers.connect_new_peers(poll.registry(), &mut self.token, yggdrasil_only); + connect_timer = Instant::now(); + } + (blocks, context.chain.get_last_hash()) + }; + self.peers.update(poll.registry(), height, hash); + ui_timer = Instant::now(); + } + } + if !running.load(Ordering::SeqCst) { + info!("Network loop finished"); + } else { + panic!("Network loop has broken prematurely!"); + } + } + + fn handle_connection_event(&mut self, registry: &Registry, event: &Event) -> bool { + if event.is_error() || (event.is_read_closed() && event.is_write_closed()) { + return false; + } + + if event.is_readable() { + let data = { + let token = event.token(); + match self.peers.get_mut_peer(&token) { + None => { + error!("Error getting peer for connection {}", token.0); + return false; + } + Some(peer) => { + if event.is_read_closed() { + debug!("Node from {} disconnected", peer.get_addr().ip()); + return false; + } + match peer.get_state().clone() { + State::Connected => { + let mut stream = peer.get_stream(); + return match read_client_handshake(&mut stream) { + Ok(key) => { + let mut buf = [0u8; 32]; + buf.copy_from_slice(key.as_slice()); + let public_key: PublicKey = PublicKey::from(buf); + let shared = self.secret_key.diffie_hellman(&public_key); + let mut nonce = [0u8; 12]; + let mut rng = rand::thread_rng(); + rng.fill(&mut nonce); + let chacha = Chacha::new(shared.as_bytes(), &nonce); + registry.reregister(stream, event.token(), Interest::WRITABLE).unwrap(); + std::mem::drop(stream); + peer.set_cipher(chacha); + peer.set_state(State::ServerHandshake); + info!("Client hello read successfully"); + true + } + Err(e) => { + warn!("Error reading client handshake. {}", e); + false + } + } + } + State::ServerHandshake => { + let mut stream = peer.get_stream(); + return match read_server_handshake(&mut stream) { + Ok(data) => { + if data.len() != 32 + 12 { + warn!("Server handshake of {} bytes instead of {}", data.len(), 32 + 12); + return false; + } + let mut buf = [0u8; 32]; + buf.copy_from_slice(&data.as_slice()[0..32]); + let public_key: PublicKey = PublicKey::from(buf); + let mut nonce = [0u8; 12]; + nonce.copy_from_slice(&data.as_slice()[32..]); + let shared = self.secret_key.diffie_hellman(&public_key); + let chacha = Chacha::new(shared.as_bytes(), &nonce); + registry.reregister(stream, event.token(), Interest::WRITABLE).unwrap(); + std::mem::drop(stream); + peer.set_cipher(chacha); + peer.set_state(State::HandshakeFinished); + info!("Server hello read successfully"); + true + } + Err(e) => { + warn!("Error reading server handshake. {}", e); + false + } + } + } + _ => { + let mut stream = peer.get_stream(); + read_message(&mut stream) + } + } + } + } + }; + + if data.is_ok() { + let data = { + match self.peers.get_peer(&event.token()) { + Some(peer) => { + let data = data.unwrap(); + //info!("Decoding message {:?}", to_hex(data.as_slice())); + match decode_message(&data, peer.get_cipher()) { + Ok(data) => { + data + } + Err(_) => { + vec![] + } + } + } + None => { + vec![] + } + } + }; + match Message::from_bytes(data) { + Ok(message) => { + let m = format!("{:?}", &message); + let new_state = self.handle_message(message, &event.token()); + let peer = self.peers.get_mut_peer(&event.token()).unwrap(); + debug!("Got message from {}: {:?}", &peer.get_addr(), &m); + let stream = peer.get_stream(); + match new_state { + State::Message { data } => { + registry.reregister(stream, event.token(), Interest::WRITABLE).unwrap(); + peer.set_state(State::Message { data }); + } + State::Connecting => {} + State::Connected => {} + State::ServerHandshake => {} + State::HandshakeFinished => {} + State::Idle { .. } => { + peer.set_state(State::idle()); + } + State::Error => {} + State::Banned => { + self.peers.ignore_peer(registry, &event.token()); + } + State::Offline { .. } => { + peer.set_state(State::offline()); + } + State::Loop => { + peer.set_state(State::Loop); + self.peers.ignore_peer(registry, &event.token()); + } + State::SendLoop => { + registry.reregister(stream, event.token(), Interest::WRITABLE).unwrap(); + peer.set_state(State::SendLoop); + } + State::Twin => { + peer.set_state(State::Twin); + // TODO set something in [Peers], maybe ignore this IP? + return false; + } + } + } + Err(_) => { + let peer = self.peers.get_peer(&event.token()).unwrap(); + warn!("Error deserializing message from {}", &peer.get_addr()); + return false; + } + } } else { - panic!("Network loop has broken prematurely!"); + return false; } - }); - Ok(()) + } + + if event.is_writable() { + let my_id = self.peers.get_my_id().to_owned(); + match self.peers.get_mut_peer(&event.token()) { + None => {} + Some(peer) => { + match peer.get_state().clone() { + State::Connecting => { + if send_client_handshake(&mut peer.get_stream(), self.public_key.as_bytes()).is_err() { + return false; + } + peer.set_state(State::ServerHandshake); + } + State::ServerHandshake => { + if send_server_handshake(peer, self.public_key.as_bytes()).is_err() { + return false; + } + peer.set_state(State::HandshakeFinished); + info!("Server handshake sent"); + } + State::HandshakeFinished => { + //debug!("Connected to peer {}, sending hello...", &peer.get_addr()); + let data: Vec = { + let c = self.context.lock().unwrap(); + let message = Message::hand(&c.app_version, &c.settings.origin, CHAIN_VERSION, c.settings.net.public, &my_id); + info!("Sending: {:?}", &message); + encode_message(&message, peer.get_cipher()).unwrap() + }; + send_message(peer.get_stream(), &data).unwrap_or_else(|e| warn!("Error sending hello {}", e)); + //debug!("Sent hello to {}", &peer.get_addr()); + } + State::Connected => {} + State::Message { data } => { + //debug!("Sending data to {}: {}", &peer.get_addr(), &String::from_utf8(data.clone()).unwrap()); + let data = encode_bytes(&data, peer.get_cipher()); + send_message(peer.get_stream(), &data).unwrap_or_else(|e| warn!("Error sending message {}", e)); + } + State::Idle { from } => { + debug!("Odd version of pings :)"); + if from.elapsed().as_secs() >= 30 { + let data: Vec = { + let c = self.context.lock().unwrap(); + let message = Message::ping(c.chain.get_height(), c.chain.get_last_hash()); + encode_message(&message, peer.get_cipher()).unwrap() + }; + send_message(peer.get_stream(), &data).unwrap_or_else(|e| warn!("Error sending ping {}", e)); + } + } + State::Error => {} + State::Banned => {} + State::Offline { .. } => {} + State::Loop => {} + State::SendLoop => { + let data = encode_message(&Message::Loop, peer.get_cipher()).unwrap(); + send_message(peer.get_stream(), &data).unwrap_or_else(|e| warn!("Error sending loop {}", e)); + } + State::Twin => { + let data = encode_message(&Message::Twin, peer.get_cipher()).unwrap(); + send_message(peer.get_stream(), &data).unwrap_or_else(|e| warn!("Error sending loop {}", e)); + } + } + registry.reregister(peer.get_stream(), event.token(), Interest::READABLE).unwrap(); + } + } + } + + true + } + + fn handle_message(&mut self, message: Message, token: &Token) -> State { + let (my_height, my_hash, my_origin, my_version, me_public) = { + let context = self.context.lock().unwrap(); + // TODO cache it somewhere + (context.chain.get_height(), context.chain.get_last_hash(), &context.settings.origin.clone(), CHAIN_VERSION, context.settings.net.public) + }; + let my_id = self.peers.get_my_id().to_owned(); + let answer = match message { + Message::Hand { app_version, origin, version, public, rand_id } => { + if self.peers.is_our_own_connect(&rand_id) { + warn!("Detected loop connect"); + State::SendLoop + } else { + if origin.eq(my_origin) && version == my_version { + let peer = self.peers.get_mut_peer(token).unwrap(); + peer.set_public(public); + peer.set_active(true); + debug!("Incoming v{} on {}", &app_version, peer.get_addr().ip()); + let app_version = self.context.lock().unwrap().app_version.clone(); + State::message(Message::shake(&app_version, &origin, version, me_public, &my_id, my_height)) + } else { + warn!("Handshake from unsupported chain or version"); + State::Banned + } + } + } + Message::Shake { app_version, origin, version, public, rand_id, height } => { + if origin.ne(my_origin) || version != my_version { + return State::Banned; + } + if self.peers.is_tween_connect(&rand_id) { + return State::Twin; + } + let nodes = self.peers.get_peers_active_count(); + let peer = self.peers.get_mut_peer(token).unwrap(); + // TODO check rand_id whether we have this peers connection already + debug!("Outgoing v{} on {}", &app_version, peer.get_addr().ip()); + peer.set_height(height); + peer.set_active(true); + peer.set_public(public); + peer.reset_reconnects(); + let mut context = self.context.lock().unwrap(); + if peer.is_higher(my_height) { + context.chain.update_max_height(height); + let event = crate::event::Event::Syncing { have: my_height, height: max(height, my_height) }; + post(event); + } + if nodes < MAX_NODES && random::() { + debug!("Requesting more peers from {}", peer.get_addr().ip()); + State::message(Message::GetPeers) + } else { + State::idle() + } + } + Message::Error => { State::Error } + Message::Ping { height, hash } => { + let peer = self.peers.get_mut_peer(token).unwrap(); + peer.set_height(height); + peer.set_active(true); + if peer.is_higher(my_height) { + let mut context = self.context.lock().unwrap(); + context.chain.update_max_height(height); + info!("Peer is higher, requesting block {} from {}", height, peer.get_addr().ip()); + State::message(Message::GetBlock { index: my_height + 1 }) + } else if my_height == height && hash.ne(&my_hash) { + info!("Hashes are different, requesting block {} from {}", my_height, peer.get_addr().ip()); + info!("My hash: {:?}, their hash: {:?}", &my_hash, &hash); + State::message(Message::GetBlock { index: my_height }) + } else { + State::message(Message::pong(my_height, my_hash)) + } + } + Message::Pong { height, hash } => { + let active_count = self.peers.get_peers_active_count(); + let peer = self.peers.get_mut_peer(token).unwrap(); + peer.set_height(height); + peer.set_active(true); + if peer.is_higher(my_height) { + let mut context = self.context.lock().unwrap(); + context.chain.update_max_height(height); + info!("Peer is higher, requesting block {} from {}", height, peer.get_addr().ip()); + State::message(Message::GetBlock { index: my_height + 1 }) + } else if my_height == height && hash.ne(&my_hash) { + info!("Hashes are different, requesting block {} from {}", my_height, peer.get_addr().ip()); + info!("My hash: {:?}, their hash: {:?}", &my_hash, &hash); + State::message(Message::GetBlock { index: my_height }) + } else { + if active_count < MAX_NODES && random::() < 50 { + debug!("Requesting more peers from {}", peer.get_addr().ip()); + State::message(Message::GetPeers) + } else { + State::idle() + } + } + } + Message::GetPeers => { + let addr = { + let peer = self.peers.get_mut_peer(token).unwrap(); + peer.set_active(true); + peer.get_addr().clone() + }; + State::message(Message::Peers { peers: self.peers.get_peers_for_exchange(&addr) }) + } + Message::Peers { peers: new_peers } => { + let peer = self.peers.get_mut_peer(token).unwrap(); + peer.set_active(true); + self.peers.add_peers_from_exchange(new_peers); + State::idle() + } + Message::GetBlock { index } => { + let peer = self.peers.get_mut_peer(token).unwrap(); + peer.set_active(true); + let context = self.context.lock().unwrap(); + match context.chain.get_block(index) { + Some(block) => State::message(Message::block(block.index, block.as_bytes())), + None => State::Error + } + } + Message::Block { index, block } => { + let peer = self.peers.get_mut_peer(token).unwrap(); + peer.set_active(true); + let block: Block = match Block::from_bytes(block.as_slice()) { + Ok(block) => block, + Err(e) => { + warn!("Error deserializing block! {}", e); + return State::Banned + } + }; + if index != block.index { + return State::Banned; + } + info!("Received block {} with hash {:?}", block.index, &block.hash); + self.handle_block(token, block) + } + Message::Twin => { State::Twin } + Message::Loop => { State::Loop } + }; + answer + } + + fn handle_block(&mut self, token: &Token, block: Block) -> State { + let peers_count = self.peers.get_peers_active_count(); + let peer = self.peers.get_mut_peer(token).unwrap(); + peer.set_received_block(block.index); + + let mut context = self.context.lock().unwrap(); + let max_height = context.chain.max_height(); + match context.chain.check_new_block(&block) { + BlockQuality::Good => { + context.chain.add_block(block); + let my_height = context.chain.get_height(); + post(crate::event::Event::BlockchainChanged { index: my_height }); + // If it was the last block to sync + if my_height == max_height { + post(crate::event::Event::SyncFinished); + } else { + let event = crate::event::Event::Syncing { have: my_height, height: max(max_height, my_height) }; + post(event); + } + let domains = context.chain.get_domains_count(); + let keys = context.chain.get_users_count(); + post(crate::event::Event::NetworkStatus { blocks: my_height, domains, keys, nodes: peers_count }); + // To load blocks from different nodes we randomize requests of new blocks + // TODO rethink this approach + if max_height > my_height && random::() < 200 { + return State::message(Message::GetBlock { index: my_height + 1 }); + } + } + BlockQuality::Twin => { debug!("Ignoring duplicate block {}", block.index); } + BlockQuality::Future => { debug!("Ignoring future block {}", block.index); } + BlockQuality::Bad => { + // TODO save bad public keys to banned table + debug!("Ignoring bad block from {}:\n{:?}", peer.get_addr(), &block); + let height = context.chain.get_height(); + context.chain.update_max_height(height); + post(crate::event::Event::SyncFinished); + return State::Banned; + } + BlockQuality::Rewind => { + debug!("Got some orphan block, requesting its parent"); + return State::message(Message::GetBlock { index: block.index - 1 }); + } + BlockQuality::Fork => { + debug!("Got forked block {} with hash {:?}", block.index, block.hash); + // If we are very much behind of blockchain + let lagged = block.index == context.chain.get_height() && block.index + LIMITED_CONFIDENCE_DEPTH <= max_height; + let last_block = context.chain.last_block().unwrap(); + if block.is_better_than(&last_block) || lagged { + context.chain.replace_block(block).expect("Error replacing block with fork"); + let index = context.chain.get_height(); + post(crate::event::Event::BlockchainChanged { index }); + } else { + debug!("Fork in not better than our block, dropping."); + if let Some(block) = context.chain.get_block(block.index) { + return State::message(Message::block(block.index, block.as_bytes())); + } + } + } + } + State::idle() + } + + /// Gets new token from old token, mutating the last + pub fn next_token(&mut self) -> Token { + let current = self.token.0; + self.token.0 += 1; + Token(current) } } @@ -203,141 +635,56 @@ fn subscribe_to_bus(running: Arc) { }); } -fn handle_connection_event(context: Arc>, peers: &mut Peers, registry: &Registry, event: &Event) -> bool { - if event.is_error() || (event.is_read_closed() && event.is_write_closed()) { - return false; - } - if event.is_readable() { - let data = { - let token = event.token(); - match peers.get_mut_peer(&token) { +fn encode_bytes(data: &Vec, cipher: &Option) -> Vec { + match cipher { + None => { data.clone() } + Some(chacha) => { + chacha.encrypt(data.as_slice()) + } + } +} + +fn encode_message(message: &Message, cipher: &Option) -> Result, ()> { + match serde_cbor::to_vec(message) { + Ok(vec) => { + match cipher { None => { - error!("Error getting peer for connection {}", token.0); - return false; + //info!("No cipher, not encoding message: {:?}", to_hex(&vec)); + Ok(vec) } - Some(peer) => { - if event.is_read_closed() { - debug!("Node from {} disconnected", peer.get_addr().ip()); - return false; - } - let mut stream = peer.get_stream(); - read_message(&mut stream) + Some(chacha) => { + //info!("Encoding message: {:?}", to_hex(&vec)); + Ok(chacha.encrypt(vec.as_slice())) } } - }; - - if data.is_ok() { - let data = data.unwrap(); - match Message::from_bytes(data) { - Ok(message) => { - //let m = format!("{:?}", &message); - let new_state = handle_message(Arc::clone(&context), message, peers, &event.token()); - let peer = peers.get_mut_peer(&event.token()).unwrap(); - //debug!("Got message from {}: {:?}", &peer.get_addr(), &m); - let stream = peer.get_stream(); - match new_state { - State::Message { data } => { - registry.reregister(stream, event.token(), Interest::WRITABLE).unwrap(); - peer.set_state(State::Message { data }); - } - State::Connecting => {} - State::Connected => {} - State::Idle { .. } => { - peer.set_state(State::idle()); - } - State::Error => {} - State::Banned => { - peers.ignore_peer(registry, &event.token()); - } - State::Offline { .. } => { - peer.set_state(State::offline()); - } - State::Loop => { - peer.set_state(State::Loop); - peers.ignore_peer(registry, &event.token()); - } - State::SendLoop => { - registry.reregister(stream, event.token(), Interest::WRITABLE).unwrap(); - peer.set_state(State::SendLoop); - } - State::Twin => { - registry.reregister(stream, event.token(), Interest::WRITABLE).unwrap(); - peer.set_state(State::Twin); - } - } - } - Err(_) => { return false; } - } - } else { - return false; - } - } - - if event.is_writable() { - //trace!("Socket {} is writable", event.token().0); - let my_id = peers.get_my_id().to_owned(); - match peers.get_mut_peer(&event.token()) { - None => {} - Some(peer) => { - match peer.get_state().clone() { - State::Connecting => { - //debug!("Connected to peer {}, sending hello...", &peer.get_addr()); - let data: String = { - let c = context.lock().unwrap(); - let message = Message::hand(&c.app_version, &c.settings.origin, CHAIN_VERSION, c.settings.net.public, &my_id); - serde_json::to_string(&message).unwrap() - }; - send_message(peer.get_stream(), &data.into_bytes()).unwrap_or_else(|e| warn!("Error sending hello {}", e)); - //debug!("Sent hello to {}", &peer.get_addr()); - } - State::Message { data } => { - //debug!("Sending data to {}: {}", &peer.get_addr(), &String::from_utf8(data.clone()).unwrap()); - send_message(peer.get_stream(), &data).unwrap_or_else(|e| warn!("Error sending message {}", e)); - } - State::Connected => {} - State::Idle { from } => { - debug!("Odd version of pings :)"); - if from.elapsed().as_secs() >= 30 { - let data: String = { - let c = context.lock().unwrap(); - let message = Message::ping(c.chain.get_height(), c.chain.get_last_hash()); - serde_json::to_string(&message).unwrap() - }; - send_message(peer.get_stream(), &data.into_bytes()).unwrap_or_else(|e| warn!("Error sending ping {}", e)); - } - } - State::Error => {} - State::Banned => {} - State::Offline { .. } => {} - State::Loop => {} - State::SendLoop => { - let data = serde_json::to_string(&Message::Loop).unwrap(); - send_message(peer.get_stream(), &data.into_bytes()).unwrap_or_else(|e| warn!("Error sending loop {}", e)); - } - State::Twin => { - let data = serde_json::to_string(&Message::Twin).unwrap(); - send_message(peer.get_stream(), &data.into_bytes()).unwrap_or_else(|e| warn!("Error sending loop {}", e)); - } - } - registry.reregister(peer.get_stream(), event.token(), Interest::READABLE).unwrap(); - } + } + Err(e) => { + warn!("Could not encode message! {}", e); + Err(()) } } +} - true +fn decode_message(data: &Vec, cipher: &Option) -> Result, Error> { + match cipher { + None => { Ok(data.clone()) } + Some(chacha) => { + Ok(chacha.decrypt(data.as_slice())) + } + } } fn read_message(stream: &mut TcpStream) -> Result, ()> { let instant = Instant::now(); - let data_size = match stream.read_u32::() { - Ok(size) => { size as usize } + let data_size = match stream.read_u16::() { + Ok(size) => { (size ^ 0xAAAA) as usize } Err(e) => { error!("Error reading from socket! {}", e); 0 } }; - //trace!("Payload size is {}", data_size); + trace!("Payload size is {}", data_size); if data_size > MAX_PACKET_SIZE || data_size == 0 { return Err(()); } @@ -379,207 +726,102 @@ fn read_message(stream: &mut TcpStream) -> Result, ()> { } } -fn send_message(connection: &mut TcpStream, data: &Vec) -> io::Result<()> { - connection.write_u32::(data.len() as u32)?; - connection.write_all(&data)?; - connection.flush() +/// Sends one byte [garbage_size], [random bytes], and [public_key] +fn send_client_handshake(stream: &mut TcpStream, public_key: &[u8]) -> io::Result<()> { + let mut rng = rand::thread_rng(); + let packet_size: usize = rng.gen_range(64..255); + let mut buf = vec![0u8; packet_size]; + rng.fill_bytes(&mut buf); + let garbage_size = packet_size - 33; + buf[0] = garbage_size as u8 ^ 0xA; // key length and 1 byte size + for i in 0..public_key.len() { + buf[i + garbage_size + 1] = public_key[i]; + } + stream.write_all(buf.as_slice())?; + stream.flush() } -fn handle_message(context: Arc>, message: Message, peers: &mut Peers, token: &Token) -> State { - let (my_height, my_hash, my_origin, my_version) = { - let context = context.lock().unwrap(); - // TODO cache it somewhere - (context.chain.get_height(), context.chain.get_last_hash(), &context.settings.origin.clone(), CHAIN_VERSION) +fn read_client_handshake(stream: &mut TcpStream) -> Result, Error> { + // First, we read garbage size + let data_size = match stream.read_u8() { + Ok(size) => { (size ^ 0xA) as usize } + Err(e) => { + error!("Error reading from socket! {}", e); + return Err(e) + } }; - let answer = match message { - Message::Hand { app_version, origin, version, public, rand} => { - if peers.is_our_own_connect(&rand) { - warn!("Detected loop connect"); - State::SendLoop - } else { - if origin.eq(my_origin) && version == my_version { - let peer = peers.get_mut_peer(token).unwrap(); - peer.set_public(public); - peer.set_active(true); - debug!("Incoming v{} on {}", &app_version, peer.get_addr().ip()); - let app_version = context.lock().unwrap().app_version.clone(); - State::message(Message::shake(&app_version, &origin, version, true, my_height)) - } else { - warn!("Handshake from unsupported chain or version"); - State::Banned - } - } - } - Message::Shake { app_version, origin, version, ok, height } => { - if origin.ne(my_origin) || version != my_version { - return State::Banned; - } - if ok { - let nodes = peers.get_peers_active_count(); - let peer = peers.get_mut_peer(token).unwrap(); - debug!("Outgoing v{} on {}", &app_version, peer.get_addr().ip()); - peer.set_height(height); - peer.set_active(true); - peer.reset_reconnects(); - let mut context = context.lock().unwrap(); - if peer.is_higher(my_height) { - context.chain.update_max_height(height); - let event = crate::event::Event::Syncing { have: my_height, height: max(height, my_height) }; - post(event); - } - if nodes < MAX_NODES && random::() { - debug!("Requesting more peers from {}", peer.get_addr().ip()); - State::message(Message::GetPeers) - } else { - State::idle() - } - } else { - State::Banned - } - } - Message::Error => { State::Error } - Message::Ping { height, hash } => { - let peer = peers.get_mut_peer(token).unwrap(); - peer.set_height(height); - peer.set_active(true); - if peer.is_higher(my_height) { - let mut context = context.lock().unwrap(); - context.chain.update_max_height(height); - info!("Peer is higher, requesting block {} from {}", height, peer.get_addr().ip()); - State::message(Message::GetBlock { index: my_height + 1 }) - } else if my_height == height && hash.ne(&my_hash) { - info!("Hashes are different, requesting block {} from {}", my_height, peer.get_addr().ip()); - info!("My hash: {:?}, their hash: {:?}", &my_hash, &hash); - State::message(Message::GetBlock { index: my_height }) - } else { - State::message(Message::pong(my_height, my_hash)) - } - } - Message::Pong { height, hash } => { - let active_count = peers.get_peers_active_count(); - let peer = peers.get_mut_peer(token).unwrap(); - peer.set_height(height); - peer.set_active(true); - if peer.is_higher(my_height) { - let mut context = context.lock().unwrap(); - context.chain.update_max_height(height); - info!("Peer is higher, requesting block {} from {}", height, peer.get_addr().ip()); - State::message(Message::GetBlock { index: my_height + 1 }) - } else if my_height == height && hash.ne(&my_hash) { - info!("Hashes are different, requesting block {} from {}", my_height, peer.get_addr().ip()); - info!("My hash: {:?}, their hash: {:?}", &my_hash, &hash); - State::message(Message::GetBlock { index: my_height }) - } else { - if active_count < MAX_NODES && random::() < 50 { - debug!("Requesting more peers from {}", peer.get_addr().ip()); - State::message(Message::GetPeers) - } else { - State::idle() - } - } - } - Message::GetPeers => { - let addr = { - let peer = peers.get_mut_peer(token).unwrap(); - peer.set_active(true); - peer.get_addr().clone() - }; - State::message(Message::Peers { peers: peers.get_peers_for_exchange(&addr) }) - } - Message::Peers { peers: new_peers } => { - let peer = peers.get_mut_peer(token).unwrap(); - peer.set_active(true); - peers.add_peers_from_exchange(new_peers); - State::idle() - } - Message::GetBlock { index } => { - let peer = peers.get_mut_peer(token).unwrap(); - peer.set_active(true); - let context = context.lock().unwrap(); - match context.chain.get_block(index) { - Some(block) => State::message(Message::block(block.index, serde_json::to_string(&block).unwrap())), - None => State::Error - } - } - Message::Block { index, block } => { - let peer = peers.get_mut_peer(token).unwrap(); - peer.set_active(true); - let block: Block = match serde_json::from_str(&block) { - Ok(block) => block, - Err(_) => return State::Banned - }; - if index != block.index { - return State::Banned; - } - info!("Received block {} with hash {:?}", block.index, &block.hash); - handle_block(context, peers, token, block) - } - Message::Twin => { State::Twin } - Message::Loop => { State::Loop } - }; - answer -} - -fn handle_block(context: Arc>, peers: &mut Peers, token: &Token, block: Block) -> State { - let peers_count = peers.get_peers_active_count(); - let peer = peers.get_mut_peer(token).unwrap(); - peer.set_received_block(block.index); - - let mut context = context.lock().unwrap(); - let max_height = context.chain.max_height(); - match context.chain.check_new_block(&block) { - BlockQuality::Good => { - context.chain.add_block(block); - let my_height = context.chain.get_height(); - post(crate::event::Event::BlockchainChanged { index: my_height }); - // If it was the last block to sync - if my_height == max_height { - post(crate::event::Event::SyncFinished); - } else { - let event = crate::event::Event::Syncing { have: my_height, height: max(max_height, my_height) }; - post(event); - } - let domains = context.chain.get_domains_count(); - let keys = context.chain.get_users_count(); - post(crate::event::Event::NetworkStatus { blocks: my_height, domains, keys, nodes: peers_count }); - // To load blocks from different nodes we randomize requests of new blocks - // TODO rethink this approach - if max_height > my_height && random::() < 200 { - return State::message(Message::GetBlock { index: my_height + 1 }); - } - } - BlockQuality::Twin => { debug!("Ignoring duplicate block {}", block.index); } - BlockQuality::Future => { debug!("Ignoring future block {}", block.index); } - BlockQuality::Bad => { - // TODO save bad public keys to banned table - debug!("Ignoring bad block from {}:\n{:?}", peer.get_addr(), &block); - let height = context.chain.get_height(); - context.chain.update_max_height(height); - post(crate::event::Event::SyncFinished); - return State::Banned; - } - BlockQuality::Rewind => { - debug!("Got some orphan block, requesting its parent"); - return State::message(Message::GetBlock { index: block.index - 1 }); - } - BlockQuality::Fork => { - debug!("Got forked block {} with hash {:?}", block.index, block.hash); - // If we are very much behind of blockchain - let lagged = block.index == context.chain.get_height() && block.index + LIMITED_CONFIDENCE_DEPTH <= max_height; - let last_block = context.chain.last_block().unwrap(); - if block.is_better_than(&last_block) || lagged { - context.chain.replace_block(block).expect("Error replacing block with fork"); - let index = context.chain.get_height(); - post(crate::event::Event::BlockchainChanged { index }); - } else { - debug!("Fork in not better than our block, dropping."); - if let Some(block) = context.chain.get_block(block.index) { - return State::message(Message::block(block.index, serde_json::to_string(&block).unwrap())); - } - } + // Read the garbage + let mut buf = vec![0u8; data_size]; + match stream.read_exact(&mut buf) { + Ok(_) => {} + Err(e) => { return Err(e); } + } + // Then we have public key for ECDH + let mut buf = vec![0u8; 32]; + match stream.read_exact(&mut buf) { + Ok(_) => { Ok(buf) } + Err(e) => { + warn!("Error reading handshake!"); + Err(e) } } - State::idle() +} + +fn send_server_handshake(peer: &mut Peer, public_key: &[u8]) -> io::Result<()> { + let mut rng = rand::thread_rng(); + let packet_size: usize = rng.gen_range(64..255); + let mut buf = vec![0u8; packet_size]; + rng.fill_bytes(&mut buf); + let nonce = peer.get_nonce(); + // We will write 1 byte size, garbage, public key, nonce + let garbage_size = packet_size - 1 - 32 - 12; + buf[0] = garbage_size as u8 ^ 0xA; + for i in 0..public_key.len() { + buf[i + garbage_size + 1] = public_key[i]; + } + for i in 0..nonce.len() { + buf[i + garbage_size + 32 + 1] = nonce[i]; + } + let stream = peer.get_stream(); + stream.write_all(buf.as_slice())?; + stream.flush() +} + +fn read_server_handshake(stream: &mut TcpStream) -> Result, Error> { + // First, we read garbage size + let data_size = match stream.read_u8() { + Ok(size) => { (size ^ 0xA) as usize } + Err(e) => { + error!("Error reading from socket! {}", e); + return Err(e) + } + }; + // Read the garbage + let mut buf = vec![0u8; data_size]; + match stream.read_exact(&mut buf) { + Ok(_) => {} + Err(e) => { return Err(e); } + } + // Then we have public key for ECDH, plus nonce 12 bytes + let mut buf = vec![0u8; 32 + 12]; + match stream.read_exact(&mut buf) { + Ok(_) => { Ok(buf) } + Err(e) => { + warn!("Error reading handshake!"); + Err(e) + } + } +} + +fn send_message(connection: &mut TcpStream, data: &Vec) -> io::Result<()> { + let data_len = data.len() as u16; + //debug!("Sending {} bytes", data_len); + //debug!("Message: {:?}", to_hex(&data)); + let mut buf: Vec = Vec::with_capacity(data.len() + 2); + buf.write_u16::(data_len ^ 0xAAAA)?; + buf.write_all(&data)?; + connection.write_all(&buf)?; + connection.flush() } fn would_block(err: &io::Error) -> bool { diff --git a/src/p2p/peer.rs b/src/p2p/peer.rs index 82f279a..b4ec42f 100644 --- a/src/p2p/peer.rs +++ b/src/p2p/peer.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use mio::net::TcpStream; use crate::p2p::State; use crate::Block; +use crate::crypto::Chacha; #[derive(Debug)] pub struct Peer { @@ -16,6 +17,7 @@ pub struct Peer { active: bool, reconnects: u32, received_block: u64, + cipher: Option, fork: HashMap } @@ -32,10 +34,26 @@ impl Peer { active: false, reconnects: 0, received_block: 0, + cipher: None, fork: HashMap::new() } } + pub fn set_cipher(&mut self, cipher: Chacha) { + self.cipher = Some(cipher); + } + + pub fn get_cipher(&self) -> &Option { + &self.cipher + } + + pub fn get_nonce(&self) -> &[u8; 12] { + match &self.cipher { + None => { &crate::crypto::ZERO_NONCE } + Some(chacha) => { chacha.get_nonce() } + } + } + pub fn get_addr(&self) -> SocketAddr { self.addr.clone() } diff --git a/src/p2p/peers.rs b/src/p2p/peers.rs index 917a158..dbe3558 100644 --- a/src/p2p/peers.rs +++ b/src/p2p/peers.rs @@ -12,7 +12,6 @@ use rand::seq::IteratorRandom; use crate::{Bytes, commons}; use crate::commons::*; use crate::p2p::{Message, Peer, State}; -use crate::commons::next; use std::io; const PING_PERIOD: u64 = 30; @@ -84,6 +83,12 @@ impl Peers { State::Twin => { info!("Peer connection {} to {:?} is a twin", &token.0, &peer.get_addr()); } + State::ServerHandshake => { + info!("Peer connection {} from {:?} didn't shake hands", &token.0, &peer.get_addr()); + } + State::HandshakeFinished => { + info!("Peer connection {} from {:?} shaked hands, but then failed", &token.0, &peer.get_addr()); + } } self.peers.remove(token); @@ -193,6 +198,15 @@ impl Peers { count } + pub fn is_tween_connect(&self, id: &str) -> bool { + for (_, peer) in self.peers.iter() { + if peer.active() && peer.get_id() == id { + return true; + } + } + false + } + pub fn get_peers_banned_count(&self) -> usize { self.ignored.len() } @@ -401,6 +415,13 @@ impl Peers { } } +/// Gets new token from old token, mutating the last +pub fn next(current: &mut Token) -> Token { + let next = current.0; + current.0 += 1; + Token(next) +} + fn skip_private_addr(addr: &SocketAddr) -> bool { if addr.ip().is_loopback() { return true; diff --git a/src/p2p/state.rs b/src/p2p/state.rs index 1d79c4d..a2d9579 100644 --- a/src/p2p/state.rs +++ b/src/p2p/state.rs @@ -5,6 +5,8 @@ use crate::p2p::Message; pub enum State { Connecting, Connected, + ServerHandshake, + HandshakeFinished, Idle { from: Instant }, Message { data: Vec }, Error, @@ -25,8 +27,8 @@ impl State { } pub fn message(message: Message) -> Self { - let response = serde_json::to_string(&message).unwrap(); - State::Message {data: Vec::from(response.as_bytes()) } + let data = serde_cbor::to_vec(&message).unwrap(); + State::Message { data } } pub fn is_idle(&self) -> bool {