From 99780d3eb0b4a2bf56587168c2486669572bccda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 27 May 2021 11:27:09 +0100 Subject: [PATCH 01/24] Updated smart contract to work with future cosmwasm 0.14.0 update --- Cargo.lock | 193 ++++++++++++-- common/mixnet-contract/Cargo.toml | 4 +- common/mixnet-contract/src/gateway.rs | 18 +- common/mixnet-contract/src/lib.rs | 2 +- common/mixnet-contract/src/mixnode.rs | 18 +- contracts/mixnet/Cargo.lock | 354 ++++++++++++++++++++++++-- contracts/mixnet/Cargo.toml | 8 +- contracts/mixnet/examples/schema.rs | 6 +- contracts/mixnet/src/contract.rs | 55 ++-- contracts/mixnet/src/error.rs | 8 +- contracts/mixnet/src/helpers.rs | 2 +- contracts/mixnet/src/lib.rs | 3 - contracts/mixnet/src/msg.rs | 17 +- contracts/mixnet/src/queries.rs | 94 ++++--- contracts/mixnet/src/state.rs | 6 +- contracts/mixnet/src/storage.rs | 18 +- contracts/mixnet/src/support/tests.rs | 16 +- contracts/mixnet/src/transactions.rs | 331 ++++++++++++------------ 18 files changed, 834 insertions(+), 319 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3e1814e16..d07581e2d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -223,6 +223,17 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitvec" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98fcd36dda4e17b7d7abc64cb549bf0201f4ab71e00700c798ca7e62ed3761fa" +dependencies = [ + "funty", + "radium", + "wyz", +] + [[package]] name = "blake2" version = "0.8.1" @@ -458,6 +469,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "const-oid" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f6b64db6932c7e49332728e3a6bd82c6b7e16016607d20923b537c3bc4c0d5f" + [[package]] name = "const_fn" version = "0.4.7" @@ -504,21 +521,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] -name = "cosmwasm-derive" -version = "0.13.2" +name = "cosmwasm-crypto" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de70197a0fe4e402aa260da00ec62d9bf091afe87866e9f3347691d591b60f89" +checksum = "3ddbf475b0e8a9bd813607d59144ad3f71d90dd66c5e975a46ac2b72ce754121" +dependencies = [ + "digest 0.9.0", + "ed25519-zebra", + "k256", + "rand_core 0.5.1", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e62de21147741486c6d4adc28850b102dcad1888d9fc2d0a200ca423284563" dependencies = [ "syn", ] [[package]] name = "cosmwasm-std" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02173c4eb78ef76863f5190f60a45278d11e7c8b142327c149e18128b2b97f85" +checksum = "db14129579ddb1dbd8a28376673d61090f35c9069978eb875d489c275bb76315" dependencies = [ "base64 0.13.0", + "cosmwasm-crypto", "cosmwasm-derive", "schemars", "serde", @@ -604,7 +635,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ "generic-array 0.14.4", - "subtle 2.2.3", + "subtle 2.4.0", ] [[package]] @@ -614,7 +645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" dependencies = [ "generic-array 0.14.4", - "subtle 2.2.3", + "subtle 2.4.0", ] [[package]] @@ -645,7 +676,7 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", - "subtle 2.2.3", + "subtle 2.4.0", "zeroize", ] @@ -659,6 +690,15 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "der" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f59c66c30bb7445c8320a5f9233e437e3572368099f25532a59054328899b4" +dependencies = [ + "const-oid", +] + [[package]] name = "derive_more" version = "0.99.13" @@ -763,6 +803,23 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +[[package]] +name = "dyn-clone" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" + +[[package]] +name = "ecdsa" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fbdb4ff710acb4db8ca29f93b897529ea6d6a45626d5183b47e012aa6ae7e4" +dependencies = [ + "elliptic-curve", + "hmac 0.10.1", + "signature", +] + [[package]] name = "ed25519" version = "1.0.1" @@ -786,12 +843,44 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-zebra" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a128b76af6dd4b427e34a6fd43dc78dbfe73672ec41ff615a2414c1a0ad0409" +dependencies = [ + "curve25519-dalek", + "hex", + "rand_core 0.5.1", + "serde", + "sha2 0.9.1", + "thiserror", +] + [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elliptic-curve" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2db227e61a43a34915680bdda462ec0e212095518020a88a1f91acd16092c39" +dependencies = [ + "bitvec", + "digest 0.9.0", + "ff", + "funty", + "generic-array 0.14.4", + "group", + "pkcs8", + "rand_core 0.5.1", + "subtle 2.4.0", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.24" @@ -820,6 +909,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "ff" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01646e077d4ebda82b73f1bca002ea1e91561a77df2431a9e79729bcc31950ef" +dependencies = [ + "bitvec", + "rand_core 0.5.1", + "subtle 2.4.0", +] + [[package]] name = "figment" version = "0.10.5" @@ -875,6 +975,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "futures" version = "0.3.9" @@ -1078,6 +1184,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "group" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11f9f5fbf1943b48ae7c2bf6846e7d827a512d1be4f23af708f5ca5d01dde1" +dependencies = [ + "ff", + "rand_core 0.5.1", + "subtle 2.4.0", +] + [[package]] name = "h2" version = "0.3.1" @@ -1126,6 +1243,12 @@ 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.8.0" @@ -1344,6 +1467,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4476a0808212a9e81ce802eb1a0cfc60e73aea296553bacc0fac7e1268bc572a" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sha2 0.9.1", +] + [[package]] name = "keystream" version = "1.0.0" @@ -2140,6 +2275,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4839a901843f3942576e65857f0ebf2e190ef7024d3c62a94099ba3f819ad1d" +dependencies = [ + "der", +] + [[package]] name = "pkg-config" version = "0.3.18" @@ -2242,6 +2386,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" + [[package]] name = "rand" version = "0.7.3" @@ -2574,10 +2724,11 @@ dependencies = [ [[package]] name = "schemars" -version = "0.7.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be77ed66abed6954aabf6a3e31a84706bedbf93750d267e92ef4a6d90bbd6a61" +checksum = "bc6ab463ae35acccb5cba66c0084c985257b797d288b6050cc2f6ac1b266cb78" dependencies = [ + "dyn-clone", "schemars_derive", "serde", "serde_json", @@ -2585,9 +2736,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.7.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11af7a475c9ee266cfaa9e303a47c830ebe072bf3101ab907a7b7b9d816fa01d" +checksum = "902fdfbcf871ae8f653bddf4b2c05905ddaabc08f69d32a915787e3be0d31356" dependencies = [ "proc-macro2", "quote", @@ -2674,9 +2825,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120bad73306616e91acd7ceed522ba96032a51cffeef3cc813de7f367df71e37" +checksum = "50eef3672ec8fa45f3457fd423ba131117786784a895548021976117c1ded449" dependencies = [ "serde", ] @@ -2797,6 +2948,10 @@ name = "signature" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" +dependencies = [ + "digest 0.9.0", + "rand_core 0.5.1", +] [[package]] name = "slab" @@ -2995,9 +3150,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" -version = "2.2.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502d53007c02d7605a05df1c1a73ee436952781653da5d0bf57ad608f66932c1" +checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" @@ -3647,6 +3802,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + [[package]] name = "x25519-dalek" version = "1.1.0" diff --git a/common/mixnet-contract/Cargo.toml b/common/mixnet-contract/Cargo.toml index 75a67f9140..5130f70776 100644 --- a/common/mixnet-contract/Cargo.toml +++ b/common/mixnet-contract/Cargo.toml @@ -7,6 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cosmwasm-std = { version = "0.13.2" } +cosmwasm-std = { version = "0.14.0" } serde = { version = "1.0", features = ["derive"] } -schemars = "0.7" +schemars = "0.8" diff --git a/common/mixnet-contract/src/gateway.rs b/common/mixnet-contract/src/gateway.rs index 301a011278..1abee2a4ef 100644 --- a/common/mixnet-contract/src/gateway.rs +++ b/common/mixnet-contract/src/gateway.rs @@ -1,7 +1,7 @@ // due to code generated by JsonSchema #![allow(clippy::field_reassign_with_default)] -use cosmwasm_std::{Coin, HumanAddr}; +use cosmwasm_std::{Addr, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Display; @@ -49,12 +49,12 @@ impl Gateway { #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct GatewayBond { pub amount: Vec, - pub owner: HumanAddr, + pub owner: Addr, pub gateway: Gateway, } impl GatewayBond { - pub fn new(amount: Vec, owner: HumanAddr, gateway: Gateway) -> Self { + pub fn new(amount: Vec, owner: Addr, gateway: Gateway) -> Self { GatewayBond { amount, owner, @@ -66,7 +66,7 @@ impl GatewayBond { &self.amount } - pub fn owner(&self) -> &HumanAddr { + pub fn owner(&self) -> &Addr { &self.owner } @@ -93,15 +93,11 @@ impl Display for GatewayBond { pub struct PagedGatewayResponse { pub nodes: Vec, pub per_page: usize, - pub start_next_after: Option, + pub start_next_after: Option, } impl PagedGatewayResponse { - pub fn new( - nodes: Vec, - per_page: usize, - start_next_after: Option, - ) -> Self { + pub fn new(nodes: Vec, per_page: usize, start_next_after: Option) -> Self { PagedGatewayResponse { nodes, per_page, @@ -112,6 +108,6 @@ impl PagedGatewayResponse { #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct GatewayOwnershipResponse { - pub address: HumanAddr, + pub address: Addr, pub has_gateway: bool, } diff --git a/common/mixnet-contract/src/lib.rs b/common/mixnet-contract/src/lib.rs index 0ffefd312d..cd1dedee33 100644 --- a/common/mixnet-contract/src/lib.rs +++ b/common/mixnet-contract/src/lib.rs @@ -1,6 +1,6 @@ mod gateway; mod mixnode; -pub use cosmwasm_std::{Coin, HumanAddr}; +pub use cosmwasm_std::{Coin, Addr}; pub use gateway::{Gateway, GatewayBond, GatewayOwnershipResponse, PagedGatewayResponse}; pub use mixnode::{MixNode, MixNodeBond, MixOwnershipResponse, PagedResponse}; diff --git a/common/mixnet-contract/src/mixnode.rs b/common/mixnet-contract/src/mixnode.rs index cd205a0a50..83aca98c63 100644 --- a/common/mixnet-contract/src/mixnode.rs +++ b/common/mixnet-contract/src/mixnode.rs @@ -1,7 +1,7 @@ // due to code generated by JsonSchema #![allow(clippy::field_reassign_with_default)] -use cosmwasm_std::{Coin, HumanAddr}; +use cosmwasm_std::{Addr, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Display; @@ -49,12 +49,12 @@ impl MixNode { #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct MixNodeBond { pub amount: Vec, - pub owner: HumanAddr, + pub owner: Addr, pub mix_node: MixNode, } impl MixNodeBond { - pub fn new(amount: Vec, owner: HumanAddr, mix_node: MixNode) -> Self { + pub fn new(amount: Vec, owner: Addr, mix_node: MixNode) -> Self { MixNodeBond { amount, owner, @@ -66,7 +66,7 @@ impl MixNodeBond { &self.amount } - pub fn owner(&self) -> &HumanAddr { + pub fn owner(&self) -> &Addr { &self.owner } @@ -97,15 +97,11 @@ impl Display for MixNodeBond { pub struct PagedResponse { pub nodes: Vec, pub per_page: usize, - pub start_next_after: Option, + pub start_next_after: Option, } impl PagedResponse { - pub fn new( - nodes: Vec, - per_page: usize, - start_next_after: Option, - ) -> Self { + pub fn new(nodes: Vec, per_page: usize, start_next_after: Option) -> Self { PagedResponse { nodes, per_page, @@ -116,6 +112,6 @@ impl PagedResponse { #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct MixOwnershipResponse { - pub address: HumanAddr, + pub address: Addr, pub has_node: bool, } diff --git a/contracts/mixnet/Cargo.lock b/contracts/mixnet/Cargo.lock index 04a7d9a5ae..34467e9eb4 100644 --- a/contracts/mixnet/Cargo.lock +++ b/contracts/mixnet/Cargo.lock @@ -7,19 +7,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] -name = "cosmwasm-derive" -version = "0.13.2" +name = "bitvec" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de70197a0fe4e402aa260da00ec62d9bf091afe87866e9f3347691d591b60f89" +checksum = "98fcd36dda4e17b7d7abc64cb549bf0201f4ab71e00700c798ca7e62ed3761fa" +dependencies = [ + "funty", + "radium", + "wyz", +] + +[[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 = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f6b64db6932c7e49332728e3a6bd82c6b7e16016607d20923b537c3bc4c0d5f" + +[[package]] +name = "cosmwasm-crypto" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ddbf475b0e8a9bd813607d59144ad3f71d90dd66c5e975a46ac2b72ce754121" +dependencies = [ + "digest", + "ed25519-zebra", + "k256", + "rand_core", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e62de21147741486c6d4adc28850b102dcad1888d9fc2d0a200ca423284563" dependencies = [ "syn", ] [[package]] name = "cosmwasm-schema" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98b56c1c839e5cfda1be0e0f152728b34bdcd5a2e921905947f6d088bab2c68" +checksum = "d6a9a6a4ca3b4d7b56f943312a65857cdfc84424f9c2773889f4cd17f36fba61" dependencies = [ "schemars", "serde_json", @@ -27,11 +78,12 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02173c4eb78ef76863f5190f60a45278d11e7c8b142327c149e18128b2b97f85" +checksum = "db14129579ddb1dbd8a28376673d61090f35c9069978eb875d489c275bb76315" dependencies = [ "base64", + "cosmwasm-crypto", "cosmwasm-derive", "schemars", "serde", @@ -41,20 +93,202 @@ dependencies = [ [[package]] name = "cosmwasm-storage" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2cdb5f6c3181c921c02b0018af66178e60bc7be088f81ec730b22ff51240404" +checksum = "13b03dc324ef7b5bce224e096d67bc67e12aadc8fbacb7c8c796eac40cf7c4b8" dependencies = [ "cosmwasm-std", "serde", ] +[[package]] +name = "cpufeatures" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8" +dependencies = [ + "libc", +] + +[[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 = "curve25519-dalek" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "639891fde0dbea823fc3d798a0fdf9d2f9440a42d64a78ab3488b0ca025117b3" +dependencies = [ + "byteorder", + "digest", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "der" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f59c66c30bb7445c8320a5f9233e437e3572368099f25532a59054328899b4" +dependencies = [ + "const-oid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dyn-clone" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" + +[[package]] +name = "ecdsa" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fbdb4ff710acb4db8ca29f93b897529ea6d6a45626d5183b47e012aa6ae7e4" +dependencies = [ + "elliptic-curve", + "hmac", + "signature", +] + +[[package]] +name = "ed25519-zebra" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a128b76af6dd4b427e34a6fd43dc78dbfe73672ec41ff615a2414c1a0ad0409" +dependencies = [ + "curve25519-dalek", + "hex", + "rand_core", + "serde", + "sha2", + "thiserror", +] + +[[package]] +name = "elliptic-curve" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2db227e61a43a34915680bdda462ec0e212095518020a88a1f91acd16092c39" +dependencies = [ + "bitvec", + "digest", + "ff", + "funty", + "generic-array", + "group", + "pkcs8", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "ff" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01646e077d4ebda82b73f1bca002ea1e91561a77df2431a9e79729bcc31950ef" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + +[[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 = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11f9f5fbf1943b48ae7c2bf6846e7d827a512d1be4f23af708f5ca5d01dde1" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac", + "digest", +] + [[package]] name = "itoa" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +[[package]] +name = "k256" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4476a0808212a9e81ce802eb1a0cfc60e73aea296553bacc0fac7e1268bc572a" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "libc" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" + [[package]] name = "mixnet-contract" version = "0.1.0" @@ -77,6 +311,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "pkcs8" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4839a901843f3942576e65857f0ebf2e190ef7024d3c62a94099ba3f819ad1d" +dependencies = [ + "der", +] + [[package]] name = "proc-macro2" version = "1.0.24" @@ -95,6 +344,21 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + [[package]] name = "ryu" version = "1.0.5" @@ -103,10 +367,11 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "schemars" -version = "0.7.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be77ed66abed6954aabf6a3e31a84706bedbf93750d267e92ef4a6d90bbd6a61" +checksum = "bc6ab463ae35acccb5cba66c0084c985257b797d288b6050cc2f6ac1b266cb78" dependencies = [ + "dyn-clone", "schemars_derive", "serde", "serde_json", @@ -114,9 +379,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.7.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11af7a475c9ee266cfaa9e303a47c830ebe072bf3101ab907a7b7b9d816fa01d" +checksum = "902fdfbcf871ae8f653bddf4b2c05905ddaabc08f69d32a915787e3be0d31356" dependencies = [ "proc-macro2", "quote", @@ -135,9 +400,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120bad73306616e91acd7ceed522ba96032a51cffeef3cc813de7f367df71e37" +checksum = "50eef3672ec8fa45f3457fd423ba131117786784a895548021976117c1ded449" dependencies = [ "serde", ] @@ -175,6 +440,35 @@ dependencies = [ "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.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" +dependencies = [ + "digest", + "rand_core", +] + +[[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.60" @@ -206,8 +500,38 @@ dependencies = [ "syn", ] +[[package]] +name = "typenum" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" + [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[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 = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index b482d2ff6b..1d9819d318 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -34,11 +34,11 @@ backtraces = ["cosmwasm-std/backtraces"] [dependencies] mixnet-contract = { path = "../../common/mixnet-contract" } -cosmwasm-std = { version = "0.13.2", features = ["iterator"] } -cosmwasm-storage = { version = "0.13.2", features = ["iterator"] } -schemars = "0.7" +cosmwasm-std = { version = "0.14.0", features = ["iterator"] } +cosmwasm-storage = { version = "0.14.0", features = ["iterator"] } +schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } thiserror = { version = "1.0.23" } [dev-dependencies] -cosmwasm-schema = { version = "0.13.2" } +cosmwasm-schema = { version = "0.14.0" } diff --git a/contracts/mixnet/examples/schema.rs b/contracts/mixnet/examples/schema.rs index cbe5ce4e9c..ad28a2d7c4 100644 --- a/contracts/mixnet/examples/schema.rs +++ b/contracts/mixnet/examples/schema.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; use mixnet_contract::MixNodeBond; -use mixnet_contracts::msg::{HandleMsg, InitMsg, QueryMsg}; +use mixnet_contracts::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; use mixnet_contracts::state::State; use std::env::current_dir; use std::fs::create_dir_all; @@ -11,8 +11,8 @@ fn main() { create_dir_all(&out_dir).unwrap(); remove_schemas(&out_dir).unwrap(); - export_schema(&schema_for!(InitMsg), &out_dir); - export_schema(&schema_for!(HandleMsg), &out_dir); + export_schema(&schema_for!(InstantiateMsg), &out_dir); + export_schema(&schema_for!(ExecuteMsg), &out_dir); export_schema(&schema_for!(QueryMsg), &out_dir); export_schema(&schema_for!(State), &out_dir); export_schema(&schema_for!(MixNodeBond), &out_dir); diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index fd69ed5c4d..09cb439d12 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -1,11 +1,11 @@ use crate::helpers::calculate_epoch_reward_rate; -use crate::msg::{HandleMsg, InitMsg, MigrateMsg, QueryMsg}; +use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; use crate::state::{State, StateParams}; use crate::storage::config; use crate::{error::ContractError, queries, transactions}; use cosmwasm_std::{ - to_binary, Decimal, Deps, DepsMut, Env, HandleResponse, HumanAddr, InitResponse, MessageInfo, - MigrateResponse, QueryResponse, Uint128, + entry_point, to_binary, Addr, Decimal, Deps, DepsMut, Env, MessageInfo, QueryResponse, + Response, Uint128, }; pub const INITIAL_DEFAULT_EPOCH_LENGTH: u32 = 2; @@ -27,13 +27,13 @@ const NETWORK_MONITOR_ADDRESS: &str = "hal1v9qauwdq5terag6uvfsdytcs2d0sdmfdq6e83 /// Constant specifying denomination of the coin used for bonding pub const DENOM: &str = "uhal"; -fn default_initial_state(owner: HumanAddr) -> State { +fn default_initial_state(owner: Addr) -> State { let mixnode_bond_reward_rate = Decimal::percent(INITIAL_MIXNODE_BOND_REWARD_RATE); let gateway_bond_reward_rate = Decimal::percent(INITIAL_GATEWAY_BOND_REWARD_RATE); State { owner, - network_monitor_address: NETWORK_MONITOR_ADDRESS.into(), + network_monitor_address: Addr::unchecked(NETWORK_MONITOR_ADDRESS), // we trust our hardcoded value params: StateParams { epoch_length: INITIAL_DEFAULT_EPOCH_LENGTH, minimum_mixnode_bond: INITIAL_MIXNODE_BOND, @@ -58,42 +58,45 @@ fn default_initial_state(owner: HumanAddr) -> State { /// `deps` contains Storage, API and Querier /// `env` contains block, message and contract info /// `msg` is the contract initialization message, sort of like a constructor call. -pub fn init( +#[entry_point] +pub fn instantiate( deps: DepsMut, _env: Env, info: MessageInfo, - _msg: InitMsg, -) -> Result { + _msg: InstantiateMsg, +) -> Result { let state = default_initial_state(info.sender); config(deps.storage).save(&state)?; - Ok(InitResponse::default()) + Ok(Response::default()) } /// Handle an incoming message -pub fn handle( +#[entry_point] +pub fn execute( deps: DepsMut, - env: Env, + _env: Env, info: MessageInfo, - msg: HandleMsg, -) -> Result { + msg: ExecuteMsg, +) -> Result { match msg { - HandleMsg::BondMixnode { mix_node } => transactions::try_add_mixnode(deps, info, mix_node), - HandleMsg::UnbondMixnode {} => transactions::try_remove_mixnode(deps, info, env), - HandleMsg::BondGateway { gateway } => transactions::try_add_gateway(deps, info, gateway), - HandleMsg::UnbondGateway {} => transactions::try_remove_gateway(deps, info, env), - HandleMsg::UpdateStateParams(params) => { + ExecuteMsg::BondMixnode { mix_node } => transactions::try_add_mixnode(deps, info, mix_node), + ExecuteMsg::UnbondMixnode {} => transactions::try_remove_mixnode(deps, info), + ExecuteMsg::BondGateway { gateway } => transactions::try_add_gateway(deps, info, gateway), + ExecuteMsg::UnbondGateway {} => transactions::try_remove_gateway(deps, info), + ExecuteMsg::UpdateStateParams(params) => { transactions::try_update_state_params(deps, info, params) } - HandleMsg::RewardMixnode { owner, uptime } => { + ExecuteMsg::RewardMixnode { owner, uptime } => { transactions::try_reward_mixnode(deps, info, owner, uptime) } - HandleMsg::RewardGateway { owner, uptime } => { + ExecuteMsg::RewardGateway { owner, uptime } => { transactions::try_reward_gateway(deps, info, owner, uptime) } } } +#[entry_point] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { let query_res = match msg { QueryMsg::GetMixNodes { start_after, limit } => { @@ -114,12 +117,8 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result Result { +#[entry_point] +pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result { Ok(Default::default()) } @@ -135,10 +134,10 @@ pub mod tests { fn initialize_contract() { let mut deps = mock_dependencies(&[]); let env = mock_env(); - let msg = InitMsg {}; + let msg = InstantiateMsg {}; let info = mock_info("creator", &[]); - let res = init(deps.as_mut(), env.clone(), info, msg).unwrap(); + let res = instantiate(deps.as_mut(), env.clone(), info, msg).unwrap(); assert_eq!(0, res.messages.len()); // mix_node_bonds should be empty after initialization diff --git a/contracts/mixnet/src/error.rs b/contracts/mixnet/src/error.rs index 9a66239cac..dc519df69f 100644 --- a/contracts/mixnet/src/error.rs +++ b/contracts/mixnet/src/error.rs @@ -1,5 +1,5 @@ use crate::contract::DENOM; -use cosmwasm_std::{HumanAddr, StdError}; +use cosmwasm_std::{Addr, StdError}; use thiserror::Error; /// Custom errors for contract failure conditions. @@ -25,7 +25,7 @@ pub enum ContractError { InsufficientGatewayBond { received: u128, minimum: u128 }, #[error("Account ({account:?}) does not own any gateway bonds")] - GatewayBondNotFound { account: HumanAddr }, + GatewayBondNotFound { account: Addr }, #[error("Unauthorized")] Unauthorized, @@ -55,8 +55,8 @@ pub enum ContractError { AlreadyOwnsGateway, #[error("Mixnode with this identity already exists. Its owner is {owner:?}")] - DuplicateMixnode { owner: HumanAddr }, + DuplicateMixnode { owner: Addr }, #[error("Gateway with this identity already exists. Its owner is {owner:?}")] - DuplicateGateway { owner: HumanAddr }, + DuplicateGateway { owner: Addr }, } diff --git a/contracts/mixnet/src/helpers.rs b/contracts/mixnet/src/helpers.rs index 5fbc245e53..ed15c3124c 100644 --- a/contracts/mixnet/src/helpers.rs +++ b/contracts/mixnet/src/helpers.rs @@ -26,7 +26,7 @@ fn decimal_sub_one(value: Decimal) -> Decimal { assert!(value >= Decimal::one()); let value_uint128 = value * DECIMAL_FRACTIONAL; - let uint128_sub_one = (value_uint128 - DECIMAL_FRACTIONAL).unwrap(); + let uint128_sub_one = value_uint128.checked_sub(DECIMAL_FRACTIONAL).unwrap(); Decimal::from_ratio(uint128_sub_one, DECIMAL_FRACTIONAL) } diff --git a/contracts/mixnet/src/lib.rs b/contracts/mixnet/src/lib.rs index 92c4113eeb..b9ebdc473a 100644 --- a/contracts/mixnet/src/lib.rs +++ b/contracts/mixnet/src/lib.rs @@ -7,6 +7,3 @@ pub mod state; pub(crate) mod storage; pub mod support; pub mod transactions; - -#[cfg(target_arch = "wasm32")] -cosmwasm_std::create_entry_points_with_migration!(contract); diff --git a/contracts/mixnet/src/msg.rs b/contracts/mixnet/src/msg.rs index 51bfb18690..772b4e9d42 100644 --- a/contracts/mixnet/src/msg.rs +++ b/contracts/mixnet/src/msg.rs @@ -1,15 +1,14 @@ use crate::state::StateParams; -use cosmwasm_std::HumanAddr; use mixnet_contract::{Gateway, MixNode}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InitMsg {} +pub struct InstantiateMsg {} #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -pub enum HandleMsg { +pub enum ExecuteMsg { BondMixnode { mix_node: MixNode, }, @@ -21,13 +20,13 @@ pub enum HandleMsg { UpdateStateParams(StateParams), RewardMixnode { - owner: HumanAddr, + owner: String, // percentage value in range 0-100 uptime: u32, }, RewardGateway { - owner: HumanAddr, + owner: String, // percentage value in range 0-100 uptime: u32, }, @@ -38,17 +37,17 @@ pub enum HandleMsg { pub enum QueryMsg { GetMixNodes { limit: Option, - start_after: Option, + start_after: Option, }, GetGateways { - start_after: Option, + start_after: Option, limit: Option, }, OwnsMixnode { - address: HumanAddr, + address: String, }, OwnsGateway { - address: HumanAddr, + address: String, }, StateParams {}, } diff --git a/contracts/mixnet/src/queries.rs b/contracts/mixnet/src/queries.rs index 996c59cb8c..a5b5e8e604 100644 --- a/contracts/mixnet/src/queries.rs +++ b/contracts/mixnet/src/queries.rs @@ -1,7 +1,6 @@ use crate::state::StateParams; use crate::storage::{gateways_read, mixnodes_read, read_state_params}; use cosmwasm_std::Deps; -use cosmwasm_std::HumanAddr; use cosmwasm_std::Order; use cosmwasm_std::StdResult; use mixnet_contract::{ @@ -14,11 +13,24 @@ const DEFAULT_LIMIT: u32 = 50; pub fn query_mixnodes_paged( deps: Deps, - start_after: Option, + start_after: Option, limit: Option, ) -> StdResult { + let input_cline = start_after.clone(); + let start_after_addr = start_after + .map(|start_after| deps.api.addr_validate(&start_after)) // try to validate address + .map_or(Ok(None), |start_after| start_after.map(Some)); // move result in front of the option + + let start_after_addr = match start_after_addr { + Ok(a) => a, + Err(err) => { + println!("{:?} is not a valid address", input_cline); + return Err(err); + } + }; + let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize; - let start = calculate_start_value(start_after); + let start = calculate_start_value(start_after_addr); let nodes = mixnodes_read(deps.storage) .range(start.as_deref(), None, Order::Ascending) @@ -33,11 +45,15 @@ pub fn query_mixnodes_paged( pub(crate) fn query_gateways_paged( deps: Deps, - start_after: Option, + start_after: Option, limit: Option, ) -> StdResult { + let start_after_addr = start_after + .map(|start_after| deps.api.addr_validate(&start_after)) // try to validate address + .map_or(Ok(None), |start_after| start_after.map(Some))?; // move result in front of the option + let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize; - let start = calculate_start_value(start_after); + let start = calculate_start_value(start_after_addr); let nodes = gateways_read(deps.storage) .range(start.as_deref(), None, Order::Ascending) @@ -50,25 +66,29 @@ pub(crate) fn query_gateways_paged( Ok(PagedGatewayResponse::new(nodes, limit, start_next_after)) } -pub(crate) fn query_owns_mixnode( - deps: Deps, - address: HumanAddr, -) -> StdResult { +pub(crate) fn query_owns_mixnode(deps: Deps, address: String) -> StdResult { + let validated_address = deps.api.addr_validate(&address)?; + let has_node = mixnodes_read(deps.storage) - .may_load(address.as_ref())? + .may_load(validated_address.as_str().as_bytes())? .is_some(); - Ok(MixOwnershipResponse { address, has_node }) + Ok(MixOwnershipResponse { + address: validated_address, + has_node, + }) } pub(crate) fn query_owns_gateway( deps: Deps, - address: HumanAddr, + address: String, ) -> StdResult { + let validated_address = deps.api.addr_validate(&address)?; + let has_gateway = gateways_read(deps.storage) - .may_load(address.as_ref())? + .may_load(validated_address.as_str().as_bytes())? .is_some(); Ok(GatewayOwnershipResponse { - address, + address: validated_address, has_gateway, }) } @@ -79,11 +99,9 @@ pub(crate) fn query_state_params(deps: Deps) -> StateParams { /// Adds a 0 byte to terminate the `start_after` value given. This allows CosmWasm /// to get the succeeding key as the start of the next page. -fn calculate_start_value( - start_after: std::option::Option, -) -> Option> { +fn calculate_start_value(start_after: std::option::Option) -> Option> { start_after.as_ref().map(|addr| { - let mut bytes = addr.as_bytes().to_owned(); + let mut bytes = addr.as_str().as_bytes().to_owned(); bytes.push(0); bytes }) @@ -95,7 +113,7 @@ mod tests { use crate::state::State; use crate::storage::{config, gateways, mixnodes}; use crate::support::tests::helpers; - use cosmwasm_std::Storage; + use cosmwasm_std::{Addr, Storage}; #[test] fn mixnodes_empty_on_init() { @@ -157,10 +175,15 @@ mod tests { #[test] fn pagination_works() { + let addr1 = "hal100"; + let addr2 = "hal101"; + let addr3 = "hal102"; + let addr4 = "hal103"; + let mut deps = helpers::init_contract(); let node = helpers::mixnode_bond_fixture(); mixnodes(&mut deps.storage) - .save("1".as_bytes(), &node) + .save(addr1.as_bytes(), &node) .unwrap(); let per_page = 2; @@ -171,7 +194,7 @@ mod tests { // save another mixnodes(&mut deps.storage) - .save("2".as_bytes(), &node) + .save(addr2.as_bytes(), &node) .unwrap(); // page1 should have 2 results on it @@ -179,7 +202,7 @@ mod tests { assert_eq!(2, page1.nodes.len()); mixnodes(&mut deps.storage) - .save("3".as_bytes(), &node) + .save(addr3.as_bytes(), &node) .unwrap(); // page1 still has 2 results @@ -187,7 +210,7 @@ mod tests { assert_eq!(2, page1.nodes.len()); // retrieving the next page should start after the last key on this page - let start_after = HumanAddr::from("2"); + let start_after = String::from(addr2); let page2 = query_mixnodes_paged( deps.as_ref(), Option::from(start_after), @@ -199,10 +222,10 @@ mod tests { // save another one mixnodes(&mut deps.storage) - .save("4".as_bytes(), &node) + .save(addr4.as_bytes(), &node) .unwrap(); - let start_after = HumanAddr::from("2"); + let start_after = String::from(addr2); let page2 = query_mixnodes_paged( deps.as_ref(), Option::from(start_after), @@ -269,10 +292,15 @@ mod tests { #[test] fn gateway_pagination_works() { + let addr1 = "hal100"; + let addr2 = "hal101"; + let addr3 = "hal102"; + let addr4 = "hal103"; + let mut deps = helpers::init_contract(); let node = helpers::gateway_bond_fixture(); gateways(&mut deps.storage) - .save("1".as_bytes(), &node) + .save(addr1.as_bytes(), &node) .unwrap(); let per_page = 2; @@ -283,7 +311,7 @@ mod tests { // save another gateways(&mut deps.storage) - .save("2".as_bytes(), &node) + .save(addr2.as_bytes(), &node) .unwrap(); // page1 should have 2 results on it @@ -291,7 +319,7 @@ mod tests { assert_eq!(2, page1.nodes.len()); gateways(&mut deps.storage) - .save("3".as_bytes(), &node) + .save(addr3.as_bytes(), &node) .unwrap(); // page1 still has 2 results @@ -299,7 +327,7 @@ mod tests { assert_eq!(2, page1.nodes.len()); // retrieving the next page should start after the last key on this page - let start_after = HumanAddr::from("2"); + let start_after = String::from(addr2); let page2 = query_gateways_paged( deps.as_ref(), Option::from(start_after), @@ -311,10 +339,10 @@ mod tests { // save another one gateways(&mut deps.storage) - .save("4".as_bytes(), &node) + .save(addr4.as_bytes(), &node) .unwrap(); - let start_after = HumanAddr::from("2"); + let start_after = String::from(addr2); let page2 = query_gateways_paged( deps.as_ref(), Option::from(start_after), @@ -395,8 +423,8 @@ mod tests { let mut deps = helpers::init_contract(); let dummy_state = State { - owner: "someowner".into(), - network_monitor_address: "monitor".into(), + owner: Addr::unchecked("someowner"), + network_monitor_address: Addr::unchecked("monitor"), params: StateParams { epoch_length: 1, minimum_mixnode_bond: 123u128.into(), diff --git a/contracts/mixnet/src/state.rs b/contracts/mixnet/src/state.rs index ece82842d0..90e0124258 100644 --- a/contracts/mixnet/src/state.rs +++ b/contracts/mixnet/src/state.rs @@ -1,11 +1,11 @@ -use cosmwasm_std::{Decimal, HumanAddr, Uint128}; +use cosmwasm_std::{Addr, Decimal, Uint128}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct State { - pub owner: HumanAddr, // only the owner account can update state - pub network_monitor_address: HumanAddr, + pub owner: Addr, // only the owner account can update state + pub network_monitor_address: Addr, pub params: StateParams, // helper values to avoid having to recalculate them on every single payment operation diff --git a/contracts/mixnet/src/storage.rs b/contracts/mixnet/src/storage.rs index f35f3e8df2..f5dace120b 100644 --- a/contracts/mixnet/src/storage.rs +++ b/contracts/mixnet/src/storage.rs @@ -1,5 +1,5 @@ use crate::state::{State, StateParams}; -use cosmwasm_std::{Decimal, HumanAddr, StdError, StdResult, Storage}; +use cosmwasm_std::{Addr, Decimal, StdError, StdResult, Storage}; use cosmwasm_storage::{ bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton, Singleton, @@ -53,11 +53,11 @@ pub fn mixnodes_read(storage: &dyn Storage) -> ReadonlyBucket { const PREFIX_MIXNODES_OWNERS: &[u8] = b"mix-owners"; -pub fn mixnodes_owners(storage: &mut dyn Storage) -> Bucket { +pub fn mixnodes_owners(storage: &mut dyn Storage) -> Bucket { bucket(storage, PREFIX_MIXNODES_OWNERS) } -pub fn mixnodes_owners_read(storage: &dyn Storage) -> ReadonlyBucket { +pub fn mixnodes_owners_read(storage: &dyn Storage) -> ReadonlyBucket { bucket_read(storage, PREFIX_MIXNODES_OWNERS) } @@ -110,11 +110,11 @@ pub fn gateways_read(storage: &dyn Storage) -> ReadonlyBucket { const PREFIX_GATEWAYS_OWNERS: &[u8] = b"gateway-owners"; -pub fn gateways_owners(storage: &mut dyn Storage) -> Bucket { +pub fn gateways_owners(storage: &mut dyn Storage) -> Bucket { bucket(storage, PREFIX_GATEWAYS_OWNERS) } -pub fn gateways_owners_read(storage: &dyn Storage) -> ReadonlyBucket { +pub fn gateways_owners_read(storage: &dyn Storage) -> ReadonlyBucket { bucket_read(storage, PREFIX_GATEWAYS_OWNERS) } @@ -204,7 +204,7 @@ mod tests { // increases the reward appropriately if node exists let mixnode_bond = MixNodeBond { amount: coins(1000, DENOM), - owner: std::str::from_utf8(node_owner).unwrap().into(), + owner: Addr::unchecked(std::str::from_utf8(node_owner).unwrap()), mix_node: mix_node_fixture(), }; @@ -231,7 +231,7 @@ mod tests { let mixnode_bond = MixNodeBond { amount: coins(bond_value, DENOM), - owner: std::str::from_utf8(node_owner).unwrap().into(), + owner: Addr::unchecked(std::str::from_utf8(node_owner).unwrap()), mix_node: mix_node_fixture(), }; @@ -259,7 +259,7 @@ mod tests { // increases the reward appropriately if node exists let gateway_bond = GatewayBond { amount: coins(1000, DENOM), - owner: std::str::from_utf8(node_owner).unwrap().into(), + owner: Addr::unchecked(std::str::from_utf8(node_owner).unwrap()), gateway: gateway_fixture(), }; @@ -286,7 +286,7 @@ mod tests { let gateway_bond = GatewayBond { amount: coins(1000, DENOM), - owner: std::str::from_utf8(node_owner).unwrap().into(), + owner: Addr::unchecked(std::str::from_utf8(node_owner).unwrap()), gateway: gateway_fixture(), }; diff --git a/contracts/mixnet/src/support/tests.rs b/contracts/mixnet/src/support/tests.rs index af36f071e4..0a09fce08b 100644 --- a/contracts/mixnet/src/support/tests.rs +++ b/contracts/mixnet/src/support/tests.rs @@ -1,10 +1,10 @@ #[cfg(test)] pub mod helpers { use super::*; - use crate::contract::init; + use crate::contract::instantiate; use crate::contract::query; use crate::contract::DENOM; - use crate::msg::InitMsg; + use crate::msg::InstantiateMsg; use crate::msg::QueryMsg; use crate::transactions::{try_add_gateway, try_add_mixnode}; use cosmwasm_std::coins; @@ -15,8 +15,8 @@ pub mod helpers { use cosmwasm_std::testing::MockApi; use cosmwasm_std::testing::MockQuerier; use cosmwasm_std::testing::MockStorage; + use cosmwasm_std::Addr; use cosmwasm_std::Coin; - use cosmwasm_std::HumanAddr; use cosmwasm_std::OwnedDeps; use cosmwasm_std::{Empty, MemoryStorage}; use mixnet_contract::{ @@ -93,10 +93,10 @@ pub mod helpers { pub fn init_contract() -> OwnedDeps> { let mut deps = mock_dependencies(&[]); - let msg = InitMsg {}; + let msg = InstantiateMsg {}; let env = mock_env(); let info = mock_info("creator", &[]); - init(deps.as_mut(), env.clone(), info, msg).unwrap(); + instantiate(deps.as_mut(), env.clone(), info, msg).unwrap(); return deps; } @@ -120,7 +120,7 @@ pub mod helpers { "aaaa".to_string(), "0.10.0".to_string(), ); - MixNodeBond::new(coins(50, DENOM), HumanAddr::from("foo"), mix_node) + MixNodeBond::new(coins(50, DENOM), Addr::unchecked("foo"), mix_node) } pub fn gateway_fixture() -> Gateway { @@ -143,11 +143,11 @@ pub mod helpers { "identity".to_string(), "0.10.0".to_string(), ); - GatewayBond::new(coins(50, DENOM), HumanAddr::from("foo"), gateway) + GatewayBond::new(coins(50, DENOM), Addr::unchecked("foo"), gateway) } pub fn query_contract_balance( - address: HumanAddr, + address: Addr, deps: OwnedDeps, ) -> Vec { let querier = deps.as_ref().querier; diff --git a/contracts/mixnet/src/transactions.rs b/contracts/mixnet/src/transactions.rs index 4900702df2..ac7676841c 100644 --- a/contracts/mixnet/src/transactions.rs +++ b/contracts/mixnet/src/transactions.rs @@ -8,9 +8,7 @@ use crate::storage::{ mixnodes_read, read_gateway_epoch_reward_rate, read_mixnode_epoch_reward_rate, read_state_params, }; -use cosmwasm_std::{ - attr, BankMsg, Coin, Decimal, DepsMut, Env, HandleResponse, HumanAddr, MessageInfo, Uint128, -}; +use cosmwasm_std::{attr, BankMsg, Coin, Decimal, DepsMut, MessageInfo, Response, Uint128}; use mixnet_contract::{Gateway, GatewayBond, MixNode, MixNodeBond}; fn validate_mixnode_bond(bond: &[Coin], minimum_bond: Uint128) -> Result<(), ContractError> { @@ -43,17 +41,17 @@ pub(crate) fn try_add_mixnode( deps: DepsMut, info: MessageInfo, mix_node: MixNode, -) -> Result { +) -> Result { // if the client has an active bonded gateway, don't allow mixnode bonding if gateways_read(deps.storage) - .may_load(info.sender.as_ref())? + .may_load(info.sender.as_str().as_bytes())? .is_some() { return Err(ContractError::AlreadyOwnsGateway); } let minimum_bond = read_state_params(deps.storage).minimum_mixnode_bond; - validate_mixnode_bond(&info.sent_funds, minimum_bond)?; + validate_mixnode_bond(&info.funds, minimum_bond)?; // check if this node wasn't already claimed by somebody else let mut was_present = false; @@ -68,9 +66,9 @@ pub(crate) fn try_add_mixnode( was_present = true } - let bond = MixNodeBond::new(info.sent_funds, info.sender.clone(), mix_node); + let bond = MixNodeBond::new(info.funds, info.sender.clone(), mix_node); - let sender_bytes = info.sender.as_bytes(); + let sender_bytes = info.sender.as_str().as_bytes(); let attributes = vec![attr("overwritten", was_present)]; // TODO: now this can be potentially problematic. What if the first call doesn't fail but the second one does? @@ -78,8 +76,9 @@ pub(crate) fn try_add_mixnode( mixnodes(deps.storage).save(sender_bytes, &bond)?; mixnodes_owners(deps.storage).save(bond.mix_node.identity_key.as_bytes(), &info.sender)?; - Ok(HandleResponse { - messages: vec![], + Ok(Response { + submessages: Vec::new(), + messages: Vec::new(), attributes, data: None, }) @@ -88,30 +87,31 @@ pub(crate) fn try_add_mixnode( pub(crate) fn try_remove_mixnode( deps: DepsMut, info: MessageInfo, - env: Env, -) -> Result { +) -> Result { + let sender_bytes = info.sender.as_str().as_bytes(); + // find the bond, return ContractError::MixNodeBondNotFound if it doesn't exist let mixnode_bond = mixnodes_read(deps.storage) - .may_load(info.sender.as_bytes())? + .may_load(sender_bytes)? .ok_or(ContractError::MixNodeBondNotFound {})?; // send bonded funds back to the bond owner let messages = vec![BankMsg::Send { - from_address: env.contract.address, - to_address: info.sender.clone(), + to_address: info.sender.as_str().to_owned(), amount: mixnode_bond.amount().to_vec(), } .into()]; // remove the bond from the list of bonded mixnodes - mixnodes(deps.storage).remove(info.sender.as_bytes()); + mixnodes(deps.storage).remove(sender_bytes); // remove the node ownership mixnodes_owners(deps.storage).remove(mixnode_bond.mix_node.identity_key.as_bytes()); // log our actions let attributes = vec![attr("action", "unbond"), attr("mixnode_bond", mixnode_bond)]; - Ok(HandleResponse { + Ok(Response { + submessages: Vec::new(), messages, attributes, data: None, @@ -148,17 +148,17 @@ pub(crate) fn try_add_gateway( deps: DepsMut, info: MessageInfo, gateway: Gateway, -) -> Result { +) -> Result { // if the client has an active bonded mixnode, don't allow gateway bonding if mixnodes_read(deps.storage) - .may_load(info.sender.as_ref())? + .may_load(info.sender.as_str().as_bytes())? .is_some() { return Err(ContractError::AlreadyOwnsMixnode); } let minimum_bond = read_state_params(deps.storage).minimum_gateway_bond; - validate_gateway_bond(&info.sent_funds, minimum_bond)?; + validate_gateway_bond(&info.funds, minimum_bond)?; // check if this node wasn't already claimed by somebody else let mut was_present = false; @@ -173,9 +173,9 @@ pub(crate) fn try_add_gateway( was_present = true; } - let bond = GatewayBond::new(info.sent_funds, info.sender.clone(), gateway); + let bond = GatewayBond::new(info.funds, info.sender.clone(), gateway); - let sender_bytes = info.sender.as_bytes(); + let sender_bytes = info.sender.as_str().as_bytes(); let attributes = vec![attr("overwritten", was_present)]; // TODO: now this can be potentially problematic. What if the first call doesn't fail but the second one does? @@ -183,8 +183,9 @@ pub(crate) fn try_add_gateway( gateways(deps.storage).save(sender_bytes, &bond)?; gateways_owners(deps.storage).save(bond.gateway.identity_key.as_bytes(), &info.sender)?; - Ok(HandleResponse { - messages: vec![], + Ok(Response { + submessages: Vec::new(), + messages: Vec::new(), attributes, data: None, }) @@ -193,9 +194,8 @@ pub(crate) fn try_add_gateway( pub(crate) fn try_remove_gateway( deps: DepsMut, info: MessageInfo, - env: Env, -) -> Result { - let sender_bytes = info.sender.as_bytes(); +) -> Result { + let sender_bytes = info.sender.as_str().as_bytes(); // find the bond, return ContractError::GatewayBondNotFound if it doesn't exist let gateway_bond = match gateways_read(deps.storage).may_load(sender_bytes)? { @@ -209,8 +209,7 @@ pub(crate) fn try_remove_gateway( // send bonded funds back to the bond owner let messages = vec![BankMsg::Send { - from_address: env.contract.address, - to_address: info.sender.clone(), + to_address: info.sender.as_str().to_owned(), amount: gateway_bond.amount().to_vec(), } .into()]; @@ -227,7 +226,8 @@ pub(crate) fn try_remove_gateway( attr("gateway_bond", gateway_bond), ]; - Ok(HandleResponse { + Ok(Response { + submessages: Vec::new(), messages, attributes, data: None, @@ -238,7 +238,7 @@ pub(crate) fn try_update_state_params( deps: DepsMut, info: MessageInfo, params: StateParams, -) -> Result { +) -> Result { // note: In any other case, I wouldn't have attempted to unwrap this result, but in here // if we fail to load the stored state we would already be in the undefined behaviour land, // so we better just blow up immediately. @@ -279,36 +279,43 @@ pub(crate) fn try_update_state_params( config(deps.storage).save(&state)?; - Ok(HandleResponse::default()) + Ok(Response::default()) } pub(crate) fn try_reward_mixnode( deps: DepsMut, info: MessageInfo, - node_owner: HumanAddr, + node_owner: String, uptime: u32, -) -> Result { +) -> Result { let state = config_read(deps.storage).load().unwrap(); // check if this is executed by the monitor, if not reject the transaction if info.sender != state.network_monitor_address { return Err(ContractError::Unauthorized); } + // in theory network monitor should never send untrusted data, but validating it regardless + // wouldn't hurt... + let validated_address = deps.api.addr_validate(&node_owner)?; let reward = read_mixnode_epoch_reward_rate(deps.storage); let scaled_reward = scale_reward_by_uptime(reward, uptime)?; - increase_mixnode_bond(deps.storage, node_owner.as_bytes(), scaled_reward)?; + increase_mixnode_bond( + deps.storage, + validated_address.as_str().as_bytes(), + scaled_reward, + )?; - Ok(HandleResponse::default()) + Ok(Response::default()) } pub(crate) fn try_reward_gateway( deps: DepsMut, info: MessageInfo, - gateway_owner: HumanAddr, + gateway_owner: String, uptime: u32, -) -> Result { +) -> Result { let state = config_read(deps.storage).load().unwrap(); // check if this is executed by the owner, if not reject the transaction @@ -316,29 +323,37 @@ pub(crate) fn try_reward_gateway( return Err(ContractError::Unauthorized); } + // in theory network monitor should never send untrusted data, but validating it regardless + // wouldn't hurt... + let validated_address = deps.api.addr_validate(&gateway_owner)?; + let reward = read_gateway_epoch_reward_rate(deps.storage); let scaled_reward = scale_reward_by_uptime(reward, uptime)?; - increase_gateway_bond(deps.storage, gateway_owner.as_bytes(), scaled_reward)?; + increase_gateway_bond( + deps.storage, + validated_address.as_str().as_bytes(), + scaled_reward, + )?; - Ok(HandleResponse::default()) + Ok(Response::default()) } #[cfg(test)] pub mod tests { use super::*; use crate::contract::{ - handle, init, query, INITIAL_DEFAULT_EPOCH_LENGTH, INITIAL_GATEWAY_BOND, + execute, instantiate, query, INITIAL_DEFAULT_EPOCH_LENGTH, INITIAL_GATEWAY_BOND, INITIAL_GATEWAY_BOND_REWARD_RATE, INITIAL_MIXNODE_BOND, INITIAL_MIXNODE_BOND_REWARD_RATE, }; use crate::helpers::calculate_epoch_reward_rate; - use crate::msg::{HandleMsg, InitMsg, QueryMsg}; + use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; use crate::state::StateParams; use crate::storage::{read_gateway_bond, read_gateway_epoch_reward_rate, read_mixnode_bond}; use crate::support::tests::helpers; use crate::support::tests::helpers::{gateway_fixture, mix_node_fixture}; use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; - use cosmwasm_std::{coins, from_binary, Uint128}; + use cosmwasm_std::{coins, from_binary, Addr, Uint128}; use mixnet_contract::{PagedGatewayResponse, PagedResponse}; fn good_mixnode_bond() -> Vec { @@ -356,7 +371,7 @@ pub mod tests { // you must send at least 100 coins... let mut bond = good_mixnode_bond(); - bond[0].amount = (INITIAL_MIXNODE_BOND - Uint128(1)).unwrap(); + bond[0].amount = INITIAL_MIXNODE_BOND.checked_sub(Uint128(1)).unwrap(); let result = validate_mixnode_bond(&bond, INITIAL_MIXNODE_BOND); assert_eq!( result, @@ -391,12 +406,12 @@ pub mod tests { // if we don't send enough funds let insufficient_bond = Into::::into(INITIAL_MIXNODE_BOND) - 1; let info = mock_info("anyone", &coins(insufficient_bond, DENOM)); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: helpers::mix_node_fixture(), }; // we are informed that we didn't send enough funds - let result = handle(deps.as_mut(), mock_env(), info, msg); + let result = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!( result, Err(ContractError::InsufficientMixNodeBond { @@ -420,7 +435,7 @@ pub mod tests { // if we send enough funds let info = mock_info("anyone", &coins(1000_000000, DENOM)); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "anyonesmixnode".into(), ..helpers::mix_node_fixture() @@ -428,7 +443,7 @@ pub mod tests { }; // we get back a message telling us everything was OK - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert!(handle_response.is_ok()); // we can query topology and the new node is there @@ -453,18 +468,18 @@ pub mod tests { // if there was already a mixnode bonded by particular user let info = mock_info("foomper", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "foompermixnode".into(), ..helpers::mix_node_fixture() }, }; - let handle_response = handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); assert_eq!(handle_response.attributes[0], attr("overwritten", false)); let info = mock_info("foomper", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "foompermixnode".into(), ..helpers::mix_node_fixture() @@ -472,33 +487,33 @@ pub mod tests { }; // we get a log message about it (TODO: does it get back to the user?) - let handle_response = handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); assert_eq!(handle_response.attributes[0], attr("overwritten", true)); // bonding fails if the user already owns a gateway let info = mock_info("gateway-owner", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: helpers::gateway_fixture(), }; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); let info = mock_info("gateway-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: helpers::mix_node_fixture(), }; - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!(handle_response, Err(ContractError::AlreadyOwnsGateway)); // but after he unbonds it, it's all fine again let info = mock_info("gateway-owner", &[]); - let msg = HandleMsg::UnbondGateway {}; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + let msg = ExecuteMsg::UnbondGateway {}; + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); let info = mock_info("gateway-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: helpers::mix_node_fixture(), }; - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert!(handle_response.is_ok()); // adding another node from another account, but with the same IP, should fail (or we would have a weird state). Is that right? Think about this, not sure yet. @@ -510,7 +525,7 @@ pub mod tests { let mut deps = helpers::init_contract(); let info = mock_info("mix-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "myAwesomeMixnode".to_string(), ..helpers::mix_node_fixture() @@ -524,11 +539,11 @@ pub mod tests { .is_none()); // it's all fine, owner is saved - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert!(handle_response.is_ok()); assert_eq!( - HumanAddr::from("mix-owner"), + Addr::unchecked("mix-owner"), mixnodes_owners_read(deps.as_ref().storage) .load("myAwesomeMixnode".as_bytes()) .unwrap() @@ -540,35 +555,35 @@ pub mod tests { let mut deps = helpers::init_contract(); let info = mock_info("mix-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "myAwesomeMixnode".to_string(), ..helpers::mix_node_fixture() }, }; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); // request fails giving the existing owner address in the message let info = mock_info("mix-owner-pretender", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "myAwesomeMixnode".to_string(), ..helpers::mix_node_fixture() }, }; - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!( Err(ContractError::DuplicateMixnode { - owner: "mix-owner".into() + owner: Addr::unchecked("mix-owner") }), handle_response ); // owner is not changed assert_eq!( - HumanAddr::from("mix-owner"), + Addr::unchecked("mix-owner"), mixnodes_owners_read(deps.as_ref().storage) .load("myAwesomeMixnode".as_bytes()) .unwrap() @@ -580,7 +595,7 @@ pub mod tests { let mut deps = helpers::init_contract(); let info = mock_info("mix-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "myAwesomeMixnode".to_string(), host: "1.1.1.1:1789".into(), @@ -588,10 +603,10 @@ pub mod tests { }, }; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); let info = mock_info("mix-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "myAwesomeMixnode".to_string(), host: "2.2.2.2:1789".into(), @@ -599,7 +614,7 @@ pub mod tests { }, }; - assert!(handle(deps.as_mut(), mock_env(), info, msg).is_ok()); + assert!(execute(deps.as_mut(), mock_env(), info, msg).is_ok()); // make sure the host information was updated assert_eq!( @@ -613,7 +628,7 @@ pub mod tests { // and nothing was changed regarding ownership assert_eq!( - HumanAddr::from("mix-owner"), + Addr::unchecked("mix-owner"), mixnodes_owners_read(deps.as_ref().storage) .load("myAwesomeMixnode".as_bytes()) .unwrap() @@ -624,14 +639,14 @@ pub mod tests { fn mixnode_remove() { let env = mock_env(); let mut deps = mock_dependencies(&[]); - let msg = InitMsg {}; + let msg = InstantiateMsg {}; let info = mock_info("creator", &[]); - init(deps.as_mut(), env.clone(), info, msg).unwrap(); + instantiate(deps.as_mut(), env.clone(), info, msg).unwrap(); // try un-registering when no nodes exist yet let info = mock_info("anyone", &coins(999_9999, DENOM)); - let msg = HandleMsg::UnbondMixnode {}; - let result = handle(deps.as_mut(), mock_env(), info, msg); + let msg = ExecuteMsg::UnbondMixnode {}; + let result = execute(deps.as_mut(), mock_env(), info, msg); // we're told that there is no node for our address assert_eq!(result, Err(ContractError::MixNodeBondNotFound {})); @@ -641,8 +656,8 @@ pub mod tests { // attempt to un-register fred's node, which doesn't exist let info = mock_info("fred", &coins(999_9999, DENOM)); - let msg = HandleMsg::UnbondMixnode {}; - let result = handle(deps.as_mut(), mock_env(), info, msg); + let msg = ExecuteMsg::UnbondMixnode {}; + let result = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!(result, Err(ContractError::MixNodeBondNotFound {})); // bob's node is still there @@ -658,7 +673,7 @@ pub mod tests { let page: PagedResponse = from_binary(&res).unwrap(); let first_node = &page.nodes[0]; assert_eq!(1, page.nodes.len()); - assert_eq!("bob", first_node.owner()); + assert_eq!(&Addr::unchecked("bob"), first_node.owner()); // add a node owned by fred let fred_bond = good_mixnode_bond(); @@ -669,8 +684,8 @@ pub mod tests { // un-register fred's node let info = mock_info("fred", &coins(999_9999, DENOM)); - let msg = HandleMsg::UnbondMixnode {}; - let remove_fred = handle(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); + let msg = ExecuteMsg::UnbondMixnode {}; + let remove_fred = execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); // we should see log messages come back showing an unbond message let expected_attributes = vec![ @@ -683,14 +698,14 @@ pub mod tests { // we should see a funds transfer from the contract back to fred let expected_messages = vec![BankMsg::Send { - from_address: env.contract.address, - to_address: info.sender, + to_address: info.sender.as_str().to_owned(), amount: fred_bond, } .into()]; // run the handler and check that we got back the correct results - let expected = HandleResponse { + let expected = Response { + submessages: Vec::new(), messages: expected_messages, attributes: expected_attributes, data: None, @@ -700,7 +715,7 @@ pub mod tests { // only 1 node now exists, owned by bob: let mix_node_bonds = helpers::get_mix_nodes(&mut deps); assert_eq!(1, mix_node_bonds.len()); - assert_eq!("bob", mix_node_bonds[0].owner()); + assert_eq!(&Addr::unchecked("bob"), mix_node_bonds[0].owner()); } #[test] @@ -708,25 +723,25 @@ pub mod tests { let mut deps = helpers::init_contract(); let info = mock_info("mix-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "myAwesomeMixnode".to_string(), ..helpers::mix_node_fixture() }, }; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); assert_eq!( - HumanAddr::from("mix-owner"), + Addr::unchecked("mix-owner"), mixnodes_owners_read(deps.as_ref().storage) .load("myAwesomeMixnode".as_bytes()) .unwrap() ); let info = mock_info("mix-owner", &[]); - let msg = HandleMsg::UnbondMixnode {}; + let msg = ExecuteMsg::UnbondMixnode {}; - assert!(handle(deps.as_mut(), mock_env(), info, msg).is_ok()); + assert!(execute(deps.as_mut(), mock_env(), info, msg).is_ok()); assert!(mixnodes_owners_read(deps.as_ref().storage) .may_load("myAwesomeMixnode".as_bytes()) @@ -735,16 +750,16 @@ pub mod tests { // and since it's removed, it can be reclaimed let info = mock_info("mix-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: MixNode { identity_key: "myAwesomeMixnode".to_string(), ..helpers::mix_node_fixture() }, }; - assert!(handle(deps.as_mut(), mock_env(), info, msg).is_ok()); + assert!(execute(deps.as_mut(), mock_env(), info, msg).is_ok()); assert_eq!( - HumanAddr::from("mix-owner"), + Addr::unchecked("mix-owner"), mixnodes_owners_read(deps.as_ref().storage) .load("myAwesomeMixnode".as_bytes()) .unwrap() @@ -766,7 +781,7 @@ pub mod tests { // you must send at least 100 coins... let mut bond = good_gateway_bond(); - bond[0].amount = (INITIAL_GATEWAY_BOND - Uint128(1)).unwrap(); + bond[0].amount = INITIAL_GATEWAY_BOND.checked_sub(Uint128(1)).unwrap(); let result = validate_gateway_bond(&bond, INITIAL_GATEWAY_BOND); assert_eq!( result, @@ -801,12 +816,12 @@ pub mod tests { // if we fail validation (by say not sending enough funds let insufficient_bond = Into::::into(INITIAL_GATEWAY_BOND) - 1; let info = mock_info("anyone", &coins(insufficient_bond, DENOM)); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: helpers::gateway_fixture(), }; // we are informed that we didn't send enough funds - let result = handle(deps.as_mut(), mock_env(), info, msg); + let result = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!( result, Err(ContractError::InsufficientGatewayBond { @@ -830,7 +845,7 @@ pub mod tests { // if we send enough funds let info = mock_info("anyone", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "anyonesgateway".into(), ..helpers::gateway_fixture() @@ -838,7 +853,7 @@ pub mod tests { }; // we get back a message telling us everything was OK - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert!(handle_response.is_ok()); // we can query topology and the new node is there @@ -863,18 +878,18 @@ pub mod tests { // if there was already a gateway bonded by particular user let info = mock_info("foomper", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "foompersgateway".into(), ..helpers::gateway_fixture() }, }; - let handle_response = handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); assert_eq!(handle_response.attributes[0], attr("overwritten", false)); let info = mock_info("foomper", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "foompersgateway".into(), ..helpers::gateway_fixture() @@ -882,33 +897,33 @@ pub mod tests { }; // we get a log message about it (TODO: does it get back to the user?) - let handle_response = handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); assert_eq!(handle_response.attributes[0], attr("overwritten", true)); // bonding fails if the user already owns a mixnode let info = mock_info("mixnode-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondMixnode { + let msg = ExecuteMsg::BondMixnode { mix_node: helpers::mix_node_fixture(), }; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); let info = mock_info("mixnode-owner", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: helpers::gateway_fixture(), }; - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!(handle_response, Err(ContractError::AlreadyOwnsMixnode)); // but after he unbonds it, it's all fine again let info = mock_info("mixnode-owner", &[]); - let msg = HandleMsg::UnbondMixnode {}; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + let msg = ExecuteMsg::UnbondMixnode {}; + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); let info = mock_info("mixnode-owner", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: helpers::gateway_fixture(), }; - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert!(handle_response.is_ok()); // adding another node from another account, but with the same IP, should fail (or we would have a weird state). @@ -920,7 +935,7 @@ pub mod tests { let mut deps = helpers::init_contract(); let info = mock_info("gateway-owner", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), ..helpers::gateway_fixture() @@ -934,11 +949,11 @@ pub mod tests { .is_none()); // it's all fine, owner is saved - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert!(handle_response.is_ok()); assert_eq!( - HumanAddr::from("gateway-owner"), + Addr::unchecked("gateway-owner"), gateways_owners_read(deps.as_ref().storage) .load("myAwesomeGateway".as_bytes()) .unwrap() @@ -950,35 +965,35 @@ pub mod tests { let mut deps = helpers::init_contract(); let info = mock_info("gateway-owner", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), ..helpers::gateway_fixture() }, }; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); // request fails giving the existing owner address in the message let info = mock_info("gateway-owner-pretender", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), ..helpers::gateway_fixture() }, }; - let handle_response = handle(deps.as_mut(), mock_env(), info, msg); + let handle_response = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!( Err(ContractError::DuplicateGateway { - owner: "gateway-owner".into() + owner: Addr::unchecked("gateway-owner") }), handle_response ); // owner is not changed assert_eq!( - HumanAddr::from("gateway-owner"), + Addr::unchecked("gateway-owner"), gateways_owners_read(deps.as_ref().storage) .load("myAwesomeGateway".as_bytes()) .unwrap() @@ -990,7 +1005,7 @@ pub mod tests { let mut deps = helpers::init_contract(); let info = mock_info("gateway-owner", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), mix_host: "1.1.1.1:1789".into(), @@ -998,10 +1013,10 @@ pub mod tests { }, }; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); let info = mock_info("gateway-owner", &good_gateway_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), mix_host: "2.2.2.2:1789".into(), @@ -1009,7 +1024,7 @@ pub mod tests { }, }; - assert!(handle(deps.as_mut(), mock_env(), info, msg).is_ok()); + assert!(execute(deps.as_mut(), mock_env(), info, msg).is_ok()); // make sure the host information was updated assert_eq!( @@ -1023,7 +1038,7 @@ pub mod tests { // and nothing was changed regarding ownership assert_eq!( - HumanAddr::from("gateway-owner"), + Addr::unchecked("gateway-owner"), gateways_owners_read(deps.as_ref().storage) .load("myAwesomeGateway".as_bytes()) .unwrap() @@ -1034,20 +1049,20 @@ pub mod tests { fn gateway_remove() { let env = mock_env(); let mut deps = mock_dependencies(&[]); - let msg = InitMsg {}; + let msg = InstantiateMsg {}; let info = mock_info("creator", &[]); - init(deps.as_mut(), env.clone(), info, msg).unwrap(); + instantiate(deps.as_mut(), env.clone(), info, msg).unwrap(); // try unbond when no nodes exist yet let info = mock_info("anyone", &[]); - let msg = HandleMsg::UnbondGateway {}; - let result = handle(deps.as_mut(), mock_env(), info, msg); + let msg = ExecuteMsg::UnbondGateway {}; + let result = execute(deps.as_mut(), mock_env(), info, msg); // we're told that there is no node for our address assert_eq!( result, Err(ContractError::GatewayBondNotFound { - account: "anyone".into() + account: Addr::unchecked("anyone") }) ); @@ -1056,12 +1071,12 @@ pub mod tests { // attempt to unbond fred's node, which doesn't exist let info = mock_info("fred", &[]); - let msg = HandleMsg::UnbondGateway {}; - let result = handle(deps.as_mut(), mock_env(), info, msg); + let msg = ExecuteMsg::UnbondGateway {}; + let result = execute(deps.as_mut(), mock_env(), info, msg); assert_eq!( result, Err(ContractError::GatewayBondNotFound { - account: "fred".into() + account: Addr::unchecked("fred") }) ); @@ -1070,7 +1085,7 @@ pub mod tests { assert_eq!(1, nodes.len()); let first_node = &nodes[0]; - assert_eq!("bob", first_node.owner()); + assert_eq!(&Addr::unchecked("bob"), first_node.owner()); // add a node owned by fred let fred_bond = good_gateway_bond(); @@ -1081,8 +1096,8 @@ pub mod tests { // unbond fred's node let info = mock_info("fred", &[]); - let msg = HandleMsg::UnbondGateway {}; - let remove_fred = handle(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); + let msg = ExecuteMsg::UnbondGateway {}; + let remove_fred = execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); // we should see log messages come back showing an unbond message let expected_attributes = vec![ @@ -1096,14 +1111,14 @@ pub mod tests { // we should see a funds transfer from the contract back to fred let expected_messages = vec![BankMsg::Send { - from_address: env.contract.address, - to_address: info.sender, + to_address: info.sender.as_str().to_owned(), amount: fred_bond, } .into()]; // run the handler and check that we got back the correct results - let expected = HandleResponse { + let expected = Response { + submessages: Vec::new(), messages: expected_messages, attributes: expected_attributes, data: None, @@ -1113,7 +1128,7 @@ pub mod tests { // only 1 node now exists, owned by bob: let gateway_bonds = helpers::get_gateways(&mut deps); assert_eq!(1, gateway_bonds.len()); - assert_eq!("bob", gateway_bonds[0].owner()); + assert_eq!(&Addr::unchecked("bob"), gateway_bonds[0].owner()); } #[test] @@ -1121,25 +1136,25 @@ pub mod tests { let mut deps = helpers::init_contract(); let info = mock_info("gateway-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), ..helpers::gateway_fixture() }, }; - handle(deps.as_mut(), mock_env(), info, msg).unwrap(); + execute(deps.as_mut(), mock_env(), info, msg).unwrap(); assert_eq!( - HumanAddr::from("gateway-owner"), + Addr::unchecked("gateway-owner"), gateways_owners_read(deps.as_ref().storage) .load("myAwesomeGateway".as_bytes()) .unwrap() ); let info = mock_info("gateway-owner", &[]); - let msg = HandleMsg::UnbondGateway {}; + let msg = ExecuteMsg::UnbondGateway {}; - assert!(handle(deps.as_mut(), mock_env(), info, msg).is_ok()); + assert!(execute(deps.as_mut(), mock_env(), info, msg).is_ok()); assert!(gateways_owners_read(deps.as_ref().storage) .may_load("myAwesomeGateway".as_bytes()) @@ -1148,16 +1163,16 @@ pub mod tests { // and since it's removed, it can be reclaimed let info = mock_info("gateway-owner", &good_mixnode_bond()); - let msg = HandleMsg::BondGateway { + let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), ..helpers::gateway_fixture() }, }; - assert!(handle(deps.as_mut(), mock_env(), info, msg).is_ok()); + assert!(execute(deps.as_mut(), mock_env(), info, msg).is_ok()); assert_eq!( - HumanAddr::from("gateway-owner"), + Addr::unchecked("gateway-owner"), gateways_owners_read(deps.as_ref().storage) .load("myAwesomeGateway".as_bytes()) .unwrap() @@ -1185,7 +1200,7 @@ pub mod tests { // but works fine from the creator account let info = mock_info("creator", &[]); let res = try_update_state_params(deps.as_mut(), info, new_params.clone()); - assert_eq!(res, Ok(HandleResponse::default())); + assert_eq!(res, Ok(Response::default())); // and the state is actually updated let current_state = config_read(deps.as_ref().storage).load().unwrap(); @@ -1289,14 +1304,14 @@ pub mod tests { assert_eq!(res, Err(ContractError::Unauthorized)); // errors out if the target owner hasn't bound any mixnodes - let info = mock_info(network_monitor_address.clone(), &[]); + let info = mock_info(network_monitor_address.as_str(), &[]); let res = try_reward_mixnode(deps.as_mut(), info, "node-owner".into(), 100); assert!(res.is_err()); let initial_bond = 100_000000; let mixnode_bond = MixNodeBond { amount: coins(initial_bond, DENOM), - owner: "node-owner".into(), + owner: Addr::unchecked("node-owner"), mix_node: mix_node_fixture(), }; @@ -1310,7 +1325,7 @@ pub mod tests { // if node was 100% up, it will get full epoch reward let expected_bond = Uint128(initial_bond) * reward + Uint128(initial_bond); - let info = mock_info(network_monitor_address.clone(), &[]); + let info = mock_info(network_monitor_address.as_str(), &[]); try_reward_mixnode(deps.as_mut(), info, "node-owner".into(), 100).unwrap(); assert_eq!( @@ -1322,7 +1337,7 @@ pub mod tests { let scaled_reward = scale_reward_by_uptime(reward, 20).unwrap(); let expected_bond = expected_bond * scaled_reward + expected_bond; - let info = mock_info(network_monitor_address, &[]); + let info = mock_info(network_monitor_address.as_str(), &[]); try_reward_mixnode(deps.as_mut(), info, "node-owner".into(), 20).unwrap(); assert_eq!( @@ -1343,14 +1358,14 @@ pub mod tests { assert_eq!(res, Err(ContractError::Unauthorized)); // errors out if the target owner hasn't bound any mixnodes - let info = mock_info(network_monitor_address.clone(), &[]); + let info = mock_info(network_monitor_address.as_str(), &[]); let res = try_reward_gateway(deps.as_mut(), info, "node-owner".into(), 100); assert!(res.is_err()); let initial_bond = 100_000000; let gateway_bond = GatewayBond { amount: coins(initial_bond, DENOM), - owner: "node-owner".into(), + owner: Addr::unchecked("node-owner"), gateway: gateway_fixture(), }; @@ -1364,7 +1379,7 @@ pub mod tests { // if node was 100% up, it will get full epoch reward let expected_bond = Uint128(initial_bond) * reward + Uint128(initial_bond); - let info = mock_info(network_monitor_address.clone(), &[]); + let info = mock_info(network_monitor_address.as_str(), &[]); try_reward_gateway(deps.as_mut(), info, "node-owner".into(), 100).unwrap(); assert_eq!( @@ -1376,7 +1391,7 @@ pub mod tests { let scaled_reward = scale_reward_by_uptime(reward, 20).unwrap(); let expected_bond = expected_bond * scaled_reward + expected_bond; - let info = mock_info(network_monitor_address, &[]); + let info = mock_info(network_monitor_address.as_str(), &[]); try_reward_gateway(deps.as_mut(), info, "node-owner".into(), 20).unwrap(); assert_eq!( From da339a83cdb4e564b11fa369b2534611b27886b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 27 May 2021 11:29:31 +0100 Subject: [PATCH 02/24] Updated the rest of the codebase --- common/client-libs/validator-client/src/lib.rs | 6 +++--- common/client-libs/validator-client/src/models.rs | 6 +++--- common/topology/src/gateway.rs | 2 +- common/topology/src/mix.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/client-libs/validator-client/src/lib.rs b/common/client-libs/validator-client/src/lib.rs index 4cd2c4b163..08d8845b48 100644 --- a/common/client-libs/validator-client/src/lib.rs +++ b/common/client-libs/validator-client/src/lib.rs @@ -4,7 +4,7 @@ use crate::models::{QueryRequest, QueryResponse}; use crate::ValidatorClientError::ValidatorError; use core::fmt::{self, Display, Formatter}; -use mixnet_contract::{GatewayBond, HumanAddr, MixNodeBond, PagedGatewayResponse, PagedResponse}; +use mixnet_contract::{Addr, GatewayBond, MixNodeBond, PagedGatewayResponse, PagedResponse}; use rand::seq::SliceRandom; use rand::thread_rng; use serde::Deserialize; @@ -175,7 +175,7 @@ impl Client { async fn get_mix_nodes_paged( &mut self, - start_after: Option, + start_after: Option, ) -> Result { let query_content_json = serde_json::to_string(&QueryRequest::GetMixNodes { limit: self.config.mixnode_page_limit, @@ -208,7 +208,7 @@ impl Client { async fn get_gateways_paged( &mut self, - start_after: Option, + start_after: Option, ) -> Result { let query_content_json = serde_json::to_string(&QueryRequest::GetGateways { limit: self.config.gateway_page_limit, diff --git a/common/client-libs/validator-client/src/models.rs b/common/client-libs/validator-client/src/models.rs index 1b4089b1ba..5f75b77c81 100644 --- a/common/client-libs/validator-client/src/models.rs +++ b/common/client-libs/validator-client/src/models.rs @@ -3,7 +3,7 @@ use crate::serde_helpers::{de_i64_from_str, de_paged_query_response_from_str}; use core::fmt::{self, Display, Formatter}; -use mixnet_contract::HumanAddr; +use mixnet_contract::Addr; use serde::{Deserialize, Serialize}; // TODO: this is a duplicate code but it really does not feel @@ -14,10 +14,10 @@ use serde::{Deserialize, Serialize}; pub(super) enum QueryRequest { GetMixNodes { limit: Option, - start_after: Option, + start_after: Option, }, GetGateways { - start_after: Option, + start_after: Option, limit: Option, }, } diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index f358f90d49..4c62db62f7 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -121,7 +121,7 @@ impl<'a> TryFrom<&'a GatewayBond> for Node { return Err(GatewayConversionError::InvalidStake); } Ok(Node { - owner: bond.owner.0.clone(), + owner: bond.owner.as_str().to_owned(), stake: bond .amount .first() diff --git a/common/topology/src/mix.rs b/common/topology/src/mix.rs index 058794a176..a97e342745 100644 --- a/common/topology/src/mix.rs +++ b/common/topology/src/mix.rs @@ -113,7 +113,7 @@ impl<'a> TryFrom<&'a MixNodeBond> for Node { return Err(MixnodeConversionError::InvalidStake); } Ok(Node { - owner: bond.owner.0.clone(), + owner: bond.owner.as_str().to_owned(), stake: bond .amount .first() From 27e704ab8073a29a81a57d9e37b5915b60743b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 27 May 2021 11:42:11 +0100 Subject: [PATCH 03/24] Reordered imports --- common/mixnet-contract/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/mixnet-contract/src/lib.rs b/common/mixnet-contract/src/lib.rs index cd1dedee33..b5c9a15ced 100644 --- a/common/mixnet-contract/src/lib.rs +++ b/common/mixnet-contract/src/lib.rs @@ -1,6 +1,6 @@ mod gateway; mod mixnode; -pub use cosmwasm_std::{Coin, Addr}; +pub use cosmwasm_std::{Addr, Coin}; pub use gateway::{Gateway, GatewayBond, GatewayOwnershipResponse, PagedGatewayResponse}; pub use mixnode::{MixNode, MixNodeBond, MixOwnershipResponse, PagedResponse}; From 50fbe55be9b1868d8f6dc3f26ee4fc9366bba177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 18 Jun 2021 12:01:29 +0100 Subject: [PATCH 04/24] Missing imports --- common/client-libs/validator-client/src/lib.rs | 4 +++- common/client-libs/validator-client/src/models.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/client-libs/validator-client/src/lib.rs b/common/client-libs/validator-client/src/lib.rs index 7cb1394ac2..11ec497274 100644 --- a/common/client-libs/validator-client/src/lib.rs +++ b/common/client-libs/validator-client/src/lib.rs @@ -4,7 +4,9 @@ use crate::models::{QueryRequest, QueryResponse}; use crate::ValidatorClientError::ValidatorError; use core::fmt::{self, Display, Formatter}; -use mixnet_contract::{Addr, GatewayBond, IdentityKey, LayerDistribution, MixNodeBond, PagedGatewayResponse, PagedResponse}; +use mixnet_contract::{ + GatewayBond, IdentityKey, LayerDistribution, MixNodeBond, PagedGatewayResponse, PagedResponse, +}; use rand::seq::SliceRandom; use rand::thread_rng; use serde::Deserialize; diff --git a/common/client-libs/validator-client/src/models.rs b/common/client-libs/validator-client/src/models.rs index a0c992fcbd..c98c9963ab 100644 --- a/common/client-libs/validator-client/src/models.rs +++ b/common/client-libs/validator-client/src/models.rs @@ -3,7 +3,7 @@ use crate::serde_helpers::{de_i64_from_str, de_paged_query_response_from_str}; use core::fmt::{self, Display, Formatter}; -use mixnet_contract::Addr; +use mixnet_contract::IdentityKey; use serde::{Deserialize, Serialize}; // TODO: this is a duplicate code but it really does not feel From dff7a8976a64abdda1e059b458a8fd179230b070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 18 Jun 2021 12:15:34 +0100 Subject: [PATCH 05/24] cargo fmt --- common/mixnet-contract/src/gateway.rs | 8 ++++++-- common/mixnet-contract/src/mixnode.rs | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/common/mixnet-contract/src/gateway.rs b/common/mixnet-contract/src/gateway.rs index 54da623ccb..d4bae81d17 100644 --- a/common/mixnet-contract/src/gateway.rs +++ b/common/mixnet-contract/src/gateway.rs @@ -1,8 +1,8 @@ // due to code generated by JsonSchema #![allow(clippy::field_reassign_with_default)] -use cosmwasm_std::{Addr, Coin}; use crate::{IdentityKey, SphinxKey}; +use cosmwasm_std::{Addr, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Display; @@ -102,7 +102,11 @@ pub struct PagedGatewayResponse { } impl PagedGatewayResponse { - pub fn new(nodes: Vec, per_page: usize, start_next_after: Option) -> Self { + pub fn new( + nodes: Vec, + per_page: usize, + start_next_after: Option, + ) -> Self { PagedGatewayResponse { nodes, per_page, diff --git a/common/mixnet-contract/src/mixnode.rs b/common/mixnet-contract/src/mixnode.rs index 38fdeda8b2..c4bfa7da41 100644 --- a/common/mixnet-contract/src/mixnode.rs +++ b/common/mixnet-contract/src/mixnode.rs @@ -1,8 +1,8 @@ // due to code generated by JsonSchema #![allow(clippy::field_reassign_with_default)] -use cosmwasm_std::{Addr, Coin}; use crate::{IdentityKey, SphinxKey}; +use cosmwasm_std::{Addr, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Display; @@ -125,7 +125,11 @@ pub struct PagedResponse { } impl PagedResponse { - pub fn new(nodes: Vec, per_page: usize, start_next_after: Option) -> Self { + pub fn new( + nodes: Vec, + per_page: usize, + start_next_after: Option, + ) -> Self { PagedResponse { nodes, per_page, From 7d69fa3ed55673315c0f134f89399469d58f5a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 18 Jun 2021 12:21:33 +0100 Subject: [PATCH 06/24] More cargo fmt action --- contracts/mixnet/src/support/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mixnet/src/support/tests.rs b/contracts/mixnet/src/support/tests.rs index 89cba360c2..79bb07c816 100644 --- a/contracts/mixnet/src/support/tests.rs +++ b/contracts/mixnet/src/support/tests.rs @@ -1,9 +1,9 @@ #[cfg(test)] pub mod helpers { use super::*; - use crate::contract::{instantiate, INITIAL_MIXNODE_BOND}; use crate::contract::query; use crate::contract::DENOM; + use crate::contract::{instantiate, INITIAL_MIXNODE_BOND}; use crate::msg::InstantiateMsg; use crate::msg::QueryMsg; use crate::transactions::{try_add_gateway, try_add_mixnode}; From 08964f8775bcac729ef8d4bf987d9c365d01fe44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 18 Jun 2021 12:32:13 +0100 Subject: [PATCH 07/24] Introduced type alias for IdentityKey reference --- common/mixnet-contract/src/lib.rs | 1 + contracts/mixnet/src/storage.rs | 47 +++++++++++++++++----------- contracts/mixnet/src/transactions.rs | 4 +-- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/common/mixnet-contract/src/lib.rs b/common/mixnet-contract/src/lib.rs index c7dd376082..d43d9d33fe 100644 --- a/common/mixnet-contract/src/lib.rs +++ b/common/mixnet-contract/src/lib.rs @@ -20,4 +20,5 @@ pub struct LayerDistribution { // type aliases for better reasoning about available data pub type IdentityKey = String; +pub type IdentityKeyRef<'a> = &'a str; pub type SphinxKey = String; diff --git a/contracts/mixnet/src/storage.rs b/contracts/mixnet/src/storage.rs index e41dcf3dc2..a2ee80285d 100644 --- a/contracts/mixnet/src/storage.rs +++ b/contracts/mixnet/src/storage.rs @@ -5,7 +5,7 @@ use cosmwasm_storage::{ bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton, Singleton, }; -use mixnet_contract::{GatewayBond, IdentityKey, LayerDistribution, MixNodeBond}; +use mixnet_contract::{GatewayBond, IdentityKey, IdentityKeyRef, LayerDistribution, MixNodeBond}; // storage prefixes // all of them must be unique and presumably not be a prefix of a different one @@ -180,7 +180,7 @@ pub(crate) fn increase_mixnode_bond( pub(crate) fn increase_mix_delegated_stakes( storage: &mut dyn Storage, - mix_identity: &IdentityKey, + mix_identity: IdentityKey, scaled_reward_rate: Decimal, ) -> StdResult<()> { let chunk_size = queries::DELEGATION_PAGE_MAX_LIMIT as usize; @@ -188,7 +188,7 @@ pub(crate) fn increase_mix_delegated_stakes( let mut chunk_start: Option> = None; loop { // get `chunk_size` of delegations - let delegations_chunk = mix_delegations_read(storage, mix_identity) + let delegations_chunk = mix_delegations_read(storage, &mix_identity) .range(chunk_start.as_deref(), None, Order::Ascending) .take(chunk_size) .collect::>>()?; @@ -213,7 +213,7 @@ pub(crate) fn increase_mix_delegated_stakes( for (delegator_address, amount) in delegations_chunk.into_iter() { let reward = amount * scaled_reward_rate; let new_amount = amount + reward; - mix_delegations(storage, mix_identity).save(&delegator_address, &new_amount)?; + mix_delegations(storage, &mix_identity).save(&delegator_address, &new_amount)?; } } @@ -222,7 +222,7 @@ pub(crate) fn increase_mix_delegated_stakes( pub(crate) fn increase_gateway_delegated_stakes( storage: &mut dyn Storage, - gateway_identity: &IdentityKey, + gateway_identity: IdentityKey, scaled_reward_rate: Decimal, ) -> StdResult<()> { let chunk_size = queries::DELEGATION_PAGE_MAX_LIMIT as usize; @@ -230,7 +230,7 @@ pub(crate) fn increase_gateway_delegated_stakes( let mut chunk_start: Option> = None; loop { // get `chunk_size` of delegations - let delegations_chunk = gateway_delegations_read(storage, gateway_identity) + let delegations_chunk = gateway_delegations_read(storage, &gateway_identity) .range(chunk_start.as_deref(), None, Order::Ascending) .take(chunk_size) .collect::>>()?; @@ -255,7 +255,8 @@ pub(crate) fn increase_gateway_delegated_stakes( for (delegator_address, amount) in delegations_chunk.into_iter() { let reward = amount * scaled_reward_rate; let new_amount = amount + reward; - gateway_delegations(storage, gateway_identity).save(&delegator_address, &new_amount)?; + gateway_delegations(storage, &gateway_identity) + .save(&delegator_address, &new_amount)?; } } @@ -316,21 +317,21 @@ pub(crate) fn increase_gateway_bond( // delegation related pub fn mix_delegations<'a>( storage: &'a mut dyn Storage, - mix_identity: &'a IdentityKey, + mix_identity: IdentityKeyRef, ) -> Bucket<'a, Uint128> { Bucket::multilevel(storage, &[PREFIX_MIX_DELEGATION, mix_identity.as_bytes()]) } pub fn mix_delegations_read<'a>( storage: &'a dyn Storage, - mix_identity: &'a IdentityKey, + mix_identity: IdentityKeyRef, ) -> ReadonlyBucket<'a, Uint128> { ReadonlyBucket::multilevel(storage, &[PREFIX_MIX_DELEGATION, mix_identity.as_bytes()]) } pub fn gateway_delegations<'a>( storage: &'a mut dyn Storage, - gateway_identity: &'a IdentityKey, + gateway_identity: IdentityKeyRef, ) -> Bucket<'a, Uint128> { Bucket::multilevel( storage, @@ -340,7 +341,7 @@ pub fn gateway_delegations<'a>( pub fn gateway_delegations_read<'a>( storage: &'a dyn Storage, - gateway_identity: &'a IdentityKey, + gateway_identity: IdentityKeyRef, ) -> ReadonlyBucket<'a, Uint128> { ReadonlyBucket::multilevel( storage, @@ -537,7 +538,8 @@ mod tests { // 0.001 let reward = Decimal::from_ratio(1u128, 1000u128); - increase_mix_delegated_stakes(&mut deps.storage, &node_identity, reward).unwrap(); + increase_mix_delegated_stakes(&mut deps.storage, node_identity.clone(), reward) + .unwrap(); // there are no 'new' delegations magically added assert!( @@ -561,7 +563,8 @@ mod tests { .save(delegator_address.as_bytes(), &Uint128(1000)) .unwrap(); - increase_mix_delegated_stakes(&mut deps.storage, &node_identity, reward).unwrap(); + increase_mix_delegated_stakes(&mut deps.storage, node_identity.clone(), reward) + .unwrap(); assert_eq!( Uint128(1001), mix_delegations_read(&mut deps.storage, &node_identity) @@ -585,7 +588,8 @@ mod tests { .unwrap(); } - increase_mix_delegated_stakes(&mut deps.storage, &node_identity, reward).unwrap(); + increase_mix_delegated_stakes(&mut deps.storage, node_identity.clone(), reward) + .unwrap(); for i in 0..100 { let delegator_address = Addr::unchecked(format!("address{}", i)); @@ -613,7 +617,8 @@ mod tests { .unwrap(); } - increase_mix_delegated_stakes(&mut deps.storage, &node_identity, reward).unwrap(); + increase_mix_delegated_stakes(&mut deps.storage, node_identity.clone(), reward) + .unwrap(); for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 { let delegator_address = Addr::unchecked(format!("address{}", i)); @@ -641,7 +646,8 @@ mod tests { // 0.001 let reward = Decimal::from_ratio(1u128, 1000u128); - increase_gateway_delegated_stakes(&mut deps.storage, &node_identity, reward).unwrap(); + increase_gateway_delegated_stakes(&mut deps.storage, node_identity.clone(), reward) + .unwrap(); // there are no 'new' delegations magically added assert!( @@ -665,7 +671,8 @@ mod tests { .save(delegator_address.as_bytes(), &Uint128(1000)) .unwrap(); - increase_gateway_delegated_stakes(&mut deps.storage, &node_identity, reward).unwrap(); + increase_gateway_delegated_stakes(&mut deps.storage, node_identity.clone(), reward) + .unwrap(); assert_eq!( Uint128(1001), gateway_delegations_read(&mut deps.storage, &node_identity) @@ -689,7 +696,8 @@ mod tests { .unwrap(); } - increase_gateway_delegated_stakes(&mut deps.storage, &node_identity, reward).unwrap(); + increase_gateway_delegated_stakes(&mut deps.storage, node_identity.clone(), reward) + .unwrap(); for i in 0..100 { let delegator_address = Addr::unchecked(format!("address{}", i)); @@ -717,7 +725,8 @@ mod tests { .unwrap(); } - increase_gateway_delegated_stakes(&mut deps.storage, &node_identity, reward).unwrap(); + increase_gateway_delegated_stakes(&mut deps.storage, node_identity.clone(), reward) + .unwrap(); for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 { let delegator_address = Addr::unchecked(format!("address{}", i)); diff --git a/contracts/mixnet/src/transactions.rs b/contracts/mixnet/src/transactions.rs index 28e415129a..3f70ae364d 100644 --- a/contracts/mixnet/src/transactions.rs +++ b/contracts/mixnet/src/transactions.rs @@ -339,7 +339,7 @@ pub(crate) fn try_reward_mixnode( let scaled_reward = scale_reward_by_uptime(reward, uptime)?; increase_mixnode_bond(deps.storage, current_bond, scaled_reward)?; - increase_mix_delegated_stakes(deps.storage, &mix_identity, scaled_reward)?; + increase_mix_delegated_stakes(deps.storage, mix_identity, scaled_reward)?; Ok(Response::default()) } @@ -372,7 +372,7 @@ pub(crate) fn try_reward_gateway( let scaled_reward = scale_reward_by_uptime(reward, uptime)?; increase_gateway_bond(deps.storage, current_bond, scaled_reward)?; - increase_gateway_delegated_stakes(deps.storage, &gateway_identity, scaled_reward)?; + increase_gateway_delegated_stakes(deps.storage, gateway_identity, scaled_reward)?; Ok(Response::default()) } From 29ac1191278ff9f1dd775514ca623e0e61092780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 22 Jun 2021 16:38:14 +0100 Subject: [PATCH 08/24] Constant defined arguments for gateway and mixnode --- gateway/src/commands/init.rs | 65 ++++++++------------------ gateway/src/commands/mod.rs | 79 ++++++++++++-------------------- gateway/src/commands/run.rs | 70 ++++++++-------------------- mixnode/src/commands/describe.rs | 7 +-- mixnode/src/commands/init.rs | 53 ++++++++++----------- mixnode/src/commands/mod.rs | 47 ++++++++++--------- mixnode/src/commands/run.rs | 44 +++++++----------- mixnode/src/commands/sign.rs | 15 +++--- mixnode/src/commands/upgrade.rs | 24 ++++++---- 9 files changed, 161 insertions(+), 243 deletions(-) diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index de4ce55a24..f5ad70456c 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -1,7 +1,7 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::commands::override_config; +use crate::commands::*; use crate::config::persistence::pathfinder::GatewayPathfinder; use crate::config::Config; use clap::{App, Arg, ArgMatches}; @@ -12,83 +12,58 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { App::new("init") .about("Initialise the gateway") .arg( - Arg::with_name("id") - .long("id") + Arg::with_name(ID_ARG_NAME) + .long(ID_ARG_NAME) .help("Id of the gateway we want to create config for.") .takes_value(true) .required(true), ) .arg( - Arg::with_name("mix-host") - .long("mix-host") + Arg::with_name(HOST_ARG_NAME) + .long(HOST_ARG_NAME) .help("The custom host on which the gateway will be running for receiving sphinx packets") .takes_value(true) .required(true), ) .arg( - Arg::with_name("mix-port") - .long("mix-port") + Arg::with_name(MIX_PORT_ARG_NAME) + .long(MIX_PORT_ARG_NAME) .help("The port on which the gateway will be listening for sphinx packets") .takes_value(true) ) .arg( - Arg::with_name("clients-host") - .long("clients-host") - .help("The custom host on which the gateway will be running for receiving clients gateway-requests") - .takes_value(true) - .required(true), - ) - .arg( - Arg::with_name("clients-port") - .long("clients-port") + Arg::with_name(CLIENTS_PORT_ARG_NAME) + .long(CLIENTS_PORT_ARG_NAME) .help("The port on which the gateway will be listening for clients gateway-requests") .takes_value(true) ) .arg( - Arg::with_name("mix-announce-host") - .long("mix-announce-host") + Arg::with_name(ANNOUNCE_HOST_ARG_NAME) + .long(ANNOUNCE_HOST_ARG_NAME) .help("The host that will be reported to the directory server") .takes_value(true), ) .arg( - Arg::with_name("mix-announce-port") - .long("mix-announce-port") - .help("The port that will be reported to the directory server") - .takes_value(true), - ) - .arg( - Arg::with_name("clients-announce-host") - .long("clients-announce-host") - .help("The host that will be reported to the directory server") - .takes_value(true), - ) - .arg( - Arg::with_name("clients-announce-port") - .long("clients-announce-port") - .help("The port that will be reported to the directory server") - .takes_value(true), - ) - .arg( - Arg::with_name("inboxes") - .long("inboxes") + Arg::with_name(INBOXES_ARG_NAME) + .long(INBOXES_ARG_NAME) .help("Directory with inboxes where all packets for the clients are stored") .takes_value(true) ) .arg( - Arg::with_name("clients-ledger") - .long("clients-ledger") - .help("Ledger directory containing registered clients") + Arg::with_name(CLIENTS_LEDGER_ARG_NAME) + .long(CLIENTS_LEDGER_ARG_NAME) + .help("Ledger file containing registered clients") .takes_value(true) ) .arg( - Arg::with_name("validators") - .long("validators") + Arg::with_name(VALIDATORS_ARG_NAME) + .long(VALIDATORS_ARG_NAME) .help("Comma separated list of rest endpoints of the validators") .takes_value(true), ) .arg( - Arg::with_name("mixnet-contract") - .long("mixnet-contract") + Arg::with_name(CONTRACT_ARG_NAME) + .long(CONTRACT_ARG_NAME) .help("Address of the validator contract managing the network") .takes_value(true), ) diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index 5cb66b2e77..f258495827 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -8,6 +8,16 @@ pub(crate) mod init; pub(crate) mod run; pub(crate) mod upgrade; +pub(crate) const ID_ARG_NAME: &str = "id"; +pub(crate) const HOST_ARG_NAME: &str = "host"; +pub(crate) const MIX_PORT_ARG_NAME: &str = "mix-port"; +pub(crate) const CLIENTS_PORT_ARG_NAME: &str = "clients-port"; +pub(crate) const VALIDATORS_ARG_NAME: &str = "validators"; +pub(crate) const CONTRACT_ARG_NAME: &str = "mixnet-contract"; +pub(crate) const ANNOUNCE_HOST_ARG_NAME: &str = "announce-host"; +pub(crate) const INBOXES_ARG_NAME: &str = "inboxes"; +pub(crate) const CLIENTS_LEDGER_ARG_NAME: &str = "clients-ledger"; + fn parse_validators(raw: &str) -> Vec { raw.split(',') .map(|raw_validator| raw_validator.trim().into()) @@ -15,85 +25,54 @@ fn parse_validators(raw: &str) -> Vec { } pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config { - let mut was_mix_host_overridden = false; - if let Some(mix_host) = matches.value_of("mix-host") { - config = config.with_mix_listening_host(mix_host); - was_mix_host_overridden = true; + let mut was_host_overridden = false; + if let Some(host) = matches.value_of(HOST_ARG_NAME) { + config = config.with_listening_address(host); + was_host_overridden = true; } - if let Some(mix_port) = matches.value_of("mix-port").map(|port| port.parse::()) { + if let Some(mix_port) = matches + .value_of(MIX_PORT_ARG_NAME) + .map(|port| port.parse::()) + { if let Err(err) = mix_port { // if port was overridden, it must be parsable panic!("Invalid port value provided - {:?}", err); } - config = config.with_mix_listening_port(mix_port.unwrap()); - } - let mut was_clients_host_overridden = false; - if let Some(clients_host) = matches.value_of("clients-host") { - config = config.with_clients_listening_host(clients_host); - was_clients_host_overridden = true; + config = config.with_mix_port(mix_port.unwrap()); } if let Some(clients_port) = matches - .value_of("clients-port") + .value_of(CLIENTS_PORT_ARG_NAME) .map(|port| port.parse::()) { if let Err(err) = clients_port { // if port was overridden, it must be parsable panic!("Invalid port value provided - {:?}", err); } - config = config.with_clients_listening_port(clients_port.unwrap()); + config = config.with_clients_port(clients_port.unwrap()); } - if let Some(mix_announce_host) = matches.value_of("mix-announce-host") { - config = config.with_mix_announce_host(mix_announce_host); - } else if was_mix_host_overridden { + if let Some(announce_host) = matches.value_of(ANNOUNCE_HOST_ARG_NAME) { + config = config.with_announce_address(announce_host); + } else if was_host_overridden { // make sure our 'mix-announce-host' always defaults to 'mix-host' - config = config.mix_announce_host_from_listening_host() + config = config.announce_host_from_listening_host() } - if let Some(mix_announce_port) = matches - .value_of("mix-announce-port") - .map(|port| port.parse::()) - { - if let Err(err) = mix_announce_port { - // if port was overridden, it must be parsable - panic!("Invalid port value provided - {:?}", err); - } - config = config.with_mix_announce_port(mix_announce_port.unwrap()); - } - - if let Some(clients_announce_host) = matches.value_of("clients-announce-host") { - config = config.with_clients_announce_host(clients_announce_host); - } else if was_clients_host_overridden { - // make sure our 'clients-announce-host' always defaults to 'clients-host' - config = config.clients_announce_host_from_listening_host() - } - - if let Some(clients_announce_port) = matches - .value_of("clients-announce-port") - .map(|port| port.parse::()) - { - if let Err(err) = clients_announce_port { - // if port was overridden, it must be parsable - panic!("Invalid port value provided - {:?}", err); - } - config = config.with_clients_announce_port(clients_announce_port.unwrap()); - } - - if let Some(raw_validators) = matches.value_of("validators") { + if let Some(raw_validators) = matches.value_of(VALIDATORS_ARG_NAME) { config = config.with_custom_validators(parse_validators(raw_validators)); } - if let Some(contract_address) = matches.value_of("mixnet-contract") { + if let Some(contract_address) = matches.value_of(CONTRACT_ARG_NAME) { config = config.with_custom_mixnet_contract(contract_address) } - if let Some(inboxes_dir) = matches.value_of("inboxes") { + if let Some(inboxes_dir) = matches.value_of(INBOXES_ARG_NAME) { config = config.with_custom_clients_inboxes(inboxes_dir); } - if let Some(clients_ledger) = matches.value_of("clients-ledger") { + if let Some(clients_ledger) = matches.value_of(CLIENTS_LEDGER_ARG_NAME) { config = config.with_custom_clients_ledger(clients_ledger); } diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index 46e46b0a7a..e83645c724 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -1,7 +1,7 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::commands::override_config; +use crate::commands::*; use crate::config::persistence::pathfinder::GatewayPathfinder; use crate::config::Config; use crate::node::Gateway; @@ -15,88 +15,58 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { App::new("run") .about("Starts the gateway") .arg( - Arg::with_name("id") - .long("id") + Arg::with_name(ID_ARG_NAME) + .long(ID_ARG_NAME) .help("Id of the gateway we want to run") .takes_value(true) .required(true), ) // the rest of arguments are optional, they are used to override settings in config file .arg( - Arg::with_name("config") - .long("config") - .help("Custom path to the nym gateway configuration file") - .takes_value(true), - ) - .arg( - Arg::with_name("mix-host") - .long("mix-host") + Arg::with_name(HOST_ARG_NAME) + .long(HOST_ARG_NAME) .help("The custom host on which the gateway will be running for receiving sphinx packets") .takes_value(true) ) .arg( - Arg::with_name("mix-port") - .long("mix-port") + Arg::with_name(MIX_PORT_ARG_NAME) + .long(MIX_PORT_ARG_NAME) .help("The port on which the gateway will be listening for sphinx packets") .takes_value(true) ) .arg( - Arg::with_name("clients-host") - .long("clients-host") - .help("The custom host on which the gateway will be running for receiving clients gateway-requests") - .takes_value(true) - ) - .arg( - Arg::with_name("clients-port") - .long("clients-port") + Arg::with_name(CLIENTS_PORT_ARG_NAME) + .long(CLIENTS_PORT_ARG_NAME) .help("The port on which the gateway will be listening for clients gateway-requests") .takes_value(true) ) .arg( - Arg::with_name("mix-announce-host") - .long("mix-announce-host") + Arg::with_name(ANNOUNCE_HOST_ARG_NAME) + .long(ANNOUNCE_HOST_ARG_NAME) .help("The host that will be reported to the directory server") .takes_value(true), ) .arg( - Arg::with_name("mix-announce-port") - .long("mix-announce-port") - .help("The port that will be reported to the directory server") - .takes_value(true), - ) - .arg( - Arg::with_name("clients-announce-host") - .long("clients-announce-host") - .help("The host that will be reported to the directory server") - .takes_value(true), - ) - .arg( - Arg::with_name("clients-announce-port") - .long("clients-announce-port") - .help("The port that will be reported to the directory server") - .takes_value(true), - ) - .arg( - Arg::with_name("inboxes") - .long("inboxes") + Arg::with_name(INBOXES_ARG_NAME) + .long(INBOXES_ARG_NAME) .help("Directory with inboxes where all packets for the clients are stored") .takes_value(true) ) .arg( - Arg::with_name("clients-ledger") - .long("clients-ledger") + Arg::with_name(CLIENTS_LEDGER_ARG_NAME) + .long(CLIENTS_LEDGER_ARG_NAME) .help("Ledger file containing registered clients") .takes_value(true) ) .arg( - Arg::with_name("validators") - .long("validators") + Arg::with_name(VALIDATORS_ARG_NAME) + .long(VALIDATORS_ARG_NAME) .help("Comma separated list of rest endpoints of the validators") .takes_value(true), ) .arg( - Arg::with_name("mixnet-contract") - .long("mixnet-contract") + Arg::with_name(CONTRACT_ARG_NAME) + .long(CONTRACT_ARG_NAME) .help("Address of the validator contract managing the network") .takes_value(true), ) @@ -163,7 +133,7 @@ fn version_check(cfg: &Config) -> bool { } pub fn execute(matches: &ArgMatches) { - let id = matches.value_of("id").unwrap(); + let id = matches.value_of(ID_ARG_NAME).unwrap(); println!("Starting gateway {}...", id); diff --git a/mixnode/src/commands/describe.rs b/mixnode/src/commands/describe.rs index 4887ae832b..2c5494907b 100644 --- a/mixnode/src/commands/describe.rs +++ b/mixnode/src/commands/describe.rs @@ -1,3 +1,4 @@ +use crate::commands::*; use crate::config::Config; use crate::node::node_description::NodeDescription; use clap::{App, Arg, ArgMatches}; @@ -10,8 +11,8 @@ pub fn command_args<'a, 'b>() -> App<'a, 'b> { App::new("describe") .about("Describe your mixnode and tell people why they should delegate stake to you") .arg( - Arg::with_name("id") - .long("id") + Arg::with_name(ID_ARG_NAME) + .long(ID_ARG_NAME) .help("The id of the mixnode you want to describe") .takes_value(true) .required(true), @@ -21,7 +22,7 @@ pub fn command_args<'a, 'b>() -> App<'a, 'b> { pub fn execute(matches: &ArgMatches) { // figure out which node the user is describing let id = matches - .value_of("id") + .value_of(ID_ARG_NAME) .expect("Please provide the id of your mixnode"); // ensure that the mixnode has in fact been initialized diff --git a/mixnode/src/commands/init.rs b/mixnode/src/commands/init.rs index c46c908b51..4edba5ecd0 100644 --- a/mixnode/src/commands/init.rs +++ b/mixnode/src/commands/init.rs @@ -1,7 +1,7 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::commands::override_config; +use crate::commands::*; use crate::config::persistence::pathfinder::MixNodePathfinder; use crate::config::Config; use clap::{App, Arg, ArgMatches}; @@ -15,61 +15,49 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { App::new("init") .about("Initialise the mixnode") .arg( - Arg::with_name("id") - .long("id") + Arg::with_name(ID_ARG_NAME) + .long(ID_ARG_NAME) .help("Id of the nym-mixnode we want to create config for.") .takes_value(true) .required(true), ) .arg( - Arg::with_name("layer") - .long("layer") + Arg::with_name(LAYER_ARG_NAME) + .long(LAYER_ARG_NAME) .help("The mixnet layer of this particular node") .takes_value(true), ) .arg( - Arg::with_name("host") - .long("host") + Arg::with_name(HOST_ARG_NAME) + .long(HOST_ARG_NAME) .help("The host on which the mixnode will be running") .takes_value(true) .required(true), ) .arg( - Arg::with_name("port") - .long("port") + Arg::with_name(MIX_PORT_ARG_NAME) + .long(MIX_PORT_ARG_NAME) .help("The port on which the mixnode will be listening") .takes_value(true), ) .arg( - Arg::with_name("announce-host") - .long("announce-host") + Arg::with_name(ANNOUNCE_HOST_ARG_NAME) + .long(ANNOUNCE_HOST_ARG_NAME) .help("The custom host that will be reported to the directory server") .takes_value(true), ) .arg( - Arg::with_name("announce-port") - .long("announce-port") - .help("The custom port that will be reported to the directory server") - .takes_value(true), - ) - .arg( - Arg::with_name("validators") - .long("validators") + Arg::with_name(VALIDATORS_ARG_NAME) + .long(VALIDATORS_ARG_NAME) .help("Comma separated list of rest endpoints of the validators") .takes_value(true), ) .arg( - Arg::with_name("mixnet-contract") - .long("mixnet-contract") + Arg::with_name(CONTRACT_ARG_NAME) + .long(CONTRACT_ARG_NAME) .help("Address of the validator contract managing the network") .takes_value(true), ) - .arg( - Arg::with_name("metrics-server") - .long("metrics-server") - .help("Server to which the node is sending all metrics data") - .takes_value(true), - ) } async fn choose_layer( @@ -78,7 +66,10 @@ async fn choose_layer( mixnet_contract: String, ) -> u64 { let max_layer = DEFAULT_NUM_MIX_HOPS; - if let Some(layer) = matches.value_of("layer").map(|layer| layer.parse::()) { + if let Some(layer) = matches + .value_of(LAYER_ARG_NAME) + .map(|layer| layer.parse::()) + { if let Err(err) = layer { // if layer was overridden, it must be parsable panic!("Invalid layer value provided - {:?}", err); @@ -139,7 +130,8 @@ fn show_bonding_info(config: &Config) { "\nTo bond your mixnode you will need to provide the following: Identity key: {} Sphinx key: {} - Host: {} + Address: {} + Mix port: {} Layer: {} Location: [physical location of your node's server] Version: {} @@ -147,6 +139,7 @@ fn show_bonding_info(config: &Config) { identity_keypair.public_key().to_base58_string(), sphinx_keypair.public_key().to_base58_string(), config.get_announce_address(), + config.get_mix_port(), config.get_layer(), config.get_version(), ); @@ -157,7 +150,7 @@ pub fn execute(matches: &ArgMatches) { // and then removing runtime from mixnode itself in `run` let rt = Runtime::new().unwrap(); rt.block_on(async { - let id = matches.value_of("id").unwrap(); + let id = matches.value_of(ID_ARG_NAME).unwrap(); println!("Initialising mixnode {}...", id); let already_init = if Config::default_config_file_path(id).exists() { diff --git a/mixnode/src/commands/mod.rs b/mixnode/src/commands/mod.rs index 11b5ad56b4..0cd690220b 100644 --- a/mixnode/src/commands/mod.rs +++ b/mixnode/src/commands/mod.rs @@ -11,6 +11,14 @@ pub(crate) mod run; pub(crate) mod sign; pub(crate) mod upgrade; +pub(crate) const ID_ARG_NAME: &str = "id"; +pub(crate) const HOST_ARG_NAME: &str = "host"; +pub(crate) const LAYER_ARG_NAME: &str = "layer"; +pub(crate) const MIX_PORT_ARG_NAME: &str = "mix-port"; +pub(crate) const VALIDATORS_ARG_NAME: &str = "validators"; +pub(crate) const CONTRACT_ARG_NAME: &str = "mixnet-contract"; +pub(crate) const ANNOUNCE_HOST_ARG_NAME: &str = "announce-host"; + fn parse_validators(raw: &str) -> Vec { raw.split(',') .map(|raw_validator| raw_validator.trim().into()) @@ -20,12 +28,15 @@ fn parse_validators(raw: &str) -> Vec { pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config { let max_layer = DEFAULT_NUM_MIX_HOPS; let mut was_host_overridden = false; - if let Some(host) = matches.value_of("host") { - config = config.with_listening_host(host); + if let Some(host) = matches.value_of(HOST_ARG_NAME) { + config = config.with_listening_address(host); was_host_overridden = true; } - if let Some(layer) = matches.value_of("layer").map(|layer| layer.parse::()) { + if let Some(layer) = matches + .value_of(LAYER_ARG_NAME) + .map(|layer| layer.parse::()) + { if let Err(err) = layer { // if layer was overridden, it must be parsable panic!("Invalid layer value provided - {:?}", err); @@ -36,38 +47,30 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi } } - if let Some(port) = matches.value_of("port").map(|port| port.parse::()) { + if let Some(port) = matches + .value_of(MIX_PORT_ARG_NAME) + .map(|port| port.parse::()) + { if let Err(err) = port { // if port was overridden, it must be parsable - panic!("Invalid port value provided - {:?}", err); + panic!("Invalid mix port value provided - {:?}", err); } - config = config.with_listening_port(port.unwrap()); + config = config.with_mix_port(port.unwrap()); } - if let Some(raw_validators) = matches.value_of("validators") { + if let Some(raw_validators) = matches.value_of(VALIDATORS_ARG_NAME) { config = config.with_custom_validators(parse_validators(raw_validators)); } - if let Some(contract_address) = matches.value_of("mixnet-contract") { + if let Some(contract_address) = matches.value_of(CONTRACT_ARG_NAME) { config = config.with_custom_mixnet_contract(contract_address) } - if let Some(announce_host) = matches.value_of("announce-host") { - config = config.with_announce_host(announce_host); + if let Some(announce_host) = matches.value_of(ANNOUNCE_HOST_ARG_NAME) { + config = config.with_announce_address(announce_host); } else if was_host_overridden { // make sure our 'announce-host' always defaults to 'host' - config = config.announce_host_from_listening_host() - } - - if let Some(announce_port) = matches - .value_of("announce-port") - .map(|port| port.parse::()) - { - if let Err(err) = announce_port { - // if port was overridden, it must be parsable - panic!("Invalid port value provided - {:?}", err); - } - config = config.with_announce_port(announce_port.unwrap()); + config = config.announce_address_from_listening_address() } config diff --git a/mixnode/src/commands/run.rs b/mixnode/src/commands/run.rs index 94d20d6510..68c07296ba 100644 --- a/mixnode/src/commands/run.rs +++ b/mixnode/src/commands/run.rs @@ -1,7 +1,7 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::commands::override_config; +use crate::commands::*; use crate::config::{persistence::pathfinder::MixNodePathfinder, Config}; use crate::node::node_description::NodeDescription; use crate::node::MixNode; @@ -15,61 +15,49 @@ pub fn command_args<'a, 'b>() -> App<'a, 'b> { App::new("run") .about("Starts the mixnode") .arg( - Arg::with_name("id") - .long("id") + Arg::with_name(ID_ARG_NAME) + .long(ID_ARG_NAME) .help("Id of the nym-mixnode we want to run") .takes_value(true) .required(true), ) // the rest of arguments are optional, they are used to override settings in config file .arg( - Arg::with_name("layer") - .long("layer") + Arg::with_name(LAYER_ARG_NAME) + .long(LAYER_ARG_NAME) .help("The mixnet layer of this particular node") .takes_value(true), ) .arg( - Arg::with_name("host") - .long("host") + Arg::with_name(HOST_ARG_NAME) + .long(HOST_ARG_NAME) .help("The custom host on which the mixnode will be running") .takes_value(true), ) .arg( - Arg::with_name("port") - .long("port") + Arg::with_name(MIX_PORT_ARG_NAME) + .long(MIX_PORT_ARG_NAME) .help("The port on which the mixnode will be listening") .takes_value(true), ) .arg( - Arg::with_name("announce-host") - .long("announce-host") + Arg::with_name(ANNOUNCE_HOST_ARG_NAME) + .long(ANNOUNCE_HOST_ARG_NAME) .help("The host that will be reported to the directory server") .takes_value(true), ) .arg( - Arg::with_name("announce-port") - .long("announce-port") - .help("The port that will be reported to the directory server") - .takes_value(true), - ) - .arg( - Arg::with_name("validators") - .long("validators") + Arg::with_name(VALIDATORS_ARG_NAME) + .long(VALIDATORS_ARG_NAME) .help("Comma separated list of rest endpoints of the validators") .takes_value(true), ) .arg( - Arg::with_name("mixnet-contract") - .long("mixnet-contract") + Arg::with_name(CONTRACT_ARG_NAME) + .long(CONTRACT_ARG_NAME) .help("Address of the validator contract managing the network") .takes_value(true), ) - .arg( - Arg::with_name("metrics-server") - .long("metrics-server") - .help("Server to which the node is sending all metrics data") - .takes_value(true), - ) } fn show_binding_warning(address: String) { @@ -125,7 +113,7 @@ fn version_check(cfg: &Config) -> bool { } pub fn execute(matches: &ArgMatches) { - let id = matches.value_of("id").unwrap(); + let id = matches.value_of(ID_ARG_NAME).unwrap(); println!("Starting mixnode {}...", id); diff --git a/mixnode/src/commands/sign.rs b/mixnode/src/commands/sign.rs index de490bd80d..bca25d4740 100644 --- a/mixnode/src/commands/sign.rs +++ b/mixnode/src/commands/sign.rs @@ -1,3 +1,4 @@ +use crate::commands::*; use crate::config::{persistence::pathfinder::MixNodePathfinder, Config}; use clap::{App, Arg, ArgMatches}; use colored::*; @@ -5,19 +6,21 @@ use config::NymConfig; use crypto::asymmetric::identity; use log::error; +const SIGN_TEXT_ARG_NAME: &str = "text"; + pub fn command_args<'a, 'b>() -> App<'a, 'b> { App::new("sign") .about("Sign text to prove ownership of this mixnode") .arg( - Arg::with_name("id") - .long("id") + Arg::with_name(ID_ARG_NAME) + .long(ID_ARG_NAME) .help("The id of the mixnode you want to sign with") .takes_value(true) .required(true), ) .arg( - Arg::with_name("text") - .long("text") + Arg::with_name(SIGN_TEXT_ARG_NAME) + .long(SIGN_TEXT_ARG_NAME) .help("The text to sign") .takes_value(true) .required(true), @@ -34,8 +37,8 @@ fn load_identity_keys(pathfinder: &MixNodePathfinder) -> identity::KeyPair { } pub fn execute(matches: &ArgMatches) { - let id = matches.value_of("id").unwrap(); - let text = matches.value_of("text").unwrap(); + let id = matches.value_of(ID_ARG_NAME).unwrap(); + let text = matches.value_of(SIGN_TEXT_ARG_NAME).unwrap(); let config = match Config::load_from_file(id) { Ok(cfg) => cfg, diff --git a/mixnode/src/commands/upgrade.rs b/mixnode/src/commands/upgrade.rs index db046f9599..89940e24a0 100644 --- a/mixnode/src/commands/upgrade.rs +++ b/mixnode/src/commands/upgrade.rs @@ -1,6 +1,7 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::commands::*; use crate::config::{ default_validator_rest_endpoints, missing_string_value, Config, DEFAULT_MIXNET_CONTRACT_ADDRESS, MISSING_VALUE, @@ -13,6 +14,8 @@ use std::path::PathBuf; use std::process; use version_checker::{parse_version, Version}; +const CURRENT_VERSION_ARG_NAME: &str = "current-version"; + fn print_start_upgrade(from: D1, to: D2) { println!( "\n==================\nTrying to upgrade mixnode from {} to {} ...", @@ -37,15 +40,15 @@ fn print_successful_upgrade(from: D1, to: D2) { pub fn command_args<'a, 'b>() -> App<'a, 'b> { App::new("upgrade").about("Try to upgrade the mixnode") .arg( - Arg::with_name("id") - .long("id") + Arg::with_name(ID_ARG_NAME) + .long(ID_ARG_NAME) .help("Id of the nym-mixnode we want to upgrade") .takes_value(true) .required(true), ) // the rest of arguments depend on the upgrade path - .arg(Arg::with_name("current version") - .long("current-version") + .arg(Arg::with_name(CURRENT_VERSION_ARG_NAME) + .long(CURRENT_VERSION_ARG_NAME) .help("REQUIRED FOR PRE-0.9.0 UPGRADES. Specifies current version of the configuration file to help to determine a valid upgrade path. Valid formats include '0.8.1', 'v0.8.1' or 'V0.8.1'") .takes_value(true) ) @@ -278,7 +281,7 @@ fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version pub fn execute(matches: &ArgMatches) { let package_version = parse_package_version(); - let id = matches.value_of("id").unwrap(); + let id = matches.value_of(ID_ARG_NAME).unwrap(); let mut existing_config = Config::load_from_file(id).unwrap_or_else(|err| { eprintln!("failed to load existing config file! - {:?}", err); @@ -287,12 +290,15 @@ pub fn execute(matches: &ArgMatches) { // versions fields were added in 0.9.0 if existing_config.get_version() == missing_string_value::() { - let self_reported_version = matches.value_of("current version").unwrap_or_else(|| { - eprintln!( + let self_reported_version = + matches + .value_of(CURRENT_VERSION_ARG_NAME) + .unwrap_or_else(|| { + eprintln!( "trying to upgrade from pre v0.9.0 without providing current system version!" ); - process::exit(1) - }); + process::exit(1) + }); // upgrades up to 0.9.0 existing_config = pre_090_upgrade(self_reported_version, existing_config); From a6be3e763fc331e033634c935b0a3e1fa68fa3bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 22 Jun 2021 16:39:07 +0100 Subject: [PATCH 09/24] Spliting host into explicit address and port(s) --- clients/native/src/commands/init.rs | 4 +- clients/socks5/src/commands/init.rs | 4 +- clients/webassembly/src/client/mod.rs | 2 +- common/mixnet-contract/src/gateway.rs | 29 +-- common/mixnet-contract/src/mixnode.rs | 19 +- common/topology/src/gateway.rs | 33 +++- common/topology/src/lib.rs | 41 ++++ common/topology/src/mix.rs | 29 ++- gateway/src/commands/init.rs | 12 +- gateway/src/commands/run.rs | 27 +-- gateway/src/config/mod.rs | 249 +++++------------------- gateway/src/node/mod.rs | 45 +++-- mixnode/src/commands/run.rs | 11 +- mixnode/src/config/mod.rs | 111 +++-------- mixnode/src/node/mod.rs | 38 +++- network-monitor/src/monitor/preparer.rs | 7 +- 16 files changed, 270 insertions(+), 391 deletions(-) diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index a4e9f30027..8558648244 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -88,7 +88,7 @@ async fn register_with_gateway( ) -> SharedKeys { let timeout = Duration::from_millis(1500); let mut gateway_client = GatewayClient::new_init( - gateway.client_listener.clone(), + gateway.clients_address(), gateway.identity_key, our_identity.clone(), timeout, @@ -215,7 +215,7 @@ pub fn execute(matches: &ArgMatches) { .with_gateway_id(gate_details.identity_key.to_base58_string()); let shared_keys = register_with_gateway(&gate_details, key_manager.identity_keypair()).await; - (shared_keys, gate_details.client_listener) + (shared_keys, gate_details.clients_address()) }; // TODO: is there perhaps a way to make it work without having to spawn entire runtime? diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 9fbb003e35..0a73d524bf 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -89,7 +89,7 @@ async fn register_with_gateway( ) -> SharedKeys { let timeout = Duration::from_millis(1500); let mut gateway_client = GatewayClient::new_init( - gateway.client_listener.clone(), + gateway.clients_address(), gateway.identity_key, our_identity.clone(), timeout, @@ -217,7 +217,7 @@ pub fn execute(matches: &ArgMatches) { .with_gateway_id(gate_details.identity_key.to_base58_string()); let shared_keys = register_with_gateway(&gate_details, key_manager.identity_keypair()).await; - (shared_keys, gate_details.client_listener) + (shared_keys, gate_details.clients_address()) }; // TODO: is there perhaps a way to make it work without having to spawn entire runtime? diff --git a/clients/webassembly/src/client/mod.rs b/clients/webassembly/src/client/mod.rs index 3785cc3ee5..4f9fc1e404 100644 --- a/clients/webassembly/src/client/mod.rs +++ b/clients/webassembly/src/client/mod.rs @@ -120,7 +120,7 @@ impl NymClient { let (ack_sender, ack_receiver) = mpsc::unbounded(); let mut gateway_client = GatewayClient::new( - gateway.client_listener.clone(), + gateway.clients_address(), Arc::clone(&client.identity), gateway.identity_key, None, diff --git a/common/mixnet-contract/src/gateway.rs b/common/mixnet-contract/src/gateway.rs index d4bae81d17..8285c4a641 100644 --- a/common/mixnet-contract/src/gateway.rs +++ b/common/mixnet-contract/src/gateway.rs @@ -6,13 +6,12 @@ use cosmwasm_std::{Addr, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Display; -use std::io; -use std::net::{SocketAddr, ToSocketAddrs}; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct Gateway { - pub mix_host: String, - pub clients_host: String, + pub host: String, + pub mix_port: u16, + pub clients_port: u16, pub location: String, pub sphinx_key: SphinxKey, /// Base58 encoded ed25519 EdDSA public key of the gateway used to derive shared keys with clients @@ -22,16 +21,18 @@ pub struct Gateway { impl Gateway { pub fn new( - mix_host: String, - clients_host: String, + host: String, + mix_port: u16, + clients_port: u16, location: String, sphinx_key: SphinxKey, identity_key: IdentityKey, version: String, ) -> Self { Gateway { - mix_host, - clients_host, + host, + mix_port, + clients_port, location, sphinx_key, identity_key, @@ -39,12 +40,12 @@ impl Gateway { } } - pub fn try_resolve_hostname(&self) -> Result { - self.mix_host - .to_socket_addrs()? - .next() - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "no valid socket address")) - } + // pub fn try_resolve_hostname(&self) -> Result { + // self.mix_host + // .to_socket_addrs()? + // .next() + // .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "no valid socket address")) + // } } #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] diff --git a/common/mixnet-contract/src/mixnode.rs b/common/mixnet-contract/src/mixnode.rs index c4bfa7da41..eb7687ad17 100644 --- a/common/mixnet-contract/src/mixnode.rs +++ b/common/mixnet-contract/src/mixnode.rs @@ -6,12 +6,11 @@ use cosmwasm_std::{Addr, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Display; -use std::io; -use std::net::{SocketAddr, ToSocketAddrs}; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct MixNode { pub host: String, + pub mix_port: u16, pub layer: u64, pub location: String, pub sphinx_key: SphinxKey, @@ -23,6 +22,7 @@ pub struct MixNode { impl MixNode { pub fn new( host: String, + mix_port: u16, layer: u64, location: String, sphinx_key: SphinxKey, @@ -31,6 +31,7 @@ impl MixNode { ) -> Self { MixNode { host, + mix_port, layer, location, sphinx_key, @@ -38,20 +39,8 @@ impl MixNode { version, } } - - pub fn try_resolve_hostname(&self) -> Result { - self.host - .to_socket_addrs()? - .next() - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "no valid socket address")) - } } -/* -By the way, I've also been thinking of some potential changes in the contract we could introduce once we have to make an incompatible upgrade (say to cosmwasm 0.14+). Is there some place I could write them down so that we would not forget about them? Should I make a GitHub issue, a google doc or maybe put it on GitLab? - - */ - #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct MixNodeBond { // TODO: @@ -62,8 +51,6 @@ pub struct MixNodeBond { // // I would also modify the `MixNode` struct: // - remove `location` field - // - repurpose `host` field to hold either ip or hostname (WITHOUT port information) - // - introduce `mix_port` field // - introduce `rest_api_port` field // - [POTENTIALLY] introduce `verloc_port` field or keep it accessible via http api // diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index 4c62db62f7..b285c9d48e 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::filter; +use crate::{filter, NetworkAddress}; use crypto::asymmetric::{encryption, identity}; use mixnet_contract::GatewayBond; use nymsphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress}; @@ -84,8 +84,11 @@ pub struct Node { // on the network at a type, right? pub stake: u128, pub location: String, - pub client_listener: String, - pub mixnet_listener: SocketAddr, + pub host: NetworkAddress, + // we're keeping this as separate resolved field since we do not want to be resolving the potential + // hostname every time we want to construct a path via this node + pub mix_host: SocketAddr, + pub clients_port: u16, pub identity_key: identity::PublicKey, pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519 pub version: String, @@ -95,6 +98,10 @@ impl Node { pub fn identity(&self) -> &NodeIdentity { &self.identity_key } + + pub fn clients_address(&self) -> String { + format!("ws://{}:{}", self.host, self.clients_port) + } } impl filter::Versioned for Node { @@ -105,7 +112,7 @@ impl filter::Versioned for Node { impl<'a> From<&'a Node> for SphinxNode { fn from(node: &'a Node) -> Self { - let node_address_bytes = NymNodeRoutingAddress::from(node.mixnet_listener) + let node_address_bytes = NymNodeRoutingAddress::from(node.mix_host) .try_into() .unwrap(); @@ -120,6 +127,17 @@ impl<'a> TryFrom<&'a GatewayBond> for Node { if bond.amount.len() > 1 { return Err(GatewayConversionError::InvalidStake); } + + let host: NetworkAddress = bond.gateway.host.parse().map_err(|err| { + GatewayConversionError::InvalidAddress(bond.gateway.host.clone(), err) + })?; + + // try to completely resolve the host in the mix situation to avoid doing it every + // single time we want to construct a path + let mix_host = host.to_socket_addrs(bond.gateway.mix_port).map_err(|err| { + GatewayConversionError::InvalidAddress(bond.gateway.host.clone(), err) + })?[0]; + Ok(Node { owner: bond.owner.as_str().to_owned(), stake: bond @@ -128,10 +146,9 @@ impl<'a> TryFrom<&'a GatewayBond> for Node { .map(|stake| stake.amount.into()) .unwrap_or(0), location: bond.gateway.location.clone(), - client_listener: bond.gateway.clients_host.clone(), - mixnet_listener: bond.gateway.try_resolve_hostname().map_err(|err| { - GatewayConversionError::InvalidAddress(bond.gateway.mix_host.clone(), err) - })?, + host, + mix_host, + clients_port: bond.gateway.clients_port, identity_key: identity::PublicKey::from_base58_string(&bond.gateway.identity_key)?, sphinx_key: encryption::PublicKey::from_base58_string(&bond.gateway.sphinx_key)?, version: bond.gateway.version.clone(), diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index 666d5e3003..316d8c90c3 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -20,6 +20,10 @@ use nymsphinx_types::Node as SphinxNode; use rand::Rng; use std::collections::HashMap; use std::convert::TryInto; +use std::fmt::{self, Display, Formatter}; +use std::io; +use std::net::{IpAddr, SocketAddr, ToSocketAddrs}; +use std::str::FromStr; pub mod filter; pub mod gateway; @@ -35,6 +39,43 @@ pub enum NymTopologyError { NoMixesOnLayerAvailable(MixLayer), } +#[derive(Debug, Clone)] +pub enum NetworkAddress { + IpAddr(IpAddr), + Hostname(String), +} + +impl NetworkAddress { + pub fn to_socket_addrs(&self, port: u16) -> io::Result> { + match self { + NetworkAddress::IpAddr(addr) => Ok(vec![SocketAddr::new(*addr, port)]), + NetworkAddress::Hostname(hostname) => { + Ok((hostname.as_str(), port).to_socket_addrs()?.collect()) + } + } + } +} + +impl FromStr for NetworkAddress { + type Err = std::io::Error; + + fn from_str(s: &str) -> Result { + if let Ok(ip_addr) = s.parse() { + return Ok(NetworkAddress::IpAddr(ip_addr)); + } + todo!() + } +} + +impl Display for NetworkAddress { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + NetworkAddress::IpAddr(ip_addr) => ip_addr.fmt(f), + NetworkAddress::Hostname(hostname) => hostname.fmt(f), + } + } +} + pub type MixLayer = u8; #[derive(Debug, Clone)] diff --git a/common/topology/src/mix.rs b/common/topology/src/mix.rs index a97e342745..291b7fabdc 100644 --- a/common/topology/src/mix.rs +++ b/common/topology/src/mix.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::filter; +use crate::{filter, NetworkAddress}; use crypto::asymmetric::{encryption, identity}; use mixnet_contract::MixNodeBond; use nymsphinx_addressing::nodes::NymNodeRoutingAddress; @@ -84,7 +84,10 @@ pub struct Node { // on the network at a type, right? pub stake: u128, pub location: String, - pub host: SocketAddr, + pub host: NetworkAddress, + // we're keeping this as separate resolved field since we do not want to be resolving the potential + // hostname every time we want to construct a path via this node + pub mix_host: SocketAddr, pub identity_key: identity::PublicKey, pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519 pub layer: u64, @@ -99,7 +102,9 @@ impl filter::Versioned for Node { impl<'a> From<&'a Node> for SphinxNode { fn from(node: &'a Node) -> Self { - let node_address_bytes = NymNodeRoutingAddress::from(node.host).try_into().unwrap(); + let node_address_bytes = NymNodeRoutingAddress::from(node.mix_host) + .try_into() + .unwrap(); SphinxNode::new(node_address_bytes, (&node.sphinx_key).into()) } @@ -112,6 +117,19 @@ impl<'a> TryFrom<&'a MixNodeBond> for Node { if bond.amount.len() > 1 { return Err(MixnodeConversionError::InvalidStake); } + + let host: NetworkAddress = bond.mix_node.host.parse().map_err(|err| { + MixnodeConversionError::InvalidAddress(bond.mix_node.host.clone(), err) + })?; + + // try to completely resolve the host in the mix situation to avoid doing it every + // single time we want to construct a path + let mix_host = host + .to_socket_addrs(bond.mix_node.mix_port) + .map_err(|err| { + MixnodeConversionError::InvalidAddress(bond.mix_node.host.clone(), err) + })?[0]; + Ok(Node { owner: bond.owner.as_str().to_owned(), stake: bond @@ -120,9 +138,8 @@ impl<'a> TryFrom<&'a MixNodeBond> for Node { .map(|stake| stake.amount.into()) .unwrap_or(0), location: bond.mix_node.location.clone(), - host: bond.mix_node.try_resolve_hostname().map_err(|err| { - MixnodeConversionError::InvalidAddress(bond.mix_node.host.clone(), err) - })?, + host, + mix_host, identity_key: identity::PublicKey::from_base58_string(&bond.mix_node.identity_key)?, sphinx_key: encryption::PublicKey::from_base58_string(&bond.mix_node.sphinx_key)?, layer: bond.mix_node.layer, diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index f5ad70456c..3e285b65ad 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -106,21 +106,23 @@ fn show_bonding_info(config: &Config) { "\nTo bond your gateway you will [most likely] need to provide the following: Identity key: {} Sphinx key: {} - Mix Host: {} - Clients Host: {} + Host: {} + Mix Port: {} + Clients Port: {} Location: [physical location of your node's server] Version: {} ", identity_keypair.public_key().to_base58_string(), sphinx_keypair.public_key().to_base58_string(), - config.get_mix_announce_address(), - config.get_clients_announce_address(), + config.get_announce_address(), + config.get_mix_port(), + config.get_clients_port(), config.get_version(), ); } pub fn execute(matches: &ArgMatches) { - let id = matches.value_of("id").unwrap(); + let id = matches.value_of(ID_ARG_NAME).unwrap(); println!("Initialising gateway {}...", id); let already_init = if Config::default_config_file_path(id).exists() { diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index e83645c724..6c1b8e2041 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -156,14 +156,8 @@ pub fn execute(matches: &ArgMatches) { let sphinx_keypair = load_sphinx_keys(&pathfinder); let identity = load_identity_keys(&pathfinder); - let mix_listening_ip_string = config.get_mix_listening_address().ip().to_string(); - if special_addresses().contains(&mix_listening_ip_string.as_ref()) { - show_binding_warning(mix_listening_ip_string); - } - - let clients_listening_ip_string = config.get_clients_listening_address().ip().to_string(); - if special_addresses().contains(&clients_listening_ip_string.as_ref()) { - show_binding_warning(clients_listening_ip_string); + if special_addresses().contains(&&*config.get_listening_address()) { + show_binding_warning(config.get_listening_address()); } println!( @@ -172,21 +166,12 @@ pub fn execute(matches: &ArgMatches) { ); println!( - "Listening for incoming sphinx packets on {}", - config.get_mix_listening_address() + "Listening for incoming packets on {}", + config.get_listening_address() ); println!( - "Announcing the following socket address for sphinx packets: {}", - config.get_mix_announce_address() - ); - - println!( - "Listening for incoming clients packets on {}", - config.get_clients_listening_address() - ); - println!( - "Announcing the following socket address for clients packets: {}", - config.get_clients_announce_address() + "Announcing the following address: {}", + config.get_announce_address() ); println!( diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 1dad80b084..398bb4e8fb 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -3,11 +3,8 @@ use crate::config::template::config_template; use config::{deserialize_duration, deserialize_validators, NymConfig}; -use log::*; use serde::{Deserialize, Serialize}; -use std::net::{IpAddr, SocketAddr}; use std::path::PathBuf; -use std::str::FromStr; use std::time::Duration; pub mod persistence; @@ -58,8 +55,6 @@ pub fn missing_vec_string_value() -> Vec { pub struct Config { gateway: Gateway, - mixnet_endpoint: MixnetEndpoint, - clients_endpoint: ClientsEndpoint, #[serde(default)] @@ -155,169 +150,38 @@ impl Config { self } - pub fn with_mix_listening_host>(mut self, host: S) -> Self { - // see if the provided `host` is just an ip address or ip:port - let host = host.into(); - - // is it ip:port? - match SocketAddr::from_str(host.as_ref()) { - Ok(socket_addr) => { - self.mixnet_endpoint.listening_address = socket_addr; - self - } - // try just for ip - Err(_) => match IpAddr::from_str(host.as_ref()) { - Ok(ip_addr) => { - self.mixnet_endpoint.listening_address.set_ip(ip_addr); - self - } - Err(_) => { - error!( - "failed to make any changes to config - invalid host {}", - host - ); - self - } - }, - } - } - - pub fn with_mix_listening_port(mut self, port: u16) -> Self { - self.mixnet_endpoint.listening_address.set_port(port); + pub fn with_listening_address>(mut self, listening_address: S) -> Self { + self.gateway.listening_address = listening_address.into(); self } - pub fn with_mix_announce_host>(mut self, host: S) -> Self { - // this is slightly more complicated as we store announce information as String, - // since it might not necessarily be a valid SocketAddr (say `nymtech.net:8080` is a valid - // announce address, yet invalid SocketAddr` - - // first let's see if we received host:port or just host part of an address - let host = host.into(); - match host.split(':').count() { - 1 => { - // we provided only 'host' part so we are going to reuse existing port - self.mixnet_endpoint.announce_address = - format!("{}:{}", host, self.mixnet_endpoint.listening_address.port()); - self - } - 2 => { - // we provided 'host:port' so just put the whole thing there - self.mixnet_endpoint.announce_address = host; - self - } - _ => { - // we provided something completely invalid, so don't try to parse it - error!( - "failed to make any changes to config - invalid announce host {}", - host - ); - self - } - } - } - - pub fn mix_announce_host_from_listening_host(mut self) -> Self { - self.mixnet_endpoint.announce_address = self.mixnet_endpoint.listening_address.to_string(); + pub fn with_announce_address>(mut self, announce_address: S) -> Self { + self.gateway.announce_address = announce_address.into(); self } - pub fn with_mix_announce_port(mut self, port: u16) -> Self { - let current_host: Vec<_> = self.mixnet_endpoint.announce_address.split(':').collect(); - debug_assert_eq!(current_host.len(), 2); - self.mixnet_endpoint.announce_address = format!("{}:{}", current_host[0], port); + pub fn with_mix_port(mut self, port: u16) -> Self { + self.gateway.mix_port = port; self } - pub fn with_clients_listening_host>(mut self, host: S) -> Self { - // see if the provided `host` is just an ip address or ip:port - let host = host.into(); - - // is it ip:port? - match SocketAddr::from_str(host.as_ref()) { - Ok(socket_addr) => { - self.clients_endpoint.listening_address = socket_addr; - self - } - // try just for ip - Err(_) => match IpAddr::from_str(host.as_ref()) { - Ok(ip_addr) => { - self.clients_endpoint.listening_address.set_ip(ip_addr); - self - } - Err(_) => { - error!( - "failed to make any changes to config - invalid host {}", - host - ); - self - } - }, - } - } - - pub fn clients_announce_host_from_listening_host(mut self) -> Self { - self.clients_endpoint.announce_address = format!( - "ws://{}", - self.clients_endpoint.listening_address.to_string() - ); + pub fn with_clients_port(mut self, port: u16) -> Self { + self.gateway.clients_port = port; self } - pub fn with_clients_listening_port(mut self, port: u16) -> Self { - self.clients_endpoint.listening_address.set_port(port); + pub fn announce_host_from_listening_host(mut self) -> Self { + self.gateway.announce_address = self.gateway.listening_address.clone(); self } - pub fn with_clients_announce_host>(mut self, host: S) -> Self { - // this is slightly more complicated as we store announce information as String, - // since it might not necessarily be a valid SocketAddr (say `nymtech.net:8080` is a valid - // announce address, yet invalid SocketAddr` - - // first let's see if we received host:port or just host part of an address - let host = host.into(); - match host.split(':').count() { - 1 => { - // we provided only 'host' part so we are going to reuse existing port - self.clients_endpoint.announce_address = format!( - "{}:{}", - host, - self.clients_endpoint.listening_address.port() - ); - // make sure it has 'ws' prefix (by extension it also includes 'wss') - if !self.clients_endpoint.announce_address.starts_with("ws") { - self.clients_endpoint.announce_address = - format!("ws://{}", self.clients_endpoint.announce_address); - } - self - } - 2 => { - // we provided 'host:port' so just put the whole thing there - self.clients_endpoint.announce_address = host; - // make sure it has 'ws' prefix (by extension it also includes 'wss') - if !self.clients_endpoint.announce_address.starts_with("ws") { - self.clients_endpoint.announce_address = - format!("ws://{}", self.clients_endpoint.announce_address); - } - self - } - _ => { - // we provided something completely invalid, so don't try to parse it - error!( - "failed to make any changes to config - invalid announce host {}", - host - ); - self - } - } - } - - pub fn with_clients_announce_port(mut self, port: u16) -> Self { - let current_host: Vec<_> = self.clients_endpoint.announce_address.split(':').collect(); - debug_assert_eq!(current_host.len(), 2); - self.clients_endpoint.announce_address = format!("{}:{}", current_host[0], port); - self - } + // pub fn clients_announce_host_from_listening_host(mut self) -> Self { + // self.clients_endpoint.announce_address = format!( + // "ws://{}", + // self.clients_endpoint.listening_address.to_string() + // ); + // self + // } pub fn with_custom_clients_inboxes>(mut self, inboxes_dir: S) -> Self { self.clients_endpoint.inboxes_directory = PathBuf::from(inboxes_dir.into()); @@ -363,20 +227,20 @@ impl Config { self.gateway.mixnet_contract_address.clone() } - pub fn get_mix_listening_address(&self) -> SocketAddr { - self.mixnet_endpoint.listening_address + pub fn get_listening_address(&self) -> String { + self.gateway.listening_address.clone() } - pub fn get_mix_announce_address(&self) -> String { - self.mixnet_endpoint.announce_address.clone() + pub fn get_announce_address(&self) -> String { + self.gateway.announce_address.clone() } - pub fn get_clients_listening_address(&self) -> SocketAddr { - self.clients_endpoint.listening_address + pub fn get_mix_port(&self) -> u16 { + self.gateway.mix_port } - pub fn get_clients_announce_address(&self) -> String { - self.clients_endpoint.announce_address.clone() + pub fn get_clients_port(&self) -> u16 { + self.gateway.clients_port } pub fn get_clients_inboxes_dir(&self) -> PathBuf { @@ -429,6 +293,22 @@ pub struct Gateway { /// ID specifies the human readable ID of this particular gateway. id: String, + /// Address to which this mixnode will bind to and will be listening for packets. + listening_address: String, + + /// Optional address announced to the validator for the clients to connect to. + /// It is useful, say, in NAT scenarios or wanting to more easily update actual IP address + /// later on by using name resolvable with a DNS query, such as `nymtech.net`. + announce_address: String, + + /// Port used for listening for all mixnet traffic. + /// (default: 1789) + mix_port: u16, + + /// Port used for listening for all client-related traffic. + /// (default: 9000) + clients_port: u16, + /// Path to file containing private identity key. private_identity_key_file: PathBuf, @@ -481,6 +361,10 @@ impl Default for Gateway { Gateway { version: env!("CARGO_PKG_VERSION").to_string(), id: "".to_string(), + listening_address: "0.0.0.0".to_string(), + announce_address: "127.0.0.1".to_string(), + mix_port: DEFAULT_MIX_LISTENING_PORT, + clients_port: DEFAULT_CLIENT_LISTENING_PORT, private_identity_key_file: Default::default(), public_identity_key_file: Default::default(), private_sphinx_key_file: Default::default(), @@ -492,48 +376,9 @@ impl Default for Gateway { } } -#[derive(Debug, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] -pub struct MixnetEndpoint { - /// Socket address to which this gateway will bind to - /// and will be listening for sphinx packets coming from the mixnet. - listening_address: SocketAddr, - - /// Optional address announced to the directory server for the clients to connect to. - /// It is useful, say, in NAT scenarios or wanting to more easily update actual IP address - /// later on by using name resolvable with a DNS query, such as `nymtech.net:8080`. - /// Additionally a custom port can be provided, so both `nymtech.net:8080` and `nymtech.net` - /// are valid announce addresses, while the later will default to whatever port is used for - /// `listening_address`. - announce_address: String, -} - -impl Default for MixnetEndpoint { - fn default() -> Self { - MixnetEndpoint { - listening_address: format!("0.0.0.0:{}", DEFAULT_MIX_LISTENING_PORT) - .parse() - .unwrap(), - announce_address: format!("127.0.0.1:{}", DEFAULT_MIX_LISTENING_PORT), - } - } -} - #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] pub struct ClientsEndpoint { - /// Socket address to which this gateway will bind to - /// and will be listening for data packets coming from the clients. - listening_address: SocketAddr, - - /// Optional address announced to the directory server for the clients to connect to. - /// It is useful, say, in NAT scenarios or wanting to more easily update actual IP address - /// later on by using name resolvable with a DNS query, such as `nymtech.net:8080`. - /// Additionally a custom port can be provided, so both `nymtech.net:8080` and `nymtech.net` - /// are valid announce addresses, while the later will default to whatever port is used for - /// `listening_address`. - announce_address: String, - /// Path to the directory with clients inboxes containing messages stored for them. inboxes_directory: PathBuf, @@ -555,10 +400,6 @@ impl ClientsEndpoint { impl Default for ClientsEndpoint { fn default() -> Self { ClientsEndpoint { - listening_address: format!("0.0.0.0:{}", DEFAULT_CLIENT_LISTENING_PORT) - .parse() - .unwrap(), - announce_address: format!("ws://127.0.0.1:{}", DEFAULT_CLIENT_LISTENING_PORT), inboxes_directory: Default::default(), ledger_path: Default::default(), } diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 9d4793e4d4..c5b07d7101 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -70,9 +70,21 @@ impl Gateway { ack_sender, ); - let listener = mixnet_handling::Listener::new(self.config.get_mix_listening_address()); + let listening_address = match format!( + "{}:{}", + self.config.get_listening_address(), + self.config.get_mix_port() + ) + .parse() + { + Ok(addr) => addr, + Err(err) => { + error!("Failed to correctly parse socket address - {}", err); + process::exit(1); + } + }; - listener.start(connection_handler); + mixnet_handling::Listener::new(listening_address).start(connection_handler); } fn start_client_websocket_listener( @@ -82,11 +94,22 @@ impl Gateway { ) { info!("Starting client [web]socket listener..."); - websocket::Listener::new( - self.config.get_clients_listening_address(), - Arc::clone(&self.identity), + let listening_address = match format!( + "{}:{}", + self.config.get_listening_address(), + self.config.get_clients_port() ) - .start(clients_handler_sender, forwarding_channel); + .parse() + { + Ok(addr) => addr, + Err(err) => { + error!("Failed to correctly parse socket address - {}", err); + process::exit(1); + } + }; + + websocket::Listener::new(listening_address, Arc::clone(&self.identity)) + .start(clients_handler_sender, forwarding_channel); } fn start_packet_forwarder(&self) -> MixForwardingSender { @@ -127,9 +150,6 @@ impl Gateway { // TODO: ask DH whether this function still makes sense in ^0.10 async fn check_if_same_ip_gateway_exists(&self) -> Option { - let announced_mix_host = self.config.get_mix_announce_address(); - let announced_clients_host = self.config.get_clients_announce_address(); - let validator_client_config = validator_client::Config::new( self.config.get_validator_rest_endpoints(), self.config.get_validator_mixnet_contract_address(), @@ -144,12 +164,11 @@ impl Gateway { } }; + let our_host = self.config.get_announce_address(); + existing_gateways .iter() - .find(|node| { - node.gateway.mix_host == announced_mix_host - || node.gateway.clients_host == announced_clients_host - }) + .find(|node| node.gateway.host == our_host) .map(|node| node.gateway().identity_key.clone()) } diff --git a/mixnode/src/commands/run.rs b/mixnode/src/commands/run.rs index 68c07296ba..cffa00393f 100644 --- a/mixnode/src/commands/run.rs +++ b/mixnode/src/commands/run.rs @@ -136,9 +136,8 @@ pub fn execute(matches: &ArgMatches) { let identity_keypair = load_identity_keys(&pathfinder); let sphinx_keypair = load_sphinx_keys(&pathfinder); - let listening_ip_string = config.get_listening_address().ip().to_string(); - if special_addresses().contains(&listening_ip_string.as_ref()) { - show_binding_warning(listening_ip_string); + if special_addresses().contains(&&*config.get_listening_address()) { + show_binding_warning(config.get_listening_address()); } println!( @@ -150,7 +149,7 @@ pub fn execute(matches: &ArgMatches) { config.get_listening_address() ); println!( - "Announcing the following socket address: {}", + "Announcing the following address: {}", config.get_announce_address() ); @@ -158,7 +157,8 @@ pub fn execute(matches: &ArgMatches) { "\nTo bond your mixnode, go to https://web-wallet-finney.nymtech.net/. You will need to provide the following: Identity key: {} Sphinx key: {} - Host: {} + Address: {} + Mix port: {} Layer: {} Location: [physical location of your node's server] Version: {} @@ -166,6 +166,7 @@ pub fn execute(matches: &ArgMatches) { identity_keypair.public_key().to_base58_string(), sphinx_keypair.public_key().to_base58_string(), config.get_announce_address(), + config.get_mix_port(), config.get_layer(), config.get_version(), ); diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index 10d84ed849..e5af5ea822 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -3,11 +3,8 @@ use crate::config::template::config_template; use config::{deserialize_duration, deserialize_validators, NymConfig}; -use log::error; use serde::{Deserialize, Serialize}; -use std::net::{IpAddr, SocketAddr}; use std::path::PathBuf; -use std::str::FromStr; use std::time::Duration; pub mod persistence; @@ -16,7 +13,7 @@ mod template; pub(crate) const MISSING_VALUE: &str = "MISSING VALUE"; // 'MIXNODE' -const DEFAULT_LISTENING_PORT: u16 = 1789; +const DEFAULT_MIX_LISTENING_PORT: u16 = 1789; pub(crate) const DEFAULT_VALIDATOR_REST_ENDPOINTS: &[&str] = &[ "http://testnet-finney-validator.nymtech.net:1317", "http://testnet-finney-validator2.nymtech.net:1317", @@ -152,77 +149,23 @@ impl Config { self } - pub fn with_listening_host>(mut self, host: S) -> Self { - // see if the provided `host` is just an ip address or ip:port - let host = host.into(); - - // is it ip:port? - match SocketAddr::from_str(host.as_ref()) { - Ok(socket_addr) => { - self.mixnode.listening_address = socket_addr; - self - } - // try just for ip - Err(_) => match IpAddr::from_str(host.as_ref()) { - Ok(ip_addr) => { - self.mixnode.listening_address.set_ip(ip_addr); - self - } - Err(_) => { - error!( - "failed to make any changes to config - invalid host {}", - host - ); - self - } - }, - } - } - - pub fn with_listening_port(mut self, port: u16) -> Self { - self.mixnode.listening_address.set_port(port); + pub fn with_listening_address>(mut self, listening_address: S) -> Self { + self.mixnode.listening_address = listening_address.into(); self } - pub fn with_announce_host>(mut self, host: S) -> Self { - // this is slightly more complicated as we store announce information as String, - // since it might not necessarily be a valid SocketAddr (say `nymtech.net:8080` is a valid - // announce address, yet invalid SocketAddr` - - // first lets see if we received host:port or just host part of an address - let host = host.into(); - match host.split(':').count() { - 1 => { - // we provided only 'host' part so we are going to reuse existing port - self.mixnode.announce_address = - format!("{}:{}", host, self.mixnode.listening_address.port()); - self - } - 2 => { - // we provided 'host:port' so just put the whole thing there - self.mixnode.announce_address = host; - self - } - _ => { - // we provided something completely invalid, so don't try to parse it - error!( - "failed to make any changes to config - invalid announce host {}", - host - ); - self - } - } - } - - pub fn announce_host_from_listening_host(mut self) -> Self { - self.mixnode.announce_address = self.mixnode.listening_address.to_string(); + pub fn with_announce_address>(mut self, announce_address: S) -> Self { + self.mixnode.announce_address = announce_address.into(); self } - pub fn with_announce_port(mut self, port: u16) -> Self { - let current_host: Vec<_> = self.mixnode.announce_address.split(':').collect(); - debug_assert_eq!(current_host.len(), 2); - self.mixnode.announce_address = format!("{}:{}", current_host[0], port); + pub fn with_mix_port(mut self, port: u16) -> Self { + self.mixnode.mix_port = port; + self + } + + pub fn announce_address_from_listening_address(mut self) -> Self { + self.mixnode.announce_address = self.mixnode.listening_address.clone(); self } @@ -272,14 +215,18 @@ impl Config { self.mixnode.layer } - pub fn get_listening_address(&self) -> SocketAddr { - self.mixnode.listening_address + pub fn get_listening_address(&self) -> String { + self.mixnode.listening_address.clone() } pub fn get_announce_address(&self) -> String { self.mixnode.announce_address.clone() } + pub fn get_mix_port(&self) -> u16 { + self.mixnode.mix_port + } + pub fn get_packet_forwarding_initial_backoff(&self) -> Duration { self.debug.packet_forwarding_initial_backoff } @@ -349,17 +296,18 @@ pub struct MixNode { /// Layer of this particular mixnode determining its position in the network. layer: u64, - /// Socket address to which this mixnode will bind to and will be listening for packets. - listening_address: SocketAddr, + /// Address to which this mixnode will bind to and will be listening for packets. + listening_address: String, /// Optional address announced to the validator for the clients to connect to. /// It is useful, say, in NAT scenarios or wanting to more easily update actual IP address - /// later on by using name resolvable with a DNS query, such as `nymtech.net:8080`. - /// Additionally a custom port can be provided, so both `nymtech.net:8080` and `nymtech.net` - /// are valid announce addresses, while the later will default to whatever port is used for - /// `listening_address`. + /// later on by using name resolvable with a DNS query, such as `nymtech.net`. announce_address: String, + /// Port used for listening for all mixnet traffic. + /// (default: 1789) + mix_port: u16, + /// Path to file containing private identity key. #[serde(default = "missing_string_value")] private_identity_key_file: PathBuf, @@ -374,7 +322,7 @@ pub struct MixNode { /// Path to file containing public sphinx key. public_sphinx_key_file: PathBuf, - /// Validator server to which the node will be reporting their presence data. + /// Validator server from which the node gets the view on the network. #[serde( deserialize_with = "deserialize_validators", default = "missing_vec_string_value", @@ -415,10 +363,9 @@ impl Default for MixNode { version: env!("CARGO_PKG_VERSION").to_string(), id: "".to_string(), layer: 0, - listening_address: format!("0.0.0.0:{}", DEFAULT_LISTENING_PORT) - .parse() - .unwrap(), - announce_address: format!("127.0.0.1:{}", DEFAULT_LISTENING_PORT), + listening_address: "0.0.0.0".to_string(), + announce_address: "127.0.0.1".to_string(), + mix_port: DEFAULT_MIX_LISTENING_PORT, private_identity_key_file: Default::default(), public_identity_key_file: Default::default(), private_sphinx_key_file: Default::default(), diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 8582c15d0d..7d0dac15d0 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -61,7 +61,7 @@ impl MixNode { let mut config = rocket::config::Config::release_default(); // bind to the same address as we are using for mixnodes - config.address = self.config.get_listening_address().ip(); + config.address = self.config.get_listening_address().parse().unwrap(); let verloc_state = VerlocState::new(atomic_verloc_result); let descriptor = self.descriptor.clone(); @@ -106,9 +106,21 @@ impl MixNode { let connection_handler = ConnectionHandler::new(packet_processor, delay_forwarding_channel); - let listener = Listener::new(self.config.get_listening_address()); + let listening_address = match format!( + "{}:{}", + self.config.get_listening_address(), + self.config.get_mix_port() + ) + .parse() + { + Ok(addr) => addr, + Err(err) => { + error!("Failed to correctly parse socket address - {}", err); + process::exit(1); + } + }; - listener.start(connection_handler); + Listener::new(listening_address).start(connection_handler); } fn start_packet_delay_forwarder( @@ -147,10 +159,20 @@ impl MixNode { // use the same binding address with the HARDCODED port for time being (I don't like that approach personally) - let listening_address = rtt_measurement::replace_port( + let listening_address = match format!( + "{}:{}", self.config.get_listening_address(), - rtt_measurement::DEFAULT_MEASUREMENT_PORT, - ); + rtt_measurement::DEFAULT_MEASUREMENT_PORT + ) + .parse() + { + Ok(addr) => addr, + Err(err) => { + error!("Failed to correctly parse socket address - {}", err); + process::exit(1); + } + }; + let config = rtt_measurement::ConfigBuilder::new() .listening_address(listening_address) .packets_per_node(self.config.get_measurement_packets_per_node()) @@ -186,9 +208,11 @@ impl MixNode { } }; + let our_host = self.config.get_announce_address(); + existing_nodes .iter() - .find(|node| node.mix_node.host == self.config.get_announce_address()) + .find(|node| node.mix_node.host == our_host) .map(|node| node.mix_node.identity_key.clone()) } diff --git a/network-monitor/src/monitor/preparer.rs b/network-monitor/src/monitor/preparer.rs index 8905f5d8b5..a1aba7b924 100644 --- a/network-monitor/src/monitor/preparer.rs +++ b/network-monitor/src/monitor/preparer.rs @@ -408,7 +408,7 @@ impl PacketPreparer { gateway_packets.push(mix_packet.pop().unwrap()); } packets.push(GatewayPackets::new( - node.client_listener, + node.clients_address(), node.identity_key, gateway_packets, )) @@ -461,10 +461,7 @@ impl PacketPreparer { // we are not testing the gateway from our 'good' topology -> it's probably // situation similar to using 'good' qa-topology but testing testnet nodes. let main_gateway_packets = GatewayPackets::new( - self.tested_network - .main_v4_gateway() - .client_listener - .clone(), + self.tested_network.main_v4_gateway().clients_address(), main_gateway_id, mix_packets, ); From 6e24b2681b20fc45dff196b24e7c851711001f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 12:25:29 +0100 Subject: [PATCH 10/24] Using more type restrictive IpAddr rather than String for listening address --- gateway/src/commands/run.rs | 4 +- gateway/src/config/mod.rs | 49 ++++++++++++++++--------- gateway/src/node/mod.rs | 31 ++++------------ mixnode/src/commands/run.rs | 4 +- mixnode/src/config/mod.rs | 73 +++++++++++++++++++++++++++---------- mixnode/src/node/mod.rs | 33 ++++------------- 6 files changed, 105 insertions(+), 89 deletions(-) diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index 6c1b8e2041..1f6136c12e 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -156,8 +156,8 @@ pub fn execute(matches: &ArgMatches) { let sphinx_keypair = load_sphinx_keys(&pathfinder); let identity = load_identity_keys(&pathfinder); - if special_addresses().contains(&&*config.get_listening_address()) { - show_binding_warning(config.get_listening_address()); + if special_addresses().contains(&&*config.get_listening_address().to_string()) { + show_binding_warning(config.get_listening_address().to_string()); } println!( diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 398bb4e8fb..f05dee99b3 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -3,7 +3,9 @@ use crate::config::template::config_template; use config::{deserialize_duration, deserialize_validators, NymConfig}; +use log::error; use serde::{Deserialize, Serialize}; +use std::net::IpAddr; use std::path::PathBuf; use std::time::Duration; @@ -18,7 +20,6 @@ const DEFAULT_CLIENT_LISTENING_PORT: u16 = 9000; pub(crate) const DEFAULT_VALIDATOR_REST_ENDPOINTS: &[&str] = &[ "http://testnet-finney-validator.nymtech.net:1317", "http://testnet-finney-validator2.nymtech.net:1317", - "http://mixnet.club:1317", ]; pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = "hal1k0jntykt7e4g3y88ltc60czgjuqdy4c9c6gv94"; @@ -50,8 +51,19 @@ pub fn missing_vec_string_value() -> Vec { vec![missing_string_value()] } +fn bind_all_address() -> IpAddr { + "0.0.0.0".parse().unwrap() +} + +fn default_mix_port() -> u16 { + DEFAULT_MIX_LISTENING_PORT +} + +fn default_clients_port() -> u16 { + DEFAULT_CLIENT_LISTENING_PORT +} + #[derive(Debug, Default, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] pub struct Config { gateway: Gateway, @@ -151,7 +163,15 @@ impl Config { } pub fn with_listening_address>(mut self, listening_address: S) -> Self { - self.gateway.listening_address = listening_address.into(); + let listening_address_string = listening_address.into(); + if let Ok(ip_addr) = listening_address_string.parse() { + self.gateway.listening_address = ip_addr + } else { + error!( + "failed to change listening address. the provided value ({}) was invalid", + listening_address_string + ) + } self } @@ -171,18 +191,10 @@ impl Config { } pub fn announce_host_from_listening_host(mut self) -> Self { - self.gateway.announce_address = self.gateway.listening_address.clone(); + self.gateway.announce_address = self.gateway.listening_address.to_string(); self } - // pub fn clients_announce_host_from_listening_host(mut self) -> Self { - // self.clients_endpoint.announce_address = format!( - // "ws://{}", - // self.clients_endpoint.listening_address.to_string() - // ); - // self - // } - pub fn with_custom_clients_inboxes>(mut self, inboxes_dir: S) -> Self { self.clients_endpoint.inboxes_directory = PathBuf::from(inboxes_dir.into()); self @@ -227,8 +239,8 @@ impl Config { self.gateway.mixnet_contract_address.clone() } - pub fn get_listening_address(&self) -> String { - self.gateway.listening_address.clone() + pub fn get_listening_address(&self) -> IpAddr { + self.gateway.listening_address } pub fn get_announce_address(&self) -> String { @@ -294,19 +306,23 @@ pub struct Gateway { id: String, /// Address to which this mixnode will bind to and will be listening for packets. - listening_address: String, + #[serde(default = "bind_all_address")] + listening_address: IpAddr, /// Optional address announced to the validator for the clients to connect to. /// It is useful, say, in NAT scenarios or wanting to more easily update actual IP address /// later on by using name resolvable with a DNS query, such as `nymtech.net`. + #[serde(default = "missing_string_value")] announce_address: String, /// Port used for listening for all mixnet traffic. /// (default: 1789) + #[serde(default = "default_mix_port")] mix_port: u16, /// Port used for listening for all client-related traffic. /// (default: 9000) + #[serde(default = "default_clients_port")] clients_port: u16, /// Path to file containing private identity key. @@ -361,7 +377,7 @@ impl Default for Gateway { Gateway { version: env!("CARGO_PKG_VERSION").to_string(), id: "".to_string(), - listening_address: "0.0.0.0".to_string(), + listening_address: bind_all_address(), announce_address: "127.0.0.1".to_string(), mix_port: DEFAULT_MIX_LISTENING_PORT, clients_port: DEFAULT_CLIENT_LISTENING_PORT, @@ -377,7 +393,6 @@ impl Default for Gateway { } #[derive(Debug, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] pub struct ClientsEndpoint { /// Path to the directory with clients inboxes containing messages stored for them. inboxes_directory: PathBuf, diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index c5b07d7101..8552c37a85 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -9,6 +9,7 @@ use crate::node::storage::{inboxes, ClientLedger}; use crypto::asymmetric::{encryption, identity}; use log::*; use mixnet_client::forwarder::{MixForwardingSender, PacketForwarder}; +use std::net::SocketAddr; use std::process; use std::sync::Arc; use tokio::runtime::Runtime; @@ -70,19 +71,10 @@ impl Gateway { ack_sender, ); - let listening_address = match format!( - "{}:{}", + let listening_address = SocketAddr::new( self.config.get_listening_address(), - self.config.get_mix_port() - ) - .parse() - { - Ok(addr) => addr, - Err(err) => { - error!("Failed to correctly parse socket address - {}", err); - process::exit(1); - } - }; + self.config.get_mix_port(), + ); mixnet_handling::Listener::new(listening_address).start(connection_handler); } @@ -94,19 +86,10 @@ impl Gateway { ) { info!("Starting client [web]socket listener..."); - let listening_address = match format!( - "{}:{}", + let listening_address = SocketAddr::new( self.config.get_listening_address(), - self.config.get_clients_port() - ) - .parse() - { - Ok(addr) => addr, - Err(err) => { - error!("Failed to correctly parse socket address - {}", err); - process::exit(1); - } - }; + self.config.get_clients_port(), + ); websocket::Listener::new(listening_address, Arc::clone(&self.identity)) .start(clients_handler_sender, forwarding_channel); diff --git a/mixnode/src/commands/run.rs b/mixnode/src/commands/run.rs index cffa00393f..be4fd76355 100644 --- a/mixnode/src/commands/run.rs +++ b/mixnode/src/commands/run.rs @@ -136,8 +136,8 @@ pub fn execute(matches: &ArgMatches) { let identity_keypair = load_identity_keys(&pathfinder); let sphinx_keypair = load_sphinx_keys(&pathfinder); - if special_addresses().contains(&&*config.get_listening_address()) { - show_binding_warning(config.get_listening_address()); + if special_addresses().contains(&&*config.get_listening_address().to_string()) { + show_binding_warning(config.get_listening_address().to_string()); } println!( diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index e5af5ea822..d3240c975c 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -3,8 +3,10 @@ use crate::config::template::config_template; use config::{deserialize_duration, deserialize_validators, NymConfig}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; +use std::net::{IpAddr, SocketAddr}; use std::path::PathBuf; +use std::str::FromStr; use std::time::Duration; pub mod persistence; @@ -17,7 +19,6 @@ const DEFAULT_MIX_LISTENING_PORT: u16 = 1789; pub(crate) const DEFAULT_VALIDATOR_REST_ENDPOINTS: &[&str] = &[ "http://testnet-finney-validator.nymtech.net:1317", "http://testnet-finney-validator2.nymtech.net:1317", - "http://mixnet.club:1317", ]; pub const DEFAULT_MIXNET_CONTRACT_ADDRESS: &str = "hal1k0jntykt7e4g3y88ltc60czgjuqdy4c9c6gv94"; @@ -55,13 +56,37 @@ pub fn missing_vec_string_value() -> Vec { vec![missing_string_value()] } +fn bind_all_address() -> IpAddr { + "0.0.0.0".parse().unwrap() +} + +fn default_mix_port() -> u16 { + DEFAULT_MIX_LISTENING_PORT +} + +// basically a migration helper that deserialises string representation of a maybe socket addr (like "1.1.1.1:1234") +// into just the ipaddr (like "1.1.1.1") +pub(super) fn de_ipaddr_from_maybe_str_socks_addr<'de, D>( + deserializer: D, +) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + if let Ok(socket_addr) = SocketAddr::from_str(&s) { + Ok(socket_addr.ip()) + } else { + IpAddr::from_str(&s).map_err(serde::de::Error::custom) + } +} + #[derive(Debug, Default, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] pub struct Config { mixnode: MixNode, #[serde(default)] - rtt_measurement: RttMeasurement, + verloc: Verloc, #[serde(default)] logging: Logging, #[serde(default)] @@ -150,7 +175,15 @@ impl Config { } pub fn with_listening_address>(mut self, listening_address: S) -> Self { - self.mixnode.listening_address = listening_address.into(); + let listening_address_string = listening_address.into(); + if let Ok(ip_addr) = listening_address_string.parse() { + self.mixnode.listening_address = ip_addr + } else { + error!( + "failed to change listening address. the provided value ({}) was invalid", + listening_address_string + ) + } self } @@ -165,7 +198,7 @@ impl Config { } pub fn announce_address_from_listening_address(mut self) -> Self { - self.mixnode.announce_address = self.mixnode.listening_address.clone(); + self.mixnode.announce_address = self.mixnode.listening_address.to_string(); self } @@ -215,8 +248,8 @@ impl Config { self.mixnode.layer } - pub fn get_listening_address(&self) -> String { - self.mixnode.listening_address.clone() + pub fn get_listening_address(&self) -> IpAddr { + self.mixnode.listening_address } pub fn get_announce_address(&self) -> String { @@ -252,27 +285,27 @@ impl Config { } pub fn get_measurement_packets_per_node(&self) -> usize { - self.rtt_measurement.packets_per_node + self.verloc.packets_per_node } pub fn get_measurement_packet_timeout(&self) -> Duration { - self.rtt_measurement.packet_timeout + self.verloc.packet_timeout } pub fn get_measurement_connection_timeout(&self) -> Duration { - self.rtt_measurement.connection_timeout + self.verloc.connection_timeout } pub fn get_measurement_delay_between_packets(&self) -> Duration { - self.rtt_measurement.delay_between_packets + self.verloc.delay_between_packets } pub fn get_measurement_tested_nodes_batch_size(&self) -> usize { - self.rtt_measurement.tested_nodes_batch_size + self.verloc.tested_nodes_batch_size } pub fn get_measurement_testing_interval(&self) -> Duration { - self.rtt_measurement.testing_interval + self.verloc.testing_interval } pub fn get_measurement_retry_timeout(&self) -> Duration { - self.rtt_measurement.retry_timeout + self.verloc.retry_timeout } // upgrade-specific @@ -297,7 +330,8 @@ pub struct MixNode { layer: u64, /// Address to which this mixnode will bind to and will be listening for packets. - listening_address: String, + #[serde(deserialize_with = "de_ipaddr_from_maybe_str_socks_addr")] + listening_address: IpAddr, /// Optional address announced to the validator for the clients to connect to. /// It is useful, say, in NAT scenarios or wanting to more easily update actual IP address @@ -306,6 +340,7 @@ pub struct MixNode { /// Port used for listening for all mixnet traffic. /// (default: 1789) + #[serde(default = "default_mix_port")] mix_port: u16, /// Path to file containing private identity key. @@ -363,7 +398,7 @@ impl Default for MixNode { version: env!("CARGO_PKG_VERSION").to_string(), id: "".to_string(), layer: 0, - listening_address: "0.0.0.0".to_string(), + listening_address: bind_all_address(), announce_address: "127.0.0.1".to_string(), mix_port: DEFAULT_MIX_LISTENING_PORT, private_identity_key_file: Default::default(), @@ -389,7 +424,7 @@ impl Default for Logging { #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] -pub struct RttMeasurement { +pub struct Verloc { /// Specifies number of echo packets sent to each node during a measurement run. packets_per_node: usize, @@ -413,9 +448,9 @@ pub struct RttMeasurement { retry_timeout: Duration, } -impl Default for RttMeasurement { +impl Default for Verloc { fn default() -> Self { - RttMeasurement { + Verloc { packets_per_node: DEFAULT_PACKETS_PER_NODE, connection_timeout: DEFAULT_CONNECTION_TIMEOUT, packet_timeout: DEFAULT_PACKET_TIMEOUT, diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 7d0dac15d0..3b5ed2219e 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -17,6 +17,7 @@ use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSende use crypto::asymmetric::{encryption, identity}; use log::{error, info, warn}; use mixnode_common::rtt_measurement::{self, AtomicVerlocResult, RttMeasurer}; +use std::net::SocketAddr; use std::process; use std::sync::Arc; use tokio::runtime::Runtime; @@ -61,7 +62,7 @@ impl MixNode { let mut config = rocket::config::Config::release_default(); // bind to the same address as we are using for mixnodes - config.address = self.config.get_listening_address().parse().unwrap(); + config.address = self.config.get_listening_address(); let verloc_state = VerlocState::new(atomic_verloc_result); let descriptor = self.descriptor.clone(); @@ -106,19 +107,10 @@ impl MixNode { let connection_handler = ConnectionHandler::new(packet_processor, delay_forwarding_channel); - let listening_address = match format!( - "{}:{}", + let listening_address = SocketAddr::new( self.config.get_listening_address(), - self.config.get_mix_port() - ) - .parse() - { - Ok(addr) => addr, - Err(err) => { - error!("Failed to correctly parse socket address - {}", err); - process::exit(1); - } - }; + self.config.get_mix_port(), + ); Listener::new(listening_address).start(connection_handler); } @@ -159,19 +151,10 @@ impl MixNode { // use the same binding address with the HARDCODED port for time being (I don't like that approach personally) - let listening_address = match format!( - "{}:{}", + let listening_address = SocketAddr::new( self.config.get_listening_address(), - rtt_measurement::DEFAULT_MEASUREMENT_PORT - ) - .parse() - { - Ok(addr) => addr, - Err(err) => { - error!("Failed to correctly parse socket address - {}", err); - process::exit(1); - } - }; + rtt_measurement::DEFAULT_MEASUREMENT_PORT, + ); let config = rtt_measurement::ConfigBuilder::new() .listening_address(listening_address) From 6524fa3f9c86ee5b339339137ba4abc61929c196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 12:25:40 +0100 Subject: [PATCH 11/24] Updated config templates --- gateway/src/config/template.rs | 50 ++++++++++++++-------------------- mixnode/src/config/template.rs | 11 ++++---- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index 000aad2368..2ac303b465 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -19,6 +19,9 @@ version = '{{ gateway.version }}' # Human readable ID of this particular gateway. id = '{{ gateway.id }}' +# Socket address to which this gateway will bind to and will be listening for packets. +listening_address = '{{ gateway.listening_address }}' + # Path to file containing private identity key. private_identity_key_file = '{{ gateway.private_identity_key_file }}' @@ -31,7 +34,22 @@ private_sphinx_key_file = '{{ gateway.private_sphinx_key_file }}' # Path to file containing public sphinx key. public_sphinx_key_file = '{{ gateway.public_sphinx_key_file }}' -# Validator server to which the node will be reporting their presence data. +##### additional gateway config options ##### + +# Optional address announced to the directory server for the clients to connect to. +# It is useful, say, in NAT scenarios or wanting to more easily update actual IP address +# later on by using name resolvable with a DNS query, such as `nymtech.net`. +announce_address = '{{ gateway.announce_address }}' + +# Port used for listening for all mixnet traffic. +# (default: 1789) +mix_port = {{ gateway.mix_port }} + +# Port used for listening for all client websocket traffic. +# (default: 9000) +clients_port = {{ gateway.clients_port }} + +# Validator server to which the node will be getting information about the network. validator_rest_urls = [ {{#each gateway.validator_rest_urls }} '{{this}}', @@ -41,41 +59,15 @@ validator_rest_urls = [ # Address of the validator contract managing the network. mixnet_contract_address = '{{ gateway.mixnet_contract_address }}' +##### advanced configuration options ##### + # nym_home_directory specifies absolute path to the home nym gateway directory. # It is expected to use default value and hence .toml file should not redefine this field. nym_root_directory = '{{ gateway.nym_root_directory }}' - - -##### Mixnet endpoint config options ##### - -[mixnet_endpoint] -# Socket address to which this gateway will bind to -# and will be listening for sphinx packets coming from the mixnet. -listening_address = '{{ mixnet_endpoint.listening_address }}' - -# Optional address announced to the directory server for the clients to connect to. -# It is useful, say, in NAT scenarios or wanting to more easily update actual IP address -# later on by using name resolvable with a DNS query, such as `nymtech.net:8080`. -# Additionally a custom port can be provided, so both `nymtech.net:8080` and `nymtech.net` -# are valid announce addresses, while the later will default to whatever port is used for -# `listening_address`. -announce_address = '{{ mixnet_endpoint.announce_address }}' - #### Clients endpoint config options ##### [clients_endpoint] -# Socket address to which this gateway will bind to -# and will be listening for sphinx packets coming from the mixnet. -listening_address = '{{ clients_endpoint.listening_address }}' - -# Optional address announced to the directory server for the clients to connect to. -# It is useful, say, in NAT scenarios or wanting to more easily update actual IP address -# later on by using name resolvable with a DNS query, such as `nymtech.net:8080`. -# Additionally a custom port can be provided, so both `nymtech.net:8080` and `nymtech.net` -# are valid announce addresses, while the later will default to whatever port is used for -# `listening_address`. -announce_address = '{{ clients_endpoint.announce_address }}' # Path to the directory with clients inboxes containing messages stored for them. inboxes_directory = '{{ clients_endpoint.inboxes_directory }}' diff --git a/mixnode/src/config/template.rs b/mixnode/src/config/template.rs index 58299e0bba..dfaae35eae 100644 --- a/mixnode/src/config/template.rs +++ b/mixnode/src/config/template.rs @@ -41,13 +41,14 @@ public_sphinx_key_file = '{{ mixnode.public_sphinx_key_file }}' # Optional address announced to the directory server for the clients to connect to. # It is useful, say, in NAT scenarios or wanting to more easily update actual IP address -# later on by using name resolvable with a DNS query, such as `nymtech.net:8080`. -# Additionally a custom port can be provided, so both `nymtech.net:8080` and `nymtech.net` -# are valid announce addresses, while the later will default to whatever port is used for -# `listening_address`. +# later on by using name resolvable with a DNS query, such as `nymtech.net`. announce_address = '{{ mixnode.announce_address }}' -# Validator server to which the node will be reporting their presence data. +# Port used for listening for all mixnet traffic. +# (default: 1789) +mix_port = {{ mixnode.mix_port }} + +# Validator server to which the node will be getting information about the network. validator_rest_urls = [ {{#each mixnode.validator_rest_urls }} '{{this}}', From 1d4026ec71a09140bcdeb67bd27057d4f9b0c1ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 12:26:06 +0100 Subject: [PATCH 12/24] Tentative upgrade commands, probably to be further changed before release --- gateway/src/commands/upgrade.rs | 96 +++++++++++++++++++++++++++++---- mixnode/src/commands/upgrade.rs | 90 +++++++++++++++++++++++++------ 2 files changed, 158 insertions(+), 28 deletions(-) diff --git a/gateway/src/commands/upgrade.rs b/gateway/src/commands/upgrade.rs index ee9fa4fb1b..31d79a2cd1 100644 --- a/gateway/src/commands/upgrade.rs +++ b/gateway/src/commands/upgrade.rs @@ -1,14 +1,22 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::DEFAULT_MIXNET_CONTRACT_ADDRESS; -use crate::config::{default_validator_rest_endpoints, Config, MISSING_VALUE}; -use clap::{App, Arg, ArgMatches}; -use config::NymConfig; use std::fmt::Display; use std::process; + +use clap::{App, Arg, ArgMatches}; + +use config::NymConfig; use version_checker::{parse_version, Version}; +use crate::config::DEFAULT_MIXNET_CONTRACT_ADDRESS; +use crate::config::{default_validator_rest_endpoints, Config, MISSING_VALUE}; + +fn fail_upgrade(from_version: D1, to_version: D2) -> ! { + print_failed_upgrade(from_version, to_version); + process::exit(1) +} + fn print_start_upgrade(from: D1, to: D2) { println!( "\n==================\nTrying to upgrade gateway from {} to {} ...", @@ -45,6 +53,16 @@ pub fn command_args<'a, 'b>() -> App<'a, 'b> { .help("REQUIRED FOR PRE-0.9.0 UPGRADES. Specifies current version of the configuration file to help to determine a valid upgrade path. Valid formats include '0.8.1', 'v0.8.1' or 'V0.8.1'") .takes_value(true) ) + .arg(Arg::with_name("listening-address") + .long("listening-address") + .help("REQUIRED FOR 0.Y.Z UPGRADE. Specifies the listening address of this gateway") + .takes_value(true) + ) + .arg(Arg::with_name("announce-address") + .long("announce-address") + .help("OPTIONAL FOR 0.Y.Z UPGRADE. Specifies the announce address of this gateway. If not provided, it will be set to the same value as listening address") + .takes_value(true) + ) } fn unsupported_upgrade(current_version: Version, config_version: Version) -> ! { @@ -169,8 +187,7 @@ fn minor_010_upgrade( if config.get_validator_mixnet_contract_address() != MISSING_VALUE { eprintln!("existing config seems to have specified mixnet contract address which was only introduced in 0.10.0! Can't perform upgrade."); - print_failed_upgrade(&config_version, &to_version); - process::exit(1); + fail_upgrade(&config_version, &to_version) } println!( @@ -190,8 +207,7 @@ fn minor_010_upgrade( upgraded_config.save_to_file(None).unwrap_or_else(|err| { eprintln!("failed to overwrite config file! - {:?}", err); - print_failed_upgrade(&config_version, &to_version); - process::exit(1); + fail_upgrade(&config_version, &to_version) }); print_successful_upgrade(config_version, to_version); @@ -214,8 +230,58 @@ fn patch_010_upgrade( upgraded_config.save_to_file(None).unwrap_or_else(|err| { eprintln!("failed to overwrite config file! - {:?}", err); - print_failed_upgrade(&config_version, &to_version); - process::exit(1); + fail_upgrade(&config_version, &to_version) + }); + + print_successful_upgrade(config_version, to_version); + + upgraded_config +} + +// TODO: to be renamed once the release version is decided (so presumably either 0.10.2 or 0.11.0) +fn undetermined_version_upgrade( + config: Config, + matches: &ArgMatches, + config_version: &Version, + package_version: &Version, +) -> Config { + // If we decide this version should be tagged with 0.11.0, then the following code will be used instead: + // let to_version = if package_version.major == 0 && package_version.minor == 11 { + // package_version.clone() + // } else { + // Version::new(0, 11, 0) + // }; + let to_version = package_version; + + print_start_upgrade(&config_version, &to_version); + + // normally the proper approach would have been to keep old structs, parse file according to old structs + // and move it to the new ones + // however, considering that at this point of time we don't have many gateways and all + // are run by us, this would be an unnecessary code complication and so just providing + // addresses again during upgrade is I think a better approach. + let listening_address = matches.value_of("listening-address").unwrap_or_else(|| { + eprintln!( + "trying to upgrade to {} without providing proper listening address!", + to_version + ); + fail_upgrade(&config_version, &to_version) + }); + + let announce_address = if let Some(announce_addr) = matches.value_of("announce-address") { + announce_addr.to_string() + } else { + listening_address.to_string() + }; + + let upgraded_config = config + .with_custom_version(to_version.to_string().as_ref()) + .with_listening_address(listening_address) + .with_announce_address(announce_address); + + upgraded_config.save_to_file(None).unwrap_or_else(|err| { + eprintln!("failed to overwrite config file! - {:?}", err); + fail_upgrade(&config_version, &to_version) }); print_successful_upgrade(config_version, to_version); @@ -235,7 +301,15 @@ fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version config = match config_version.major { 0 => match config_version.minor { 9 => minor_010_upgrade(config, matches, &config_version, &package_version), - 10 => patch_010_upgrade(config, matches, &config_version, &package_version), + 10 => match config_version.patch { + 0 => patch_010_upgrade(config, matches, &config_version, &package_version), + _ => undetermined_version_upgrade( + config, + matches, + &config_version, + &package_version, + ), + }, _ => unsupported_upgrade(config_version, package_version), }, _ => unsupported_upgrade(config_version, package_version), diff --git a/mixnode/src/commands/upgrade.rs b/mixnode/src/commands/upgrade.rs index 89940e24a0..847e407306 100644 --- a/mixnode/src/commands/upgrade.rs +++ b/mixnode/src/commands/upgrade.rs @@ -10,12 +10,19 @@ use clap::{App, Arg, ArgMatches}; use config::NymConfig; use crypto::asymmetric::identity; use std::fmt::Display; +use std::net::SocketAddr; use std::path::PathBuf; use std::process; +use std::str::FromStr; use version_checker::{parse_version, Version}; const CURRENT_VERSION_ARG_NAME: &str = "current-version"; +fn fail_upgrade(from_version: D1, to_version: D2) -> ! { + print_failed_upgrade(from_version, to_version); + process::exit(1) +} + fn print_start_upgrade(from: D1, to: D2) { println!( "\n==================\nTrying to upgrade mixnode from {} to {} ...", @@ -126,28 +133,24 @@ fn pre_090_upgrade(from: &str, config: Config) -> Config { if from_version.major == 0 && from_version.minor < 8 { // technically this could be implemented, but is there any point in that? eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead"); - print_failed_upgrade(&from_version, &to_version); - process::exit(1) + fail_upgrade(&from_version, &to_version) } if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 { eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version"); - print_failed_upgrade(&from_version, &to_version); - process::exit(1) + fail_upgrade(&from_version, &to_version) } if config.get_private_identity_key_file() != missing_string_value::() || config.get_public_identity_key_file() != missing_string_value::() { eprintln!("existing config seems to have specified identity keys which were only introduced in 0.9.0! Can't perform upgrade."); - print_failed_upgrade(&from_version, &to_version); - process::exit(1); + fail_upgrade(&from_version, &to_version) } if config.get_validator_rest_endpoints()[0] != missing_string_value::() { eprintln!("existing config seems to have specified new validator rest endpoint which was only introduced in 0.9.0! Can't perform upgrade."); - print_failed_upgrade(&from_version, &to_version); - process::exit(1); + fail_upgrade(&from_version, &to_version) } let mut upgraded_config = config @@ -178,8 +181,7 @@ fn pre_090_upgrade(from: &str, config: Config) -> Config { upgraded_config.save_to_file(None).unwrap_or_else(|err| { eprintln!("failed to overwrite config file! - {:?}", err); - print_failed_upgrade(&from_version, &to_version); - process::exit(1); + fail_upgrade(&from_version, &to_version) }); print_successful_upgrade(from_version, to_version); @@ -203,8 +205,7 @@ fn minor_010_upgrade( if config.get_validator_mixnet_contract_address() != MISSING_VALUE { eprintln!("existing config seems to have specified mixnet contract address which was only introduced in 0.10.0! Can't perform upgrade."); - print_failed_upgrade(&config_version, &to_version); - process::exit(1); + fail_upgrade(&config_version, to_version) } println!( @@ -224,8 +225,7 @@ fn minor_010_upgrade( upgraded_config.save_to_file(None).unwrap_or_else(|err| { eprintln!("failed to overwrite config file! - {:?}", err); - print_failed_upgrade(&config_version, &to_version); - process::exit(1); + fail_upgrade(&config_version, &to_version) }); print_successful_upgrade(config_version, to_version); @@ -249,8 +249,56 @@ fn patch_010_upgrade( upgraded_config.save_to_file(None).unwrap_or_else(|err| { eprintln!("failed to overwrite config file! - {:?}", err); - print_failed_upgrade(&config_version, &to_version); - process::exit(1); + fail_upgrade(&config_version, to_version) + }); + + print_successful_upgrade(config_version, to_version); + + upgraded_config +} + +// TODO: to be renamed once the release version is decided (so presumably either 0.10.2 or 0.11.0) +fn undetermined_version_upgrade( + config: Config, + _matches: &ArgMatches, + config_version: &Version, + package_version: &Version, +) -> Config { + // If we decide this version should be tagged with 0.11.0, then the following code will be used instead: + // let to_version = if package_version.major == 0 && package_version.minor == 11 { + // package_version.clone() + // } else { + // Version::new(0, 11, 0) + // }; + let to_version = package_version; + + print_start_upgrade(&config_version, &to_version); + + let current_annnounce_addr = config.get_announce_address(); + // try to parse it as socket address directly + let (announce_address, custom_mix_port) = match SocketAddr::from_str(¤t_annnounce_addr) { + Ok(addr) => (addr.ip().to_string(), addr.port()), + Err(_) => { + let announce_split = current_annnounce_addr.split(':').collect::>(); + if announce_split.len() != 2 { + eprintln!("failed to correctly parse current announce host"); + fail_upgrade(&config_version, &to_version) + } + ( + announce_split[0].to_string(), + announce_split[1].parse().unwrap(), + ) + } + }; + + let upgraded_config = config + .with_custom_version(to_version.to_string().as_ref()) + .with_announce_address(announce_address) + .with_mix_port(custom_mix_port); + + upgraded_config.save_to_file(None).unwrap_or_else(|err| { + eprintln!("failed to overwrite config file! - {:?}", err); + fail_upgrade(&config_version, to_version) }); print_successful_upgrade(config_version, to_version); @@ -270,7 +318,15 @@ fn do_upgrade(mut config: Config, matches: &ArgMatches, package_version: Version config = match config_version.major { 0 => match config_version.minor { 9 => minor_010_upgrade(config, matches, &config_version, &package_version), - 10 => patch_010_upgrade(config, matches, &config_version, &package_version), + 10 => match config_version.patch { + 0 => patch_010_upgrade(config, matches, &config_version, &package_version), + _ => undetermined_version_upgrade( + config, + matches, + &config_version, + &package_version, + ), + }, _ => unsupported_upgrade(config_version, package_version), }, _ => unsupported_upgrade(config_version, package_version), From 07f2f9c39e432da203288d490b2a2abd642c13bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 12:46:38 +0100 Subject: [PATCH 13/24] Fixed mixnet contract test fixtures --- common/mixnet-contract/src/gateway.rs | 7 ------- contracts/mixnet/src/support/tests.rs | 12 ++++++++---- contracts/mixnet/src/transactions.rs | 8 ++++---- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/common/mixnet-contract/src/gateway.rs b/common/mixnet-contract/src/gateway.rs index 8285c4a641..c474d20a41 100644 --- a/common/mixnet-contract/src/gateway.rs +++ b/common/mixnet-contract/src/gateway.rs @@ -39,13 +39,6 @@ impl Gateway { version, } } - - // pub fn try_resolve_hostname(&self) -> Result { - // self.mix_host - // .to_socket_addrs()? - // .next() - // .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "no valid socket address")) - // } } #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] diff --git a/contracts/mixnet/src/support/tests.rs b/contracts/mixnet/src/support/tests.rs index 79bb07c816..8b3ee0dc37 100644 --- a/contracts/mixnet/src/support/tests.rs +++ b/contracts/mixnet/src/support/tests.rs @@ -107,6 +107,7 @@ pub mod helpers { pub fn mix_node_fixture() -> MixNode { MixNode::new( "mix.node.org".to_string(), + 1789, 1, "Sweden".to_string(), "sphinx".to_string(), @@ -118,6 +119,7 @@ pub mod helpers { pub fn mixnode_bond_fixture() -> MixNodeBond { let mix_node = MixNode::new( "1.1.1.1".to_string(), + 1789, 1, "London".to_string(), "1234".to_string(), @@ -129,8 +131,9 @@ pub mod helpers { pub fn gateway_fixture() -> Gateway { Gateway::new( - "1.1.1.1:1234".to_string(), - "ws://1.1.1.1:1235".to_string(), + "1.1.1.1".to_string(), + 1789, + 9000, "Sweden".to_string(), "sphinx".to_string(), "identity".to_string(), @@ -140,8 +143,9 @@ pub mod helpers { pub fn gateway_bond_fixture() -> GatewayBond { let gateway = Gateway::new( - "1.1.1.1:1234".to_string(), - "ws://1.1.1.1:1235".to_string(), + "1.1.1.1".to_string(), + 1789, + 9000, "London".to_string(), "sphinx".to_string(), "identity".to_string(), diff --git a/contracts/mixnet/src/transactions.rs b/contracts/mixnet/src/transactions.rs index 3f70ae364d..7640f4ea5a 100644 --- a/contracts/mixnet/src/transactions.rs +++ b/contracts/mixnet/src/transactions.rs @@ -1210,7 +1210,7 @@ pub mod tests { let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), - mix_host: "1.1.1.1:1789".into(), + host: "1.1.1.1".into(), ..helpers::gateway_fixture() }, }; @@ -1221,7 +1221,7 @@ pub mod tests { let msg = ExecuteMsg::BondGateway { gateway: Gateway { identity_key: "myAwesomeGateway".to_string(), - mix_host: "2.2.2.2:1789".into(), + host: "2.2.2.2".into(), ..helpers::gateway_fixture() }, }; @@ -1230,12 +1230,12 @@ pub mod tests { // make sure the host information was updated assert_eq!( - "2.2.2.2:1789".to_string(), + "2.2.2.2".to_string(), gateways_read(deps.as_ref().storage) .load("myAwesomeGateway".as_bytes()) .unwrap() .gateway - .mix_host + .host ); } From 53253d443cadf2f5752f7da0ba3a9ac16eb625ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 12:58:24 +0100 Subject: [PATCH 14/24] Further missing test adjustments --- common/nymsphinx/src/receiver.rs | 14 +++++++++----- common/topology/src/lib.rs | 8 +++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/common/nymsphinx/src/receiver.rs b/common/nymsphinx/src/receiver.rs index e2523fdabf..6898ea6c86 100644 --- a/common/nymsphinx/src/receiver.rs +++ b/common/nymsphinx/src/receiver.rs @@ -217,7 +217,8 @@ mod message_receiver { owner: "foomp1".to_string(), stake: 123, location: "unknown".to_string(), - host: "10.20.30.40:1789".parse().unwrap(), + host: "10.20.30.40".parse().unwrap(), + mix_host: "10.20.30.40:1789".parse().unwrap(), identity_key: identity::PublicKey::from_base58_string( "3ebjp1Fb9hdcS1AR6AZihgeJiMHkB5jjJUsvqNnfQwU7", ) @@ -237,7 +238,8 @@ mod message_receiver { owner: "foomp2".to_string(), stake: 123, location: "unknown".to_string(), - host: "11.21.31.41:1789".parse().unwrap(), + host: "11.21.31.41".parse().unwrap(), + mix_host: "11.21.31.41:1789".parse().unwrap(), identity_key: identity::PublicKey::from_base58_string( "D6YaMzLSY7mANtSQRKXsmMZpqgqiVkeiagKM4V4oFPFr", ) @@ -257,7 +259,8 @@ mod message_receiver { owner: "foomp3".to_string(), stake: 123, location: "unknown".to_string(), - host: "12.22.32.42:1789".parse().unwrap(), + host: "12.22.32.42".parse().unwrap(), + mix_host: "12.22.32.42:1789".parse().unwrap(), identity_key: identity::PublicKey::from_base58_string( "GkWDysw4AjESv1KiAiVn7JzzCMJeksxNSXVfr1PpX8wD", ) @@ -278,8 +281,9 @@ mod message_receiver { owner: "foomp4".to_string(), stake: 123, location: "unknown".to_string(), - client_listener: "ws://1.2.3.4:9000".to_string(), - mixnet_listener: "1.2.3.4:1789".parse().unwrap(), + host: "1.2.3.4".parse().unwrap(), + mix_host: "1.2.3.4:1789".parse().unwrap(), + clients_port: 9000, identity_key: identity::PublicKey::from_base58_string( "FioFa8nMmPpQnYi7JyojoTuwGLeyNS8BF4ChPr29zUML", ) diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index 316d8c90c3..bfdca9aaec 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -61,9 +61,10 @@ impl FromStr for NetworkAddress { fn from_str(s: &str) -> Result { if let Ok(ip_addr) = s.parse() { - return Ok(NetworkAddress::IpAddr(ip_addr)); + Ok(NetworkAddress::IpAddr(ip_addr)) + } else { + Ok(NetworkAddress::Hostname(s.to_string())) } - todo!() } } @@ -289,7 +290,8 @@ mod converting_mixes_to_vec { owner: "N/A".to_string(), stake: 0, location: "London".to_string(), - host: "3.3.3.3:1789".parse().unwrap(), + host: "3.3.3.3".parse().unwrap(), + mix_host: "3.3.3.3:1789".parse().unwrap(), identity_key: identity::PublicKey::from_base58_string( "3ebjp1Fb9hdcS1AR6AZihgeJiMHkB5jjJUsvqNnfQwU7", ) From 0a5f6f2ca7c1b042a6357e5f17c48097ed91e989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 15:25:23 +0100 Subject: [PATCH 15/24] Added verloc and http port fields to config --- mixnode/src/config/mod.rs | 41 ++++++++++++++++++++++++++++++++++ mixnode/src/config/template.rs | 8 +++++++ 2 files changed, 49 insertions(+) diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index d3240c975c..19447dbdca 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -16,6 +16,9 @@ pub(crate) const MISSING_VALUE: &str = "MISSING VALUE"; // 'MIXNODE' const DEFAULT_MIX_LISTENING_PORT: u16 = 1789; +const DEFAULT_VERLOC_LISTENING_PORT: u16 = 1790; +const DEFAULT_HTTP_API_LISTENING_PORT: u16 = 8000; + pub(crate) const DEFAULT_VALIDATOR_REST_ENDPOINTS: &[&str] = &[ "http://testnet-finney-validator.nymtech.net:1317", "http://testnet-finney-validator2.nymtech.net:1317", @@ -64,6 +67,14 @@ fn default_mix_port() -> u16 { DEFAULT_MIX_LISTENING_PORT } +fn default_verloc_port() -> u16 { + DEFAULT_VERLOC_LISTENING_PORT +} + +fn default_http_api_port() -> u16 { + DEFAULT_HTTP_API_LISTENING_PORT +} + // basically a migration helper that deserialises string representation of a maybe socket addr (like "1.1.1.1:1234") // into just the ipaddr (like "1.1.1.1") pub(super) fn de_ipaddr_from_maybe_str_socks_addr<'de, D>( @@ -197,6 +208,16 @@ impl Config { self } + pub fn with_verloc_port(mut self, port: u16) -> Self { + self.mixnode.verloc_port = port; + self + } + + pub fn with_http_api_port(mut self, port: u16) -> Self { + self.mixnode.http_api_port = port; + self + } + pub fn announce_address_from_listening_address(mut self) -> Self { self.mixnode.announce_address = self.mixnode.listening_address.to_string(); self @@ -260,6 +281,14 @@ impl Config { self.mixnode.mix_port } + pub fn get_verloc_port(&self) -> u16 { + self.mixnode.verloc_port + } + + pub fn get_http_api_port(&self) -> u16 { + self.mixnode.http_api_port + } + pub fn get_packet_forwarding_initial_backoff(&self) -> Duration { self.debug.packet_forwarding_initial_backoff } @@ -343,6 +372,16 @@ pub struct MixNode { #[serde(default = "default_mix_port")] mix_port: u16, + /// Port used for listening for verloc traffic. + /// (default: 1790) + #[serde(default = "default_verloc_port")] + verloc_port: u16, + + /// Port used for listening for http requests. + /// (default: 8000) + #[serde(default = "default_http_api_port")] + http_api_port: u16, + /// Path to file containing private identity key. #[serde(default = "missing_string_value")] private_identity_key_file: PathBuf, @@ -401,6 +440,8 @@ impl Default for MixNode { listening_address: bind_all_address(), announce_address: "127.0.0.1".to_string(), mix_port: DEFAULT_MIX_LISTENING_PORT, + verloc_port: DEFAULT_VERLOC_LISTENING_PORT, + http_api_port: DEFAULT_HTTP_API_LISTENING_PORT, private_identity_key_file: Default::default(), public_identity_key_file: Default::default(), private_sphinx_key_file: Default::default(), diff --git a/mixnode/src/config/template.rs b/mixnode/src/config/template.rs index dfaae35eae..404dacb409 100644 --- a/mixnode/src/config/template.rs +++ b/mixnode/src/config/template.rs @@ -48,6 +48,14 @@ announce_address = '{{ mixnode.announce_address }}' # (default: 1789) mix_port = {{ mixnode.mix_port }} +# Port used for listening for verloc traffic. +# (default: 1790) +verloc_port = {{ mixnode.verloc_port }} + +# Port used for listening for http requests. +# (default: 8000) +http_api_port = {{ mixnode.http_api_port }} + # Validator server to which the node will be getting information about the network. validator_rest_urls = [ {{#each mixnode.validator_rest_urls }} From 35cddab3bddee94a1f34cbe7d1dbcbad6c47edf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 15:33:57 +0100 Subject: [PATCH 16/24] Introduced cli arguments for verloc and http ports --- mixnode/src/commands/init.rs | 14 +++++++++++++- mixnode/src/commands/mod.rs | 24 ++++++++++++++++++++++++ mixnode/src/commands/run.rs | 14 +++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/mixnode/src/commands/init.rs b/mixnode/src/commands/init.rs index 4edba5ecd0..b356832dd5 100644 --- a/mixnode/src/commands/init.rs +++ b/mixnode/src/commands/init.rs @@ -37,7 +37,19 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { .arg( Arg::with_name(MIX_PORT_ARG_NAME) .long(MIX_PORT_ARG_NAME) - .help("The port on which the mixnode will be listening") + .help("The port on which the mixnode will be listening for mix packets") + .takes_value(true), + ) + .arg( + Arg::with_name(VERLOC_PORT_ARG_NAME) + .long(VERLOC_PORT_ARG_NAME) + .help("The port on which the mixnode will be listening for verloc packets") + .takes_value(true), + ) + .arg( + Arg::with_name(HTTP_API_PORT_ARG_NAME) + .long(HTTP_API_PORT_ARG_NAME) + .help("The port on which the mixnode will be listening for http requests") .takes_value(true), ) .arg( diff --git a/mixnode/src/commands/mod.rs b/mixnode/src/commands/mod.rs index 0cd690220b..97e49a4d46 100644 --- a/mixnode/src/commands/mod.rs +++ b/mixnode/src/commands/mod.rs @@ -15,6 +15,8 @@ pub(crate) const ID_ARG_NAME: &str = "id"; pub(crate) const HOST_ARG_NAME: &str = "host"; pub(crate) const LAYER_ARG_NAME: &str = "layer"; pub(crate) const MIX_PORT_ARG_NAME: &str = "mix-port"; +pub(crate) const VERLOC_PORT_ARG_NAME: &str = "verloc-port"; +pub(crate) const HTTP_API_PORT_ARG_NAME: &str = "http-api-port"; pub(crate) const VALIDATORS_ARG_NAME: &str = "validators"; pub(crate) const CONTRACT_ARG_NAME: &str = "mixnet-contract"; pub(crate) const ANNOUNCE_HOST_ARG_NAME: &str = "announce-host"; @@ -58,6 +60,28 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi config = config.with_mix_port(port.unwrap()); } + if let Some(port) = matches + .value_of(VERLOC_PORT_ARG_NAME) + .map(|port| port.parse::()) + { + if let Err(err) = port { + // if port was overridden, it must be parsable + panic!("Invalid verloc port value provided - {:?}", err); + } + config = config.with_verloc_port(port.unwrap()); + } + + if let Some(port) = matches + .value_of(HTTP_API_PORT_ARG_NAME) + .map(|port| port.parse::()) + { + if let Err(err) = port { + // if port was overridden, it must be parsable + panic!("Invalid http api port value provided - {:?}", err); + } + config = config.with_http_api_port(port.unwrap()); + } + if let Some(raw_validators) = matches.value_of(VALIDATORS_ARG_NAME) { config = config.with_custom_validators(parse_validators(raw_validators)); } diff --git a/mixnode/src/commands/run.rs b/mixnode/src/commands/run.rs index be4fd76355..870e351d71 100644 --- a/mixnode/src/commands/run.rs +++ b/mixnode/src/commands/run.rs @@ -37,7 +37,19 @@ pub fn command_args<'a, 'b>() -> App<'a, 'b> { .arg( Arg::with_name(MIX_PORT_ARG_NAME) .long(MIX_PORT_ARG_NAME) - .help("The port on which the mixnode will be listening") + .help("The port on which the mixnode will be listening for mix packets") + .takes_value(true), + ) + .arg( + Arg::with_name(VERLOC_PORT_ARG_NAME) + .long(VERLOC_PORT_ARG_NAME) + .help("The port on which the mixnode will be listening for verloc packets") + .takes_value(true), + ) + .arg( + Arg::with_name(HTTP_API_PORT_ARG_NAME) + .long(HTTP_API_PORT_ARG_NAME) + .help("The port on which the mixnode will be listening for http requests") .takes_value(true), ) .arg( From 4c8f8ff1b630ee5a2ef088976605bbf05bc2b8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 15:38:52 +0100 Subject: [PATCH 17/24] Renamed 'rtt_measurement' to verloc to avoid confusion --- clients/native/src/client/config/template.rs | 2 +- clients/socks5/src/client/config/template.rs | 2 +- common/mixnode-common/src/lib.rs | 2 +- .../src/{rtt_measurement => verloc}/error.rs | 0 .../src/{rtt_measurement => verloc}/listener.rs | 4 ++-- .../src/{rtt_measurement => verloc}/measurement.rs | 0 .../src/{rtt_measurement => verloc}/mod.rs | 6 +++--- .../src/{rtt_measurement => verloc}/packet.rs | 2 +- .../src/{rtt_measurement => verloc}/sender.rs | 6 +++--- gateway/src/config/template.rs | 2 +- mixnode/src/config/template.rs | 2 +- mixnode/src/node/http/verloc.rs | 2 +- mixnode/src/node/mod.rs | 12 ++++++------ 13 files changed, 21 insertions(+), 21 deletions(-) rename common/mixnode-common/src/{rtt_measurement => verloc}/error.rs (100%) rename common/mixnode-common/src/{rtt_measurement => verloc}/listener.rs (98%) rename common/mixnode-common/src/{rtt_measurement => verloc}/measurement.rs (100%) rename common/mixnode-common/src/{rtt_measurement => verloc}/mod.rs (98%) rename common/mixnode-common/src/{rtt_measurement => verloc}/packet.rs (98%) rename common/mixnode-common/src/{rtt_measurement => verloc}/sender.rs (97%) diff --git a/clients/native/src/client/config/template.rs b/clients/native/src/client/config/template.rs index 2c8a69444d..99e1b867c8 100644 --- a/clients/native/src/client/config/template.rs +++ b/clients/native/src/client/config/template.rs @@ -16,7 +16,7 @@ pub(crate) fn config_template() -> &'static str { // While using normal toml marshalling would have been way simpler with less overhead, // I think it's useful to have comments attached to the saved config file to explain behaviour of // particular fields. - // Note: any changes to the template must be reflected in the appropriate structs in mod.rs. + // Note: any changes to the template must be reflected in the appropriate structs in verloc. r#" # This is a TOML config file. # For more information, see https://github.com/toml-lang/toml diff --git a/clients/socks5/src/client/config/template.rs b/clients/socks5/src/client/config/template.rs index 614a7f6ed6..791580718a 100644 --- a/clients/socks5/src/client/config/template.rs +++ b/clients/socks5/src/client/config/template.rs @@ -16,7 +16,7 @@ pub(crate) fn config_template() -> &'static str { // While using normal toml marshalling would have been way simpler with less overhead, // I think it's useful to have comments attached to the saved config file to explain behaviour of // particular fields. - // Note: any changes to the template must be reflected in the appropriate structs in mod.rs. + // Note: any changes to the template must be reflected in the appropriate structs in verloc. r#" # This is a TOML config file. # For more information, see https://github.com/toml-lang/toml diff --git a/common/mixnode-common/src/lib.rs b/common/mixnode-common/src/lib.rs index b0eba79f06..a7e8a54485 100644 --- a/common/mixnode-common/src/lib.rs +++ b/common/mixnode-common/src/lib.rs @@ -13,4 +13,4 @@ // limitations under the License. pub mod cached_packet_processor; -pub mod rtt_measurement; +pub mod verloc; diff --git a/common/mixnode-common/src/rtt_measurement/error.rs b/common/mixnode-common/src/verloc/error.rs similarity index 100% rename from common/mixnode-common/src/rtt_measurement/error.rs rename to common/mixnode-common/src/verloc/error.rs diff --git a/common/mixnode-common/src/rtt_measurement/listener.rs b/common/mixnode-common/src/verloc/listener.rs similarity index 98% rename from common/mixnode-common/src/rtt_measurement/listener.rs rename to common/mixnode-common/src/verloc/listener.rs index 00ea7616f0..0b8025dde7 100644 --- a/common/mixnode-common/src/rtt_measurement/listener.rs +++ b/common/mixnode-common/src/verloc/listener.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::rtt_measurement::error::RttError; -use crate::rtt_measurement::packet::{EchoPacket, ReplyPacket}; +use crate::verloc::error::RttError; +use crate::verloc::packet::{EchoPacket, ReplyPacket}; use bytes::{BufMut, BytesMut}; use crypto::asymmetric::identity; use futures::StreamExt; diff --git a/common/mixnode-common/src/rtt_measurement/measurement.rs b/common/mixnode-common/src/verloc/measurement.rs similarity index 100% rename from common/mixnode-common/src/rtt_measurement/measurement.rs rename to common/mixnode-common/src/verloc/measurement.rs diff --git a/common/mixnode-common/src/rtt_measurement/mod.rs b/common/mixnode-common/src/verloc/mod.rs similarity index 98% rename from common/mixnode-common/src/rtt_measurement/mod.rs rename to common/mixnode-common/src/verloc/mod.rs index 2a351eef49..fc6417ad4f 100644 --- a/common/mixnode-common/src/rtt_measurement/mod.rs +++ b/common/mixnode-common/src/verloc/mod.rs @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::rtt_measurement::listener::PacketListener; -pub use crate::rtt_measurement::measurement::{AtomicVerlocResult, Verloc, VerlocResult}; -use crate::rtt_measurement::sender::{PacketSender, TestedNode}; +use crate::verloc::listener::PacketListener; +pub use crate::verloc::measurement::{AtomicVerlocResult, Verloc, VerlocResult}; +use crate::verloc::sender::{PacketSender, TestedNode}; use crypto::asymmetric::identity; use futures::stream::FuturesUnordered; use futures::StreamExt; diff --git a/common/mixnode-common/src/rtt_measurement/packet.rs b/common/mixnode-common/src/verloc/packet.rs similarity index 98% rename from common/mixnode-common/src/rtt_measurement/packet.rs rename to common/mixnode-common/src/verloc/packet.rs index d25b12b1b7..d899273694 100644 --- a/common/mixnode-common/src/rtt_measurement/packet.rs +++ b/common/mixnode-common/src/verloc/packet.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::rtt_measurement::error::RttError; +use crate::verloc::error::RttError; use crypto::asymmetric::identity::{self, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH}; use std::convert::TryInto; diff --git a/common/mixnode-common/src/rtt_measurement/sender.rs b/common/mixnode-common/src/verloc/sender.rs similarity index 97% rename from common/mixnode-common/src/rtt_measurement/sender.rs rename to common/mixnode-common/src/verloc/sender.rs index 4bbefd2dac..2f45d99854 100644 --- a/common/mixnode-common/src/rtt_measurement/sender.rs +++ b/common/mixnode-common/src/verloc/sender.rs @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::rtt_measurement::error::RttError; -use crate::rtt_measurement::measurement::Measurement; -use crate::rtt_measurement::packet::{EchoPacket, ReplyPacket}; +use crate::verloc::error::RttError; +use crate::verloc::measurement::Measurement; +use crate::verloc::packet::{EchoPacket, ReplyPacket}; use crypto::asymmetric::identity; use log::*; use rand::{thread_rng, Rng}; diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index 2ac303b465..c4522abfdd 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -5,7 +5,7 @@ pub(crate) fn config_template() -> &'static str { // While using normal toml marshalling would have been way simpler with less overhead, // I think it's useful to have comments attached to the saved config file to explain behaviour of // particular fields. - // Note: any changes to the template must be reflected in the appropriate structs in mod.rs. + // Note: any changes to the template must be reflected in the appropriate structs in verloc. r#" # This is a TOML config file. # For more information, see https://github.com/toml-lang/toml diff --git a/mixnode/src/config/template.rs b/mixnode/src/config/template.rs index 404dacb409..2ef91b3f9f 100644 --- a/mixnode/src/config/template.rs +++ b/mixnode/src/config/template.rs @@ -5,7 +5,7 @@ pub(crate) fn config_template() -> &'static str { // While using normal toml marshalling would have been way simpler with less overhead, // I think it's useful to have comments attached to the saved config file to explain behaviour of // particular fields. - // Note: any changes to the template must be reflected in the appropriate structs in mod.rs. + // Note: any changes to the template must be reflected in the appropriate structs in verloc. r#" # This is a TOML config file. # For more information, see https://github.com/toml-lang/toml diff --git a/mixnode/src/node/http/verloc.rs b/mixnode/src/node/http/verloc.rs index 9d71ee67a3..4a9643aa12 100644 --- a/mixnode/src/node/http/verloc.rs +++ b/mixnode/src/node/http/verloc.rs @@ -1,4 +1,4 @@ -use mixnode_common::rtt_measurement::{AtomicVerlocResult, VerlocResult}; +use mixnode_common::verloc::{AtomicVerlocResult, VerlocResult}; use rocket::State; use rocket_contrib::json::Json; diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 3b5ed2219e..d64b8acfdd 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -6,7 +6,7 @@ use crate::node::http::{ description::description, not_found, stats::stats, - verloc::{verloc, VerlocState}, + verloc::{verloc as verlocRoute, VerlocState}, }; use crate::node::listener::connection_handler::packet_processing::PacketProcessor; use crate::node::listener::connection_handler::ConnectionHandler; @@ -16,7 +16,7 @@ use crate::node::node_statistics::NodeStatsWrapper; use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender}; use crypto::asymmetric::{encryption, identity}; use log::{error, info, warn}; -use mixnode_common::rtt_measurement::{self, AtomicVerlocResult, RttMeasurer}; +use mixnode_common::verloc::{self, AtomicVerlocResult, RttMeasurer}; use std::net::SocketAddr; use std::process; use std::sync::Arc; @@ -70,7 +70,7 @@ impl MixNode { tokio::spawn(async move { rocket::build() .configure(config) - .mount("/", routes![verloc, description, stats]) + .mount("/", routes![verlocRoute, description, stats]) .register("/", catchers![not_found]) .manage(verloc_state) .manage(descriptor) @@ -143,7 +143,7 @@ impl MixNode { // if this code exists in the node, it MUST BE compatible let config_version = parse_version(self.config.get_version()).expect("malformed version in the config file"); - let minimum_version = parse_version(rtt_measurement::MINIMUM_NODE_VERSION).unwrap(); + let minimum_version = parse_version(verloc::MINIMUM_NODE_VERSION).unwrap(); if config_version < minimum_version { error!("You seem to have not updated your mixnode configuration file - please run `upgrade` before attempting again"); process::exit(1) @@ -153,10 +153,10 @@ impl MixNode { let listening_address = SocketAddr::new( self.config.get_listening_address(), - rtt_measurement::DEFAULT_MEASUREMENT_PORT, + verloc::DEFAULT_MEASUREMENT_PORT, ); - let config = rtt_measurement::ConfigBuilder::new() + let config = verloc::ConfigBuilder::new() .listening_address(listening_address) .packets_per_node(self.config.get_measurement_packets_per_node()) .connection_timeout(self.config.get_measurement_connection_timeout()) From 035a2554ee96e25ea2439e8d9b151dd98ea74938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 15:49:38 +0100 Subject: [PATCH 18/24] Configurable http api port --- mixnode/src/node/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index d64b8acfdd..1c004a5948 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -61,8 +61,10 @@ impl MixNode { info!("Starting HTTP API on http://localhost:8000"); let mut config = rocket::config::Config::release_default(); + // bind to the same address as we are using for mixnodes config.address = self.config.get_listening_address(); + config.port = self.config.get_http_api_port(); let verloc_state = VerlocState::new(atomic_verloc_result); let descriptor = self.descriptor.clone(); From 035ee3a4029c33d6cca58471529f772eaccb043e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 16:04:21 +0100 Subject: [PATCH 19/24] Added new ports to bond model --- common/mixnet-contract/src/mixnode.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/mixnet-contract/src/mixnode.rs b/common/mixnet-contract/src/mixnode.rs index eb7687ad17..d5fb1f8f3b 100644 --- a/common/mixnet-contract/src/mixnode.rs +++ b/common/mixnet-contract/src/mixnode.rs @@ -11,6 +11,8 @@ use std::fmt::Display; pub struct MixNode { pub host: String, pub mix_port: u16, + pub verloc_port: u16, + pub http_api_port: u16, pub layer: u64, pub location: String, pub sphinx_key: SphinxKey, From 9df360cf63bb4dd9d39d2d7c5e3348b33744aac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 16:08:27 +0100 Subject: [PATCH 20/24] Removed constructors only used in tests To elaborate further, to update Mixnode constructor it would require adding yet two more arguments and at that point the compiler warns about too many arguments --- common/mixnet-contract/src/gateway.rs | 22 -------- common/mixnet-contract/src/mixnode.rs | 22 -------- contracts/mixnet/src/support/tests.rs | 77 ++++++++++++++------------- 3 files changed, 41 insertions(+), 80 deletions(-) diff --git a/common/mixnet-contract/src/gateway.rs b/common/mixnet-contract/src/gateway.rs index c474d20a41..3c8d3c0a9a 100644 --- a/common/mixnet-contract/src/gateway.rs +++ b/common/mixnet-contract/src/gateway.rs @@ -19,28 +19,6 @@ pub struct Gateway { pub version: String, } -impl Gateway { - pub fn new( - host: String, - mix_port: u16, - clients_port: u16, - location: String, - sphinx_key: SphinxKey, - identity_key: IdentityKey, - version: String, - ) -> Self { - Gateway { - host, - mix_port, - clients_port, - location, - sphinx_key, - identity_key, - version, - } - } -} - #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct GatewayBond { pub amount: Vec, diff --git a/common/mixnet-contract/src/mixnode.rs b/common/mixnet-contract/src/mixnode.rs index d5fb1f8f3b..8ceb5c26fa 100644 --- a/common/mixnet-contract/src/mixnode.rs +++ b/common/mixnet-contract/src/mixnode.rs @@ -21,28 +21,6 @@ pub struct MixNode { pub version: String, } -impl MixNode { - pub fn new( - host: String, - mix_port: u16, - layer: u64, - location: String, - sphinx_key: SphinxKey, - identity_key: IdentityKey, - version: String, - ) -> Self { - MixNode { - host, - mix_port, - layer, - location, - sphinx_key, - identity_key, - version, - } - } -} - #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct MixNodeBond { // TODO: diff --git a/contracts/mixnet/src/support/tests.rs b/contracts/mixnet/src/support/tests.rs index 8b3ee0dc37..c591b768a7 100644 --- a/contracts/mixnet/src/support/tests.rs +++ b/contracts/mixnet/src/support/tests.rs @@ -105,52 +105,57 @@ pub mod helpers { } pub fn mix_node_fixture() -> MixNode { - MixNode::new( - "mix.node.org".to_string(), - 1789, - 1, - "Sweden".to_string(), - "sphinx".to_string(), - "identity".to_string(), - "0.10.0".to_string(), - ) + MixNode { + host: "mix.node.org".to_string(), + mix_port: 1789, + verloc_port: 1790, + http_api_port: 8000, + layer: 1, + location: "Sweden".to_string(), + sphinx_key: "sphinx".to_string(), + identity_key: "identity".to_string(), + version: "0.10.0".to_string(), + } } pub fn mixnode_bond_fixture() -> MixNodeBond { - let mix_node = MixNode::new( - "1.1.1.1".to_string(), - 1789, - 1, - "London".to_string(), - "1234".to_string(), - "aaaa".to_string(), - "0.10.0".to_string(), - ); + let mix_node = MixNode { + host: "1.1.1.1".to_string(), + mix_port: 1789, + verloc_port: 1790, + http_api_port: 8000, + layer: 1, + location: "London".to_string(), + sphinx_key: "1234".to_string(), + identity_key: "aaaa".to_string(), + version: "0.10.0".to_string(), + }; MixNodeBond::new(coins(50, DENOM), Addr::unchecked("foo"), mix_node) } pub fn gateway_fixture() -> Gateway { - Gateway::new( - "1.1.1.1".to_string(), - 1789, - 9000, - "Sweden".to_string(), - "sphinx".to_string(), - "identity".to_string(), - "0.10.0".to_string(), - ) + Gateway { + host: "1.1.1.1".to_string(), + mix_port: 1789, + clients_port: 9000, + location: "Sweden".to_string(), + + sphinx_key: "sphinx".to_string(), + identity_key: "identity".to_string(), + version: "0.10.0".to_string(), + } } pub fn gateway_bond_fixture() -> GatewayBond { - let gateway = Gateway::new( - "1.1.1.1".to_string(), - 1789, - 9000, - "London".to_string(), - "sphinx".to_string(), - "identity".to_string(), - "0.10.0".to_string(), - ); + let gateway = Gateway { + host: "1.1.1.1".to_string(), + mix_port: 1789, + clients_port: 9000, + location: "London".to_string(), + sphinx_key: "sphinx".to_string(), + identity_key: "identity".to_string(), + version: "0.10.0".to_string(), + }; GatewayBond::new(coins(50, DENOM), Addr::unchecked("foo"), gateway) } From f0fafe97fe650b31308b4a6e64165f19d2c9c645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 23 Jun 2021 16:08:48 +0100 Subject: [PATCH 21/24] Using verloc with custom ports --- common/mixnode-common/src/verloc/mod.rs | 47 ++++++++++--------------- mixnode/src/node/mod.rs | 14 ++++---- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/common/mixnode-common/src/verloc/mod.rs b/common/mixnode-common/src/verloc/mod.rs index fc6417ad4f..6596f9269c 100644 --- a/common/mixnode-common/src/verloc/mod.rs +++ b/common/mixnode-common/src/verloc/mod.rs @@ -19,7 +19,7 @@ use crypto::asymmetric::identity; use futures::stream::FuturesUnordered; use futures::StreamExt; use log::*; -use std::net::SocketAddr; +use std::net::{SocketAddr, ToSocketAddrs}; use std::sync::Arc; use std::time::Duration; use tokio::task::JoinHandle; @@ -34,9 +34,9 @@ pub(crate) mod sender; // TODO: MUST BE UPDATED BEFORE ACTUAL RELEASE!! pub const MINIMUM_NODE_VERSION: &str = "0.10.1"; -pub const DEFAULT_MEASUREMENT_PORT: u16 = 1790; // by default all of those are overwritten by config data from mixnodes directly +const DEFAULT_VERLOC_PORT: u16 = 1790; const DEFAULT_PACKETS_PER_NODE: usize = 100; const DEFAULT_PACKET_TIMEOUT: Duration = Duration::from_millis(1500); const DEFAULT_CONNECTION_TIMEOUT: Duration = Duration::from_millis(5000); @@ -50,9 +50,6 @@ pub struct Config { /// Minimum semver version of a node (gateway or mixnode) that is capable of replying to echo packets. minimum_compatible_node_version: version_checker::Version, - /// Port on which all nodes are (supposed to be) listening for the measurement packets. - measurement_port: u16, - /// Socket address of this node on which it will be listening for the measurement packets. listening_address: SocketAddr, @@ -102,10 +99,6 @@ impl ConfigBuilder { self.0.minimum_compatible_node_version = version; self } - pub fn measurement_port(mut self, measurement_port: u16) -> Self { - self.0.measurement_port = measurement_port; - self - } pub fn listening_address(mut self, listening_address: SocketAddr) -> Self { self.0.listening_address = listening_address; self @@ -154,9 +147,6 @@ impl ConfigBuilder { if self.0.mixnet_contract_address.is_empty() { panic!("the mixnet contract address must be set") } - if self.0.measurement_port != self.0.listening_address.port() { - panic!("Tried to create listener on different port than the other machines") - } self.0 } } @@ -165,10 +155,7 @@ impl Default for ConfigBuilder { fn default() -> Self { ConfigBuilder(Config { minimum_compatible_node_version: parse_version(MINIMUM_NODE_VERSION).unwrap(), - measurement_port: DEFAULT_MEASUREMENT_PORT, - listening_address: format!("[::]:{}", DEFAULT_MEASUREMENT_PORT) - .parse() - .unwrap(), + listening_address: format!("[::]:{}", DEFAULT_VERLOC_PORT).parse().unwrap(), packets_per_node: DEFAULT_PACKETS_PER_NODE, packet_timeout: DEFAULT_PACKET_TIMEOUT, connection_timeout: DEFAULT_CONNECTION_TIMEOUT, @@ -182,7 +169,7 @@ impl Default for ConfigBuilder { } } -pub struct RttMeasurer { +pub struct VerlocMeasurer { config: Config, packet_sender: Arc, packet_listener: Arc, @@ -195,14 +182,9 @@ pub struct RttMeasurer { results: AtomicVerlocResult, } -// I really don't like this solution, I think nodes should be explicitly announcing that address... -pub fn replace_port(address: SocketAddr, port: u16) -> SocketAddr { - SocketAddr::new(address.ip(), port) -} - -impl RttMeasurer { +impl VerlocMeasurer { pub fn new(config: Config, identity: Arc) -> Self { - RttMeasurer { + VerlocMeasurer { packet_sender: Arc::new(PacketSender::new( Arc::clone(&identity), config.packets_per_node, @@ -312,11 +294,18 @@ impl RttMeasurer { // try to parse the identity and host let node_identity = identity::PublicKey::from_base58_string(node.mix_node.identity_key).ok()?; - let mix_host = node.mix_node.host.parse().ok()?; - Some(TestedNode::new( - replace_port(mix_host, self.config.measurement_port), - node_identity, - )) + + let verloc_host = (&*node.mix_node.host, node.mix_node.verloc_port) + .to_socket_addrs() + .ok()? + .next()?; + + // TODO: possible problem in the future, this does name resolution and theoretically + // if a lot of nodes maliciously mis-configured themselves, it might take a while to resolve them all + // However, maybe it's not a problem as if they are misconfigured, they will eventually be + // pushed out of the network and on top of that, verloc is done in separate task that runs + // only every few hours. + Some(TestedNode::new(verloc_host, node_identity)) }) .collect::>(); diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 1c004a5948..94babb9232 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -16,7 +16,7 @@ use crate::node::node_statistics::NodeStatsWrapper; use crate::node::packet_delayforwarder::{DelayForwarder, PacketDelayForwardSender}; use crypto::asymmetric::{encryption, identity}; use log::{error, info, warn}; -use mixnode_common::verloc::{self, AtomicVerlocResult, RttMeasurer}; +use mixnode_common::verloc::{self, AtomicVerlocResult, VerlocMeasurer}; use std::net::SocketAddr; use std::process; use std::sync::Arc; @@ -137,7 +137,7 @@ impl MixNode { packet_sender } - fn start_rtt_measurer(&self) -> AtomicVerlocResult { + fn start_verloc_measurements(&self) -> AtomicVerlocResult { info!("Starting the round-trip-time measurer..."); // this is a sanity check to make sure we didn't mess up with the minimum version at some point @@ -155,7 +155,7 @@ impl MixNode { let listening_address = SocketAddr::new( self.config.get_listening_address(), - verloc::DEFAULT_MEASUREMENT_PORT, + self.config.get_verloc_port(), ); let config = verloc::ConfigBuilder::new() @@ -171,9 +171,9 @@ impl MixNode { .mixnet_contract_address(self.config.get_validator_mixnet_contract_address()) .build(); - let mut rtt_measurer = RttMeasurer::new(config, Arc::clone(&self.identity_keypair)); - let atomic_verloc_results = rtt_measurer.get_verloc_results_pointer(); - tokio::spawn(async move { rtt_measurer.run().await }); + let mut verloc_measurer = VerlocMeasurer::new(config, Arc::clone(&self.identity_keypair)); + let atomic_verloc_results = verloc_measurer.get_verloc_results_pointer(); + tokio::spawn(async move { verloc_measurer.run().await }); atomic_verloc_results } @@ -235,7 +235,7 @@ impl MixNode { let delay_forwarding_channel = self.start_packet_delay_forwarder(node_stats_update_sender.clone()); self.start_socket_listener(node_stats_update_sender, delay_forwarding_channel); - let atomic_verloc_results= self.start_rtt_measurer(); + let atomic_verloc_results= self.start_verloc_measurements(); self.start_http_api(atomic_verloc_results, node_stats_pointer); info!("Finished nym mixnode startup procedure - it should now be able to receive mix traffic!"); From b56bb7f2265c004cd3d4d1e45036fe94417666ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 24 Jun 2021 10:46:02 +0100 Subject: [PATCH 22/24] Updated typescript models --- clients/validator/src/types.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clients/validator/src/types.ts b/clients/validator/src/types.ts index e2f5f75a23..201fac8943 100644 --- a/clients/validator/src/types.ts +++ b/clients/validator/src/types.ts @@ -9,6 +9,9 @@ export type MixNodeBond = { // TODO: change name to MixNodeBond export type MixNode = { host: string, + mix_port: number, + verloc_port: number, + http_api_port: number, layer: number, location: string, sphinx_key: string, // TODO: camelCase this later once everything else works @@ -23,8 +26,9 @@ export type GatewayBond = { } export type Gateway = { - mix_host: string, - clients_host: string, + host: string, + mix_port: number, + clients_port: number, location: string, sphinx_key: string, identity_key: string, From 23951acdec965553c861110f1aae8d85d71be3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 24 Jun 2021 14:51:44 +0100 Subject: [PATCH 23/24] Fixed trying to log invalid field --- clients/validator/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/validator/src/index.ts b/clients/validator/src/index.ts index 851bea5fd3..a88c27b4e8 100644 --- a/clients/validator/src/index.ts +++ b/clients/validator/src/index.ts @@ -405,7 +405,7 @@ export default class ValidatorClient { if (this.client instanceof NetClient) { const bond = await this.minimumGatewayBond() const result = await this.client.executeContract(this.client.clientAddress, this.contractAddress, {bond_gateway: {gateway: gateway}}, "adding gateway", [bond]).catch((err) => this.handleRequestFailure(err)); - console.log(`account ${this.client.clientAddress} added gateway with ${gateway.mix_host}`); + console.log(`account ${this.client.clientAddress} added gateway with ${gateway.host}`); return result; } else { throw new Error("Tried to bond gateway with a query client") From 3412a0b7bd3a6ba66eedf20551a1aa97fbb62cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 24 Jun 2021 15:51:05 +0100 Subject: [PATCH 24/24] Increased validator client version --- clients/validator/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/validator/package.json b/clients/validator/package.json index acbcb713c5..c1cc85eea5 100644 --- a/clients/validator/package.json +++ b/clients/validator/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nym-validator-client", - "version": "0.12.1", + "version": "0.14.0", "description": "A TypeScript client for interacting with smart contracts in Nym validators", "repository": "https://github.com/nymtech/nym", "main": "./dist/index.js",