From 4a1a4b641504e1a0047147e3979d40117c9ecdb1 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Mon, 28 Mar 2022 13:33:55 +0200 Subject: [PATCH 01/16] Different values for mixes and gateways (#1169) --- validator-api/src/config/mod.rs | 28 +++++++++++++++---- validator-api/src/config/template.rs | 3 +- validator-api/src/main.rs | 21 ++++++++++++++ .../src/network_monitor/monitor/mod.rs | 10 ++++--- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/validator-api/src/config/mod.rs b/validator-api/src/config/mod.rs index 567aba8858..b458777574 100644 --- a/validator-api/src/config/mod.rs +++ b/validator-api/src/config/mod.rs @@ -34,7 +34,8 @@ const DEFAULT_PER_NODE_TEST_PACKETS: usize = 3; const DEFAULT_CACHE_INTERVAL: Duration = Duration::from_secs(30); const DEFAULT_MONITOR_THRESHOLD: u8 = 60; -const DEFAULT_MIN_RELIABILITY: u8 = 50; +const DEFAULT_MIN_MIXNODE_RELIABILITY: u8 = 50; +const DEFAULT_MIN_GATEWAY_RELIABILITY: u8 = 20; #[derive(Debug, Default, Deserialize, PartialEq, Serialize)] pub struct Config { @@ -109,8 +110,8 @@ impl Default for Base { #[serde(default)] pub struct NetworkMonitor { // Mixnodes and gateways with relialability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set. - min_reliability: u8, - + min_mixnode_reliability: u8, // defaults to 50 + min_gateway_reliability: u8, // defaults to 20 /// Specifies whether network monitoring service is enabled in this process. enabled: bool, @@ -192,7 +193,8 @@ impl NetworkMonitor { impl Default for NetworkMonitor { fn default() -> Self { NetworkMonitor { - min_reliability: DEFAULT_MIN_RELIABILITY, + min_mixnode_reliability: DEFAULT_MIN_MIXNODE_RELIABILITY, + min_gateway_reliability: DEFAULT_MIN_GATEWAY_RELIABILITY, enabled: false, testnet_mode: false, all_validator_apis: default_api_endpoints(), @@ -334,6 +336,16 @@ impl Config { self } + pub fn with_min_mixnode_reliability(mut self, min_mixnode_reliability: u8) -> Self { + self.network_monitor.min_mixnode_reliability = min_mixnode_reliability; + self + } + + pub fn with_min_gateway_reliability(mut self, min_gateway_reliability: u8) -> Self { + self.network_monitor.min_gateway_reliability = min_gateway_reliability; + self + } + #[cfg(not(feature = "coconut"))] pub fn with_eth_private_key(mut self, eth_private_key: String) -> Self { self.network_monitor.eth_private_key = eth_private_key; @@ -423,8 +435,12 @@ impl Config { self.network_monitor.minimum_test_routes } - pub fn get_min_reliability(&self) -> u8 { - self.network_monitor.min_reliability + pub fn get_min_mixnode_reliability(&self) -> u8 { + self.network_monitor.min_mixnode_reliability + } + + pub fn get_min_gateway_reliability(&self) -> u8 { + self.network_monitor.min_gateway_reliability } pub fn get_route_test_packets(&self) -> usize { diff --git a/validator-api/src/config/template.rs b/validator-api/src/config/template.rs index a9c9005fb2..815bc8e8e7 100644 --- a/validator-api/src/config/template.rs +++ b/validator-api/src/config/template.rs @@ -21,7 +21,8 @@ mixnet_contract_address = '{{ base.mixnet_contract_address }}' [network_monitor] # Mixnodes and gateways with relialability lower the this get blacklisted by network monitor, get no traffic and cannot be selected into a rewarded set. -min_reliability = {{ network_monitor.min_reliability }} +min_mixnode_reliability = {{ network_monitor.min_mixnode_reliability }} # deafults to 50 +min_gateway_reliability = {{ network_monitor.min_gateway_reliability }} # defaults to 20 # Specifies whether network monitoring service is enabled in this process. enabled = {{ network_monitor.enabled }} diff --git a/validator-api/src/main.rs b/validator-api/src/main.rs index 037fc3911e..3419cb41c6 100644 --- a/validator-api/src/main.rs +++ b/validator-api/src/main.rs @@ -64,6 +64,9 @@ const ETH_PRIVATE_KEY: &str = "eth_private_key"; const REWARDING_MONITOR_THRESHOLD_ARG: &str = "monitor-threshold"; +const MIN_MIXNODE_RELIABILITY_ARG: &str = "min_mixnode_reliability"; +const MIN_GATEWAY_RELIABILITY_ARG: &str = "min_gateway_reliability"; + fn parse_validators(raw: &str) -> Vec { raw.split(',') .map(|raw_validator| { @@ -276,6 +279,24 @@ fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> Config { config = config.with_minimum_interval_monitor_threshold(monitor_threshold) } + if let Some(reliability) = matches + .value_of(MIN_MIXNODE_RELIABILITY_ARG) + .map(|t| t.parse::()) + { + config = config.with_min_mixnode_reliability( + reliability.expect("Provided reliability is not a u8 number!"), + ) + } + + if let Some(reliability) = matches + .value_of(MIN_GATEWAY_RELIABILITY_ARG) + .map(|t| t.parse::()) + { + config = config.with_min_gateway_reliability( + reliability.expect("Provided reliability is not a u8 number!"), + ) + } + #[cfg(feature = "coconut")] if let Some(keypair_path) = matches.value_of(KEYPAIR_ARG) { let keypair_bs58 = std::fs::read_to_string(keypair_path) diff --git a/validator-api/src/network_monitor/monitor/mod.rs b/validator-api/src/network_monitor/monitor/mod.rs index 6dc3483167..ce3df86727 100644 --- a/validator-api/src/network_monitor/monitor/mod.rs +++ b/validator-api/src/network_monitor/monitor/mod.rs @@ -42,7 +42,8 @@ pub(super) struct Monitor { /// The minimum number of test routes that need to be constructed (and working) in order for /// a monitor test run to be valid. minimum_test_routes: usize, - min_reliability: u8, + min_mixnode_reliability: u8, + min_gateway_reliability: u8, } impl Monitor { @@ -67,7 +68,8 @@ impl Monitor { route_test_packets: config.get_route_test_packets(), test_routes: config.get_test_routes(), minimum_test_routes: config.get_minimum_test_routes(), - min_reliability: config.get_min_reliability(), + min_mixnode_reliability: config.get_min_mixnode_reliability(), + min_gateway_reliability: config.get_min_gateway_reliability(), } } @@ -78,7 +80,7 @@ impl Monitor { // uptime calculations for result in test_summary.mixnode_results.iter() { - if result.reliability < self.min_reliability { + if result.reliability < self.min_mixnode_reliability { self.packet_preparer .validator_cache() .insert_mixnodes_blacklist(result.identity.clone()) @@ -92,7 +94,7 @@ impl Monitor { } for result in test_summary.gateway_results.iter() { - if result.reliability < self.min_reliability { + if result.reliability < self.min_gateway_reliability { self.packet_preparer .validator_cache() .insert_gateways_blacklist(result.identity.clone()) From 8d7428923a38d6f2d833b11c395fd33f6b4fe651 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Mon, 28 Mar 2022 15:32:31 +0100 Subject: [PATCH 02/16] Update binaries to rc version --- Cargo.lock | 18 +++++++++--------- clients/client-core/Cargo.toml | 2 +- clients/native/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 2 +- clients/webassembly/Cargo.toml | 2 +- contracts/bandwidth-claim/Cargo.toml | 2 +- contracts/mixnet/Cargo.toml | 2 +- contracts/vesting/Cargo.toml | 2 +- explorer-api/Cargo.toml | 2 +- gateway/Cargo.toml | 2 +- mixnode/Cargo.toml | 2 +- service-providers/network-requester/Cargo.toml | 2 +- validator-api/Cargo.toml | 2 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ad3ea4834..17b0e81fa7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -549,7 +549,7 @@ dependencies = [ [[package]] name = "client-core" -version = "0.12.0" +version = "1.0.0-rc.1" dependencies = [ "config", "crypto", @@ -1470,7 +1470,7 @@ dependencies = [ [[package]] name = "explorer-api" -version = "0.1.0" +version = "1.0.0-rc.1" dependencies = [ "chrono", "humantime-serde", @@ -2902,7 +2902,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "0.12.1" +version = "1.0.0-rc.1" dependencies = [ "clap 2.34.0", "client-core", @@ -2936,7 +2936,7 @@ dependencies = [ [[package]] name = "nym-gateway" -version = "0.12.1" +version = "1.0.0-rc.1" dependencies = [ "anyhow", "async-trait", @@ -2982,7 +2982,7 @@ dependencies = [ [[package]] name = "nym-mixnode" -version = "0.12.1" +version = "1.0.0-rc.1" dependencies = [ "anyhow", "bs58", @@ -3020,7 +3020,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "0.12.0" +version = "1.0.0-rc.1" dependencies = [ "clap 2.34.0", "dirs", @@ -3041,7 +3041,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "0.12.1" +version = "1.0.0-rc.1" dependencies = [ "clap 2.34.0", "client-core", @@ -3076,7 +3076,7 @@ dependencies = [ [[package]] name = "nym-validator-api" -version = "0.12.0" +version = "1.0.0-rc.1" dependencies = [ "anyhow", "attohttpc", @@ -6062,7 +6062,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vesting-contract" -version = "0.1.0" +version = "1.0.0-rc.1" dependencies = [ "config", "cosmwasm-std", diff --git a/clients/client-core/Cargo.toml b/clients/client-core/Cargo.toml index 464bf9d0a4..4e729a4c92 100644 --- a/clients/client-core/Cargo.toml +++ b/clients/client-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "client-core" -version = "0.12.0" +version = "1.0.0-rc.1" authors = ["Dave Hrycyszyn "] edition = "2021" diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index bbb1ba86db..bb2a0a604e 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "0.12.1" +version = "1.0.0-rc.1" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] edition = "2021" rust-version = "1.56" diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index b5116794ff..44111bb7eb 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "0.12.1" +version = "1.0.0-rc.1" authors = ["Dave Hrycyszyn "] edition = "2021" rust-version = "1.56" diff --git a/clients/webassembly/Cargo.toml b/clients/webassembly/Cargo.toml index 72321e98e3..77aadd6ef3 100644 --- a/clients/webassembly/Cargo.toml +++ b/clients/webassembly/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-client-wasm" authors = ["Dave Hrycyszyn ", "Jedrzej Stuczynski "] -version = "0.12.0" +version = "1.0.0-rc.1" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"] license = "Apache-2.0" diff --git a/contracts/bandwidth-claim/Cargo.toml b/contracts/bandwidth-claim/Cargo.toml index 390baf1ab7..d16630af9c 100644 --- a/contracts/bandwidth-claim/Cargo.toml +++ b/contracts/bandwidth-claim/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bandwidth-claim" -version = "0.1.0" +version = "1.0.0-rc.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 11f9c3a83b..f00b7fadfa 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mixnet-contract" -version = "0.1.0" +version = "1.0.0-rc.1" authors = ["Dave Hrycyszyn "] edition = "2021" diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index a54899a41b..8cf5eb6a2c 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vesting-contract" -version = "0.1.0" +version = "1.0.0-rc.1" authors = ["Drazen Urch "] edition = "2021" diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index f0084b203d..39fcd654dd 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "0.1.0" +version = "1.0.0-rc.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 147cae6444..a3d321a92b 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-gateway" -version = "0.12.1" +version = "1.0.0-rc.1" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Mixnet Gateway" edition = "2021" diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index e1e88d48d2..0166209753 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-mixnode" -version = "0.12.1" +version = "1.0.0-rc.1" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 914c97812a..6f8990388b 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-network-requester" -version = "0.12.0" +version = "1.0.0-rc.1" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] edition = "2021" diff --git a/validator-api/Cargo.toml b/validator-api/Cargo.toml index 0b606cd4aa..c28d62d1af 100644 --- a/validator-api/Cargo.toml +++ b/validator-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-validator-api" -version = "0.12.0" +version = "1.0.0-rc.1" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", From ce241339bf002938cd6fd040a612ab8c2f2f1ff7 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Mon, 28 Mar 2022 18:16:08 +0100 Subject: [PATCH 03/16] Create nym-release-publish.yml --- .github/workflows/nym-release-publish.yml | 43 +++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/nym-release-publish.yml diff --git a/.github/workflows/nym-release-publish.yml b/.github/workflows/nym-release-publish.yml new file mode 100644 index 0000000000..b90f874a97 --- /dev/null +++ b/.github/workflows/nym-release-publish.yml @@ -0,0 +1,43 @@ +name: Publish Nym binaries +on: + release: + types: [created] + +jobs: + publish-nym: + strategy: + fail-fast: false + matrix: + platform: [ubuntu-latest] + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + + - name: Check the release tag starts with `nym-binaries-` + if: startsWith(github.ref, 'refs/tags/nym-binaries-') == false + uses: actions/github-script@v3 + with: + script: | + core.setFailed('Release tag did not start with nym-binaries-...') + + - name: Install Rust stable + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: Build all binaries + uses: actions-rs/cargo@v1 + with: + command: build + args: --workspace --release + + - name: Upload to release based on tag name + uses: softprops/action-gh-release@v1 + with: + files: | + target/release/nym-client + target/release/nym-gateway + target/release/nym-mixnode + target/release/nym-socks5-client + target/release/nym-validator-api From c2938e067234931da0effddd2b9b8d500fa509a5 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Tue, 29 Mar 2022 17:02:56 +0200 Subject: [PATCH 04/16] Fix delegation paging (#1174) * Fix delegation paging and tests * Circuit breaker, upgrade storage and cosmwasm * beta6 * Cleanup delegation events --- Cargo.lock | 40 ++-- .../client-libs/validator-client/Cargo.toml | 2 +- .../contracts-common/Cargo.toml | 2 +- .../mixnet-contract/Cargo.toml | 2 +- .../mixnet-contract/src/delegation.rs | 35 +++- .../mixnet-contract/src/mixnode.rs | 29 +++ .../vesting-contract/Cargo.toml | 4 +- contracts/Cargo.lock | 52 ++--- contracts/bandwidth-claim/Cargo.toml | 4 +- contracts/mixnet/Cargo.toml | 6 +- contracts/mixnet/src/delegations/queries.rs | 194 ++++++++---------- contracts/mixnet/src/delegations/storage.rs | 4 +- .../mixnet/src/delegations/transactions.rs | 67 +++--- contracts/mixnet/src/support/helpers.rs | 13 -- contracts/mixnet/src/support/tests/mod.rs | 3 +- contracts/vesting/Cargo.toml | 4 +- 16 files changed, 227 insertions(+), 234 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17b0e81fa7..ac7e05cddf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -750,31 +750,31 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.0.0-beta6" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dddc1443004c6340e55ca66d98e9d2f1a44aadf4ce2bed2c4f29baa8a15e7b7" +checksum = "88c2565b1e73a816fb659ef4838fc356143fbd35f43c48a51d2d7d4e5d6679d3" dependencies = [ "digest 0.9.0", "ed25519-zebra", "k256 0.9.6", - "rand_core 0.5.1", + "rand_core 0.6.3", "thiserror", ] [[package]] name = "cosmwasm-derive" -version = "1.0.0-beta6" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4f0f10f165b8bcc558a13cddb498140960544519aa0581532c766dd80b5598" +checksum = "fa89fcdf8dbbe0088e663d0a814aa7368e7ebe8fb045a3a150fb5fdc2ffe3b45" dependencies = [ "syn", ] [[package]] name = "cosmwasm-std" -version = "1.0.0-beta6" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0f3145097b692b2d95fa5d2c7c6fdd60f193ccc709857e7e1987a608725300" +checksum = "bcb8f99a61d0b9069e1afc80a4ffea87dcc3523edd992080923870b13a677da0" dependencies = [ "base64", "cosmwasm-crypto", @@ -1071,20 +1071,9 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "0.11.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7ee1963302b0ac2a9d42fe0faec826209c17452bfd36fbfd9d002a88929261" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-storage-plus" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c087ff98fb0475db4c2b5298a5fd12b2848d2854b39d1115d930ee6da24d1eed" +checksum = "5e8b7f9a758c030d375520df947323c052704f784561fc28dcaab4f988c50a30" dependencies = [ "cosmwasm-std", "schemars", @@ -1322,16 +1311,17 @@ dependencies = [ [[package]] name = "ed25519-zebra" -version = "2.2.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a128b76af6dd4b427e34a6fd43dc78dbfe73672ec41ff615a2414c1a0ad0409" +checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" dependencies = [ "curve25519-dalek", "hex", - "rand_core 0.5.1", + "rand_core 0.6.3", "serde", "sha2", "thiserror", + "zeroize", ] [[package]] @@ -6066,7 +6056,7 @@ version = "1.0.0-rc.1" dependencies = [ "config", "cosmwasm-std", - "cw-storage-plus 0.12.1", + "cw-storage-plus", "mixnet-contract-common", "schemars", "serde", @@ -6080,7 +6070,7 @@ version = "0.1.0" dependencies = [ "config", "cosmwasm-std", - "cw-storage-plus 0.11.1", + "cw-storage-plus", "mixnet-contract-common", "schemars", "serde", diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 18322bac61..8e24671666 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -38,7 +38,7 @@ prost = { version = "0.9", default-features = false, optional = true } flate2 = { version = "1.0.20", optional = true } sha2 = { version = "0.9.5", optional = true } itertools = { version = "0.10", optional = true } -cosmwasm-std = { version = "1.0.0-beta3", optional = true } +cosmwasm-std = { version = "1.0.0-beta6", optional = true } [dev-dependencies] ts-rs = "6.1.2" diff --git a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml index 26c0b3d4af..74ca0bf3ec 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml +++ b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cosmwasm-std = "1.0.0-beta3" +cosmwasm-std = "1.0.0-beta6" diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index 0217635117..280a2d8e0d 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cosmwasm-std = "1.0.0-beta3" +cosmwasm-std = "1.0.0-beta6" serde = { version = "1.0", features = ["derive"] } serde_repr = "0.1" diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs index 5e6c328ecf..9ad7a63871 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs @@ -10,6 +10,9 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Display; +type OwnerAddressBytes = Vec; +type BlockHeight = u64; + #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)] pub struct Delegation { pub owner: Addr, @@ -24,7 +27,7 @@ impl Delegation { owner: Addr, node_identity: IdentityKey, amount: Coin, - block_height: u64, + block_height: BlockHeight, proxy: Option, ) -> Self { Delegation { @@ -36,15 +39,35 @@ impl Delegation { } } - // TODO: change that to use .joined_key() and return Vec - pub fn storage_key(&self) -> (IdentityKey, Vec, u64) { + pub fn storage_key(&self) -> (IdentityKey, OwnerAddressBytes, BlockHeight) { ( self.node_identity(), - self.owner().as_bytes().to_vec(), + self.proxy_storage_key(), self.block_height(), ) } + pub fn event_storage_key(&self) -> (OwnerAddressBytes, BlockHeight, IdentityKey) { + ( + self.proxy_storage_key(), + self.block_height(), + self.node_identity(), + ) + } + + pub fn proxy_storage_key(&self) -> OwnerAddressBytes { + if let Some(proxy) = &self.proxy { + self.owner() + .as_bytes() + .iter() + .zip(proxy.as_bytes()) + .map(|(x, y)| x ^ y) + .collect() + } else { + self.owner().as_bytes().to_vec() + } + } + pub fn increment_amount(&mut self, amount: Uint128, at_height: Option) { self.amount.amount += amount; if let Some(at_height) = at_height { @@ -86,10 +109,10 @@ pub struct PagedMixDelegationsResponse { } impl PagedMixDelegationsResponse { - pub fn new(delegations: Vec, start_next_after: Option<(Addr, u64)>) -> Self { + pub fn new(delegations: Vec, start_next_after: Option<(String, u64)>) -> Self { PagedMixDelegationsResponse { delegations, - start_next_after: start_next_after.map(|(s, h)| (s.to_string(), h)), + start_next_after, } } } diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs index 41702fcc8e..ddcf52e382 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs @@ -78,6 +78,35 @@ impl PendingUndelegate { pub fn block_height(&self) -> u64 { self.block_height } + + pub fn proxy_storage_key(&self) -> Vec { + if let Some(proxy) = &self.proxy { + self.delegate() + .as_bytes() + .iter() + .zip(proxy.as_bytes()) + .map(|(x, y)| x ^ y) + .collect() + } else { + self.delegate().as_bytes().to_vec() + } + } + + pub fn storage_key(&self) -> (IdentityKey, Vec) { + (self.mix_identity(), self.proxy_storage_key()) + } + + pub fn delegation_key(&self, block_height: u64) -> (IdentityKey, Vec, u64) { + (self.mix_identity(), self.proxy_storage_key(), block_height) + } + + pub fn event_storage_key(&self) -> (Vec, u64, IdentityKey) { + ( + self.proxy_storage_key(), + self.block_height(), + self.mix_identity(), + ) + } } #[cfg_attr(test, derive(ts_rs::TS))] diff --git a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml index 273835eb24..523f8a2d1f 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml @@ -6,11 +6,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cosmwasm-std = "1.0.0-beta3" +cosmwasm-std = "1.0.0-beta6" mixnet-contract-common = { path = "../mixnet-contract" } serde = { version = "1.0", features = ["derive"] } schemars = "0.8" -cw-storage-plus = "0.11.1" +cw-storage-plus = "0.13.1" config = { path = "../../config" } [dev-dependencies] diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index 9758571507..ce626cf5d3 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -41,7 +41,7 @@ checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" [[package]] name = "bandwidth-claim" -version = "0.1.0" +version = "1.0.0-rc.1" dependencies = [ "bandwidth-claim-contract", "config", @@ -218,22 +218,22 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.0.0-beta6" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dddc1443004c6340e55ca66d98e9d2f1a44aadf4ce2bed2c4f29baa8a15e7b7" +checksum = "88c2565b1e73a816fb659ef4838fc356143fbd35f43c48a51d2d7d4e5d6679d3" dependencies = [ "digest 0.9.0", "ed25519-zebra", "k256", - "rand_core 0.5.1", + "rand_core 0.6.3", "thiserror", ] [[package]] name = "cosmwasm-derive" -version = "1.0.0-beta6" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4f0f10f165b8bcc558a13cddb498140960544519aa0581532c766dd80b5598" +checksum = "fa89fcdf8dbbe0088e663d0a814aa7368e7ebe8fb045a3a150fb5fdc2ffe3b45" dependencies = [ "syn", ] @@ -250,9 +250,9 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.0.0-beta6" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0f3145097b692b2d95fa5d2c7c6fdd60f193ccc709857e7e1987a608725300" +checksum = "bcb8f99a61d0b9069e1afc80a4ffea87dcc3523edd992080923870b13a677da0" dependencies = [ "base64", "cosmwasm-crypto", @@ -267,9 +267,9 @@ dependencies = [ [[package]] name = "cosmwasm-storage" -version = "1.0.0-beta3" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a4e55f0d64fed54cd2202301b8d466af8de044589247dabd77a4222f52f749" +checksum = "07f856099c824aa8f2488e62d1da3fc06383d3fdbc764573595f451be43441a2" dependencies = [ "cosmwasm-std", "serde", @@ -360,20 +360,9 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "0.11.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7ee1963302b0ac2a9d42fe0faec826209c17452bfd36fbfd9d002a88929261" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-storage-plus" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c087ff98fb0475db4c2b5298a5fd12b2848d2854b39d1115d930ee6da24d1eed" +checksum = "5e8b7f9a758c030d375520df947323c052704f784561fc28dcaab4f988c50a30" dependencies = [ "cosmwasm-std", "schemars", @@ -450,16 +439,17 @@ dependencies = [ [[package]] name = "ed25519-zebra" -version = "2.2.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a128b76af6dd4b427e34a6fd43dc78dbfe73672ec41ff615a2414c1a0ad0409" +checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" dependencies = [ "curve25519-dalek", "hex", - "rand_core 0.5.1", + "rand_core 0.6.3", "serde", "sha2", "thiserror", + "zeroize", ] [[package]] @@ -820,7 +810,7 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mixnet-contract" -version = "0.1.0" +version = "1.0.0-rc.1" dependencies = [ "az", "bs58", @@ -829,7 +819,7 @@ dependencies = [ "cosmwasm-std", "cosmwasm-storage", "crypto", - "cw-storage-plus 0.12.1", + "cw-storage-plus", "fixed", "mixnet-contract-common", "rand", @@ -1527,11 +1517,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vesting-contract" -version = "0.1.0" +version = "1.0.0-rc.1" dependencies = [ "config", "cosmwasm-std", - "cw-storage-plus 0.12.1", + "cw-storage-plus", "mixnet-contract-common", "schemars", "serde", @@ -1545,7 +1535,7 @@ version = "0.1.0" dependencies = [ "config", "cosmwasm-std", - "cw-storage-plus 0.11.1", + "cw-storage-plus", "mixnet-contract-common", "schemars", "serde", diff --git a/contracts/bandwidth-claim/Cargo.toml b/contracts/bandwidth-claim/Cargo.toml index d16630af9c..58d0f8e283 100644 --- a/contracts/bandwidth-claim/Cargo.toml +++ b/contracts/bandwidth-claim/Cargo.toml @@ -14,8 +14,8 @@ config = { path = "../../common/config"} [dependencies] bandwidth-claim-contract = { path = "../../common/bandwidth-claim-contract" } -cosmwasm-std = "1.0.0-beta3" -cosmwasm-storage = "1.0.0-beta3" +cosmwasm-std = "1.0.0-beta6" +cosmwasm-storage = "1.0.0-beta6" schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index f00b7fadfa..7e1b7f4e77 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -20,9 +20,9 @@ mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet- vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" } config = { path = "../../common/config"} -cosmwasm-std = "1.0.0-beta3" -cosmwasm-storage = "1.0.0-beta3" -cw-storage-plus = "0.12.1" +cosmwasm-std = "1.0.0-beta6" +cosmwasm-storage = "1.0.0-beta6" +cw-storage-plus = "0.13.1" az = "1.2.0" bs58 = "0.4.0" diff --git a/contracts/mixnet/src/delegations/queries.rs b/contracts/mixnet/src/delegations/queries.rs index c0f016151e..7889ef0a4a 100644 --- a/contracts/mixnet/src/delegations/queries.rs +++ b/contracts/mixnet/src/delegations/queries.rs @@ -43,7 +43,7 @@ pub(crate) fn query_delegator_delegations_paged( .idx .owner .prefix(validated_owner) - .range(deps.storage, start, None, Order::Ascending) + .range_raw(deps.storage, start, None, Order::Ascending) .take(limit) .map(|record| record.map(|r| r.1)) .collect::>>()?; @@ -94,26 +94,29 @@ pub(crate) fn query_mixnode_delegations_paged( start_after: Option<(String, u64)>, limit: Option, ) -> StdResult { + let arg_start_after = start_after.clone(); + let limit = limit .unwrap_or(storage::DELEGATION_PAGE_DEFAULT_LIMIT) .min(storage::DELEGATION_PAGE_MAX_LIMIT) as usize; - let start = start_after.map(|(addr, height)| { - Bound::ExclusiveRaw((mix_identity.clone(), addr.as_bytes(), height).joined_key()) - }); + let start = start_after + .map(|(addr, height)| Bound::ExclusiveRaw((addr.as_bytes(), height).joined_key())); let delegations = storage::delegations() - .idx - .mixnode - .prefix(mix_identity) - .range(deps.storage, start, None, Order::Ascending) + .sub_prefix(mix_identity) + .range_raw(deps.storage, start, None, Order::Ascending) .take(limit) .map(|record| record.map(|r| r.1)) .collect::>>()?; - let start_next_after = delegations + let mut start_next_after = delegations .last() - .map(|delegation| (delegation.owner(), delegation.block_height())); + .map(|delegation| (delegation.owner().to_string(), delegation.block_height())); + + if arg_start_after == start_next_after { + start_next_after = None; + } Ok(PagedMixDelegationsResponse::new( delegations, @@ -127,18 +130,22 @@ pub(crate) mod tests { use crate::support::tests::test_helpers; use config::defaults::DENOM; use cosmwasm_std::{coin, Addr, Storage}; + use rand::Rng; pub fn store_n_mix_delegations(n: u32, storage: &mut dyn Storage, node_identity: &str) { for i in 0..n { let address = format!("address{}", i); - test_helpers::save_dummy_delegation(storage, node_identity, address); + test_helpers::save_dummy_delegation(storage, node_identity, address, 1); } } #[cfg(test)] mod querying_for_mixnode_delegations_paged { + use std::collections::HashSet; + use super::*; use mixnet_contract_common::IdentityKey; + use rand::{distributions::Alphanumeric, SeedableRng}; #[test] fn retrieval_obeys_limits() { @@ -203,39 +210,37 @@ pub(crate) mod tests { #[test] fn pagination_works() { + let dummy_seed = [42u8; 32]; + let mut rng = rand_chacha::ChaCha20Rng::from_seed(dummy_seed); + let mut deps = test_helpers::init_contract(); let node_identity: IdentityKey = "foo".into(); - let node_identity2: IdentityKey = "bar".into(); - test_helpers::save_dummy_delegation(&mut deps.storage, &node_identity, "100"); - test_helpers::save_dummy_delegation(&mut deps.storage, &node_identity2, "100"); + let mut delegation_test_data = vec![]; + let mut returned_delegation_data = HashSet::new(); - let per_page = 2; - let page1 = query_mixnode_delegations_paged( - deps.as_ref(), - node_identity.clone(), - None, - Option::from(per_page), - ) - .unwrap(); + // Crete a bunch of randomly ordered (in storage) delegations + for _ in 0..200 { + delegation_test_data.push(( + rng.clone() + .sample_iter(&Alphanumeric) + .take(30) + .map(char::from) + .collect::(), + rng.gen::() as u64, + )) + } - // page should have 1 result on it - assert_eq!(1, page1.delegations.len()); + for (address, block_height) in delegation_test_data.iter() { + test_helpers::save_dummy_delegation( + &mut deps.storage, + &node_identity, + address, + *block_height, + ); + } - // save another - test_helpers::save_dummy_delegation(&mut deps.storage, &node_identity, "200"); - - // page1 should have 2 results on it - let page1 = query_mixnode_delegations_paged( - deps.as_ref(), - node_identity.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - test_helpers::save_dummy_delegation(&mut deps.storage, &node_identity, "300"); + let per_page = 100; // page1 still has 2 results let page1 = query_mixnode_delegations_paged( @@ -245,10 +250,17 @@ pub(crate) mod tests { Option::from(per_page), ) .unwrap(); - println!("{:?}", page1); + let start_after = page1.start_next_after.unwrap(); - assert_eq!(2, page1.delegations.len()); - assert_eq!(("200".to_string(), 12345), start_after); + assert_eq!(100, page1.delegations.len()); + assert_eq!( + (("XtsZrLRXvyegwyZDjuJtlYiG5B1eiJ".to_string(), 1594717548)), + start_after + ); + + for delegation in page1.delegations { + returned_delegation_data.insert(delegation.owner().to_string()); + } // retrieving the next page should start after the last key on this page @@ -259,37 +271,30 @@ pub(crate) mod tests { Option::from(per_page), ) .unwrap(); - println!("{:?}", page2); - assert_eq!(1, page2.delegations.len()); - assert_eq!(page2.delegations.last().unwrap().owner(), "300"); - // save another one - test_helpers::save_dummy_delegation(&mut deps.storage, &node_identity, "400"); + let start_after = page2.start_next_after.unwrap(); + assert_eq!( + ("zkHTlcgOWAyH8NoIJ2lkZcvvhYsFik".to_string(), 3448133410), + start_after + ); - let page2 = query_mixnode_delegations_paged( + for delegation in page2.delegations { + returned_delegation_data.insert(delegation.owner().to_string()); + } + + let page3 = query_mixnode_delegations_paged( deps.as_ref(), node_identity.clone(), Option::from(start_after), Option::from(per_page), ) .unwrap(); - // println!("{:?}", page2); - // now we have 2 pages, with 2 results on the second page - assert_eq!(2, page2.delegations.len()); - assert_eq!(page2.delegations.last().unwrap().owner(), "400"); - - // Should be empty - let page3 = query_mixnode_delegations_paged( - deps.as_ref(), - node_identity, - page2.start_next_after, - Option::from(per_page), - ) - .unwrap(); - - assert!(page3.delegations.is_empty()); assert!(page3.start_next_after.is_none()); + + for delegation in delegation_test_data { + assert!(returned_delegation_data.contains(&*delegation.0)); + } } } @@ -404,7 +409,7 @@ pub(crate) mod tests { fn store_n_reverse_delegations(n: u32, storage: &mut dyn Storage, delegation_owner: &str) { for i in 0..n { let node_identity = format!("node{}", i); - test_helpers::save_dummy_delegation(storage, node_identity, delegation_owner); + test_helpers::save_dummy_delegation(storage, node_identity, delegation_owner, 1); } } @@ -475,9 +480,18 @@ pub(crate) mod tests { let mut deps = test_helpers::init_contract(); let delegation_owner = "bar".to_string(); - test_helpers::save_dummy_delegation(&mut deps.storage, "100", &delegation_owner); + for j in 0..20 { + for i in 0..10 { + test_helpers::save_dummy_delegation( + &mut deps.storage, + format!("{}-{}", j, i), + delegation_owner.clone(), + i, + ); + } + } - let per_page = 2; + let per_page = 100; let page1 = query_delegator_delegations_paged( deps.as_ref(), delegation_owner.clone(), @@ -486,60 +500,30 @@ pub(crate) mod tests { ) .unwrap(); - // page should have 1 result on it - assert_eq!(1, page1.delegations.len()); + let start_after = page1.start_next_after.unwrap(); + assert_eq!(per_page as usize, page1.delegations.len()); + assert_eq!(start_after, "9-9".to_string()); - // save another - test_helpers::save_dummy_delegation(&mut deps.storage, "200", &delegation_owner); - - // page1 should have 2 results on it - let page1 = query_delegator_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - test_helpers::save_dummy_delegation(&mut deps.storage, "300", &delegation_owner); - - // page1 still has 2 results - let page1 = query_delegator_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - // retrieving the next page should start after the last key on this page - let start_after: IdentityKey = page1.start_next_after.unwrap(); let page2 = query_delegator_delegations_paged( deps.as_ref(), delegation_owner.clone(), - Option::from(start_after), + Some(start_after), Option::from(per_page), ) .unwrap(); - assert_eq!(1, page2.delegations.len()); + let start_after = page2.start_next_after.unwrap(); + assert_eq!(start_after, "19-9".to_string()); - // save another one - test_helpers::save_dummy_delegation(&mut deps.storage, "400", &delegation_owner); - - let start_after = String::from("2"); - let page2 = query_delegator_delegations_paged( + let page3 = query_delegator_delegations_paged( deps.as_ref(), - delegation_owner, - Option::from(start_after), + delegation_owner.clone(), + Some(start_after), Option::from(per_page), ) .unwrap(); - // now we have 2 pages, with 2 results on the second page - assert_eq!(2, page2.delegations.len()); + assert!(page3.start_next_after.is_none()); } } } diff --git a/contracts/mixnet/src/delegations/storage.rs b/contracts/mixnet/src/delegations/storage.rs index e9a73a30a7..c65e8f0768 100644 --- a/contracts/mixnet/src/delegations/storage.rs +++ b/contracts/mixnet/src/delegations/storage.rs @@ -24,9 +24,9 @@ type OwnerAddress = Vec; type PrimaryKey = (IdentityKey, OwnerAddress, BlockHeight); pub(crate) struct DelegationIndex<'a> { - pub(crate) owner: MultiIndex<'a, Addr, Delegation>, + pub(crate) owner: MultiIndex<'a, Addr, Delegation, PrimaryKey>, - pub(crate) mixnode: MultiIndex<'a, IdentityKey, Delegation>, + pub(crate) mixnode: MultiIndex<'a, IdentityKey, Delegation, PrimaryKey>, } impl<'a> IndexList for DelegationIndex<'a> { diff --git a/contracts/mixnet/src/delegations/transactions.rs b/contracts/mixnet/src/delegations/transactions.rs index 565bb8e70d..c28e6539f2 100644 --- a/contracts/mixnet/src/delegations/transactions.rs +++ b/contracts/mixnet/src/delegations/transactions.rs @@ -4,7 +4,6 @@ use super::storage::{self, PENDING_DELEGATION_EVENTS}; use crate::error::ContractError; use crate::mixnet_contract_settings::storage as mixnet_params_storage; use crate::mixnodes::storage as mixnodes_storage; -use crate::support::helpers::generate_storage_key; use config::defaults::DENOM; use cosmwasm_std::{ coins, wasm_execute, Addr, Api, BankMsg, Coin, DepsMut, Env, Event, MessageInfo, Order, @@ -192,19 +191,18 @@ pub(crate) fn _try_delegate_to_mixnode( }); } - let maybe_proxy_storage = generate_storage_key(&delegate, proxy.as_ref()); - let storage_key = (maybe_proxy_storage, block_height, mix_identity.to_string()); + let delegation = Delegation::new( + delegate.to_owned(), + mix_identity.to_string(), + amount.clone(), + block_height, + proxy.clone(), + ); storage::PENDING_DELEGATION_EVENTS.save( storage, - storage_key, - &DelegationEvent::Delegate(Delegation::new( - delegate.to_owned(), - mix_identity.to_string(), - amount.clone(), - block_height, - proxy.clone(), - )), + delegation.event_storage_key(), + &DelegationEvent::Delegate(delegation), )?; Ok(Response::new().add_event(new_pending_delegation_event( @@ -246,17 +244,9 @@ pub(crate) fn try_reconcile_undelegation( pending_undelegate: &PendingUndelegate, ) -> Result { let delegation_map = storage::delegations(); - let maybe_proxy_storage = generate_storage_key( - &pending_undelegate.delegate(), - pending_undelegate.proxy().as_ref(), - ); - let storage_key = ( - pending_undelegate.mix_identity(), - maybe_proxy_storage.clone(), - ); let any_delegations = delegation_map - .prefix(storage_key.clone()) + .prefix(pending_undelegate.storage_key()) .keys(storage, None, None, cosmwasm_std::Order::Ascending) .filter_map(|v| v.ok()) .next() @@ -287,7 +277,7 @@ pub(crate) fn try_reconcile_undelegation( // Might want to introduce paging here let delegation_heights = delegation_map - .prefix(storage_key) + .prefix(pending_undelegate.storage_key()) .keys(storage, None, None, cosmwasm_std::Order::Ascending) .filter_map(|v| v.ok()) .collect::>(); @@ -317,14 +307,15 @@ pub(crate) fn try_reconcile_undelegation( } for h in delegation_heights { - let storage_key = ( - pending_undelegate.mix_identity(), - maybe_proxy_storage.clone(), - h, - ); - let delegation = delegation_map.load(storage, storage_key.clone())?; + let delegation = + delegation_map.load(storage, pending_undelegate.delegation_key(h).clone())?; total_delegation += delegation.amount.amount; - delegation_map.replace(storage, storage_key, None, Some(&delegation))?; + delegation_map.replace( + storage, + pending_undelegate.delegation_key(h), + None, + Some(&delegation), + )?; } let bank_msg = BankMsg::Send { @@ -386,19 +377,17 @@ pub(crate) fn _try_remove_delegation_from_mixnode( ) -> Result { let delegate = deps.api.addr_validate(delegate)?; + let event = PendingUndelegate::new( + mix_identity.to_string(), + delegate.clone(), + proxy.clone(), + env.block.height, + ); + PENDING_DELEGATION_EVENTS.save( deps.storage, - ( - delegate.as_bytes().to_vec(), - env.block.height, - mix_identity.to_string(), - ), - &DelegationEvent::Undelegate(PendingUndelegate::new( - mix_identity.to_string(), - delegate.clone(), - proxy.clone(), - env.block.height, - )), + event.event_storage_key(), + &DelegationEvent::Undelegate(event), )?; Ok(Response::new().add_event(new_pending_undelegation_event( diff --git a/contracts/mixnet/src/support/helpers.rs b/contracts/mixnet/src/support/helpers.rs index d99c72f722..a8ed1fc450 100644 --- a/contracts/mixnet/src/support/helpers.rs +++ b/contracts/mixnet/src/support/helpers.rs @@ -40,19 +40,6 @@ pub(crate) fn epoch_reward_params( Ok(epoch_reward_params) } -pub fn generate_storage_key(address: &Addr, proxy: Option<&Addr>) -> Vec { - if let Some(proxy) = &proxy { - address - .as_bytes() - .iter() - .zip(proxy.as_bytes()) - .map(|(x, y)| x ^ y) - .collect() - } else { - address.as_bytes().to_vec() - } -} - // check if the target address has already bonded a mixnode or gateway, // in either case, return an appropriate error pub(crate) fn ensure_no_existing_bond( diff --git a/contracts/mixnet/src/support/tests/mod.rs b/contracts/mixnet/src/support/tests/mod.rs index fa595e128e..78ba6082fa 100644 --- a/contracts/mixnet/src/support/tests/mod.rs +++ b/contracts/mixnet/src/support/tests/mod.rs @@ -103,12 +103,13 @@ pub mod test_helpers { storage: &mut dyn Storage, mix: impl Into, owner: impl Into, + block_height: u64, ) { let delegation = Delegation { owner: Addr::unchecked(owner.into()), node_identity: mix.into(), amount: coin(12345, DENOM), - block_height: 12345, + block_height: block_height, proxy: None, }; diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index 8cf5eb6a2c..1d0799e596 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -18,8 +18,8 @@ mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet- vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" } config = { path = "../../common/config" } -cosmwasm-std = { version = "1.0.0-beta4"} -cw-storage-plus = { version = "0.12.1", features = ["iterator"] } +cosmwasm-std = { version = "1.0.0-beta6"} +cw-storage-plus = { version = "0.13.1", features = ["iterator"] } schemars = "0.8" serde = { version = "1.0", default-features = false, features = ["derive"] } From 842bcfa782e09f419b4314c8ad837c0824b47010 Mon Sep 17 00:00:00 2001 From: Tommy Verrall Date: Wed, 30 Mar 2022 09:34:17 +0100 Subject: [PATCH 05/16] fix unbond page --- nym-wallet/src/pages/unbond/index.tsx | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/nym-wallet/src/pages/unbond/index.tsx b/nym-wallet/src/pages/unbond/index.tsx index ac727d1531..fd2209f171 100644 --- a/nym-wallet/src/pages/unbond/index.tsx +++ b/nym-wallet/src/pages/unbond/index.tsx @@ -1,9 +1,10 @@ import React, { useContext, useEffect, useState } from 'react'; import { Alert, Box, Button, CircularProgress } from '@mui/material'; +import { useSnackbar } from 'notistack'; import { Fee, NymCard } from '../../components'; import { useCheckOwnership } from '../../hooks/useCheckOwnership'; import { ClientContext } from '../../context/main'; -import { unbond } from '../../requests'; +import { unbond, vestingUnbond } from '../../requests'; import { PageLayout } from '../../layouts'; export const Unbond = () => { @@ -11,6 +12,8 @@ export const Unbond = () => { const { checkOwnership, ownership } = useCheckOwnership(); const { userBalance, getBondDetails } = useContext(ClientContext); + const { enqueueSnackbar } = useSnackbar(); + useEffect(() => { const initialiseForm = async () => { await checkOwnership(); @@ -32,11 +35,20 @@ export const Unbond = () => { disabled={isLoading} onClick={async () => { setIsLoading(true); - await unbond(ownership.nodeType!); - await userBalance.fetchBalance(); - await getBondDetails(); - await checkOwnership(); - setIsLoading(false); + try { + if (ownership.vestingPledge) { + await vestingUnbond(ownership.nodeType!); + } else { + await unbond(ownership.nodeType!); + } + } catch (e) { + enqueueSnackbar(`Failed to unbond ${ownership.nodeType}}`, { variant: 'error' }); + } finally { + await getBondDetails(); + await checkOwnership(); + await userBalance.fetchBalance(); + setIsLoading(false); + } }} color="inherit" > From 95b6ac50be87d4c17920b480fe60381661e02ce0 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Wed, 30 Mar 2022 12:20:03 +0200 Subject: [PATCH 06/16] Type safe bounds (#1179) * Type safe bounds * Debug get_all_delegations * List raw delegations * query all delegation values * Get all keys and values * Differentiate on len * Clean up duplicates * Remove stop gap * Cleanup, fix paged query key * Reduce queries required to get all delegations * Sandbox migration * Delete migration --- .../validator-client/src/nymd/mod.rs | 2 + .../mixnet-contract/src/delegation.rs | 41 ++++-- .../mixnet-contract/src/lib.rs | 2 +- .../mixnet-contract/src/msg.rs | 3 + contracts/Cargo.lock | 1 + contracts/mixnet/Cargo.toml | 1 + contracts/mixnet/src/contract.rs | 63 ++------- contracts/mixnet/src/delegations/queries.rs | 121 ++++++++++++++---- .../mixnet/src/delegations/transactions.rs | 3 + 9 files changed, 148 insertions(+), 89 deletions(-) diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 0c7f81a5ae..ecee52a06a 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -589,6 +589,7 @@ impl NymdClient { &self, mix_identity: IdentityKey, delegator: &AccountId, + proxy: Option, ) -> Result where C: CosmWasmClient + Sync, @@ -596,6 +597,7 @@ impl NymdClient { let request = QueryMsg::GetDelegationDetails { mix_identity, delegator: delegator.to_string(), + proxy, }; self.client .query_contract_smart(self.mixnet_contract_address()?, &request) diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs index 9ad7a63871..645245d8e6 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs @@ -9,10 +9,24 @@ use cosmwasm_std::{Coin, Uint128}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Display; +use std::hash::{Hash, Hasher}; type OwnerAddressBytes = Vec; type BlockHeight = u64; +pub fn generate_storage_key(address: &Addr, proxy: Option<&Addr>) -> Vec { + if let Some(proxy) = &proxy { + address + .as_bytes() + .iter() + .zip(proxy.as_bytes()) + .map(|(x, y)| x ^ y) + .collect() + } else { + address.as_bytes().to_vec() + } +} + #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)] pub struct Delegation { pub owner: Addr, @@ -22,6 +36,18 @@ pub struct Delegation { pub proxy: Option, // proxy address used to delegate the funds on behalf of anouther address } +impl Eq for Delegation {} + +#[allow(clippy::derive_hash_xor_eq)] +impl Hash for Delegation { + fn hash(&self, state: &mut H) { + self.owner.hash(state); + self.node_identity.hash(state); + self.block_height.hash(state); + self.proxy.hash(state); + } +} + impl Delegation { pub fn new( owner: Addr, @@ -56,16 +82,11 @@ impl Delegation { } pub fn proxy_storage_key(&self) -> OwnerAddressBytes { - if let Some(proxy) = &self.proxy { - self.owner() - .as_bytes() - .iter() - .zip(proxy.as_bytes()) - .map(|(x, y)| x ^ y) - .collect() - } else { - self.owner().as_bytes().to_vec() - } + generate_storage_key(&self.owner, self.proxy.as_ref()) + } + + pub fn proxy(&self) -> Option<&Addr> { + self.proxy.as_ref() } pub fn increment_amount(&mut self, amount: Uint128, at_height: Option) { diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs index a62485deb3..0931e7f751 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -mod delegation; +pub mod delegation; pub mod error; pub mod events; mod gateway; diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs index 7648baa15f..75a0bc272b 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs @@ -101,6 +101,8 @@ pub enum ExecuteMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { + GetAllDelegationKeys {}, + DebugGetAllDelegationValues {}, GetContractVersion {}, GetMixNodes { limit: Option, @@ -137,6 +139,7 @@ pub enum QueryMsg { GetDelegationDetails { mix_identity: IdentityKey, delegator: String, + proxy: Option, }, LayerDistribution {}, GetRewardPool {}, diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index ce626cf5d3..a8f452dce7 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -821,6 +821,7 @@ dependencies = [ "crypto", "cw-storage-plus", "fixed", + "hex", "mixnet-contract-common", "rand", "rand_chacha", diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 7e1b7f4e77..59f04c9406 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -30,6 +30,7 @@ schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } thiserror = { version = "1.0.23" } time = { version = "0.3", features = ["macros"] } +hex = "0.4.3" [dev-dependencies] cosmwasm-schema = "1.0.0-beta3" diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 7ed42f47da..7023434db2 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -32,7 +32,7 @@ use cosmwasm_std::{ entry_point, to_binary, Addr, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, Uint128, }; use mixnet_contract_common::{ - ContractStateParams, Delegation, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, + ContractStateParams, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, }; use time::OffsetDateTime; @@ -312,11 +312,13 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result to_binary(&query_mixnode_delegation( deps.storage, deps.api, mix_identity, delegator, + proxy, )?), QueryMsg::GetRewardPool {} => to_binary(&query_reward_pool(deps)?), QueryMsg::GetCirculatingSupply {} => to_binary(&query_circulating_supply(deps)?), @@ -363,66 +365,19 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result to_binary( &query_pending_delegation_events(deps.storage, owner_address)?, ), + QueryMsg::GetAllDelegationKeys {} => to_binary( + &crate::delegations::queries::query_all_delegation_keys(deps.storage)?, + ), + QueryMsg::DebugGetAllDelegationValues {} => to_binary( + &crate::delegations::queries::debug_query_all_delegation_values(deps.storage)?, + ), }; Ok(query_res?) } -// MIGRATE OLD DELEGATION STORAGE -// applied on QAnet -#[allow(dead_code)] -fn migrate_delegations(deps: DepsMut<'_>) -> Result<(), ContractError> { - use crate::delegations::storage::{ - DelegationIndex, DELEGATION_MIXNODE_IDX_NAMESPACE, DELEGATION_OWNER_IDX_NAMESPACE, - DELEGATION_PK_NAMESPACE, - }; - use cosmwasm_std::Order; - use cw_storage_plus::{IndexedMap, MultiIndex}; - - type PrimaryKey = Vec; - - fn old_delegations<'a>() -> IndexedMap<'a, PrimaryKey, Delegation, DelegationIndex<'a>> { - let indexes = DelegationIndex { - owner: MultiIndex::new( - |d| d.owner.clone(), - DELEGATION_PK_NAMESPACE, - DELEGATION_OWNER_IDX_NAMESPACE, - ), - mixnode: MultiIndex::new( - |d| d.node_identity.clone(), - DELEGATION_PK_NAMESPACE, - DELEGATION_MIXNODE_IDX_NAMESPACE, - ), - }; - - IndexedMap::new(DELEGATION_PK_NAMESPACE, indexes) - } - - let old_delegations = old_delegations() - .range(deps.storage, None, None, Order::Ascending) - .filter_map(|r| r.ok()) - .map(|(_key, delegation)| delegation) - .collect::>(); - - for delegation in old_delegations { - crate::delegations::storage::delegations().save( - deps.storage, - ( - delegation.node_identity(), - delegation.owner().as_bytes().to_vec(), - delegation.block_height(), - ), - &delegation, - )?; - } - Ok(()) -} - #[entry_point] pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result { - // TODO: Uncomment mainnet - // migrate_delegations(deps)?; - Ok(Default::default()) } diff --git a/contracts/mixnet/src/delegations/queries.rs b/contracts/mixnet/src/delegations/queries.rs index 7889ef0a4a..4dacb34035 100644 --- a/contracts/mixnet/src/delegations/queries.rs +++ b/contracts/mixnet/src/delegations/queries.rs @@ -48,9 +48,13 @@ pub(crate) fn query_delegator_delegations_paged( .map(|record| record.map(|r| r.1)) .collect::>>()?; - let start_next_after = delegations - .last() - .map(|delegation| delegation.node_identity()); + let start_next_after = if delegations.len() < limit { + None + } else { + delegations + .last() + .map(|delegation| delegation.node_identity()) + }; Ok(PagedDelegatorDelegationsResponse::new( delegations, @@ -58,17 +62,70 @@ pub(crate) fn query_delegator_delegations_paged( )) } +pub fn query_all_delegation_keys(storage: &dyn Storage) -> Result, ContractError> { + Ok(storage::delegations() + .keys_raw(storage, None, None, Order::Ascending) + .map(hex::encode) + .collect()) +} + +use std::collections::HashSet; + +// This should only be exposed directly on the contract via nymd binary, not through the nymd clients +pub fn debug_query_all_delegation_values( + storage: &dyn Storage, +) -> Result, ContractError> { + use crate::delegations::storage::{ + DelegationIndex, DELEGATION_MIXNODE_IDX_NAMESPACE, DELEGATION_OWNER_IDX_NAMESPACE, + DELEGATION_PK_NAMESPACE, + }; + + use cw_storage_plus::{IndexedMap, MultiIndex}; + + type PrimaryKey = Vec; + + fn all_delegations<'a>() -> IndexedMap<'a, PrimaryKey, Delegation, DelegationIndex<'a>> { + let indexes = DelegationIndex { + owner: MultiIndex::new( + |d| d.owner.clone(), + DELEGATION_PK_NAMESPACE, + DELEGATION_OWNER_IDX_NAMESPACE, + ), + mixnode: MultiIndex::new( + |d| d.node_identity.clone(), + DELEGATION_PK_NAMESPACE, + DELEGATION_MIXNODE_IDX_NAMESPACE, + ), + }; + + IndexedMap::new(DELEGATION_PK_NAMESPACE, indexes) + } + + let all_delegations = all_delegations() + .range(storage, None, None, Order::Ascending) + .filter_map(|r| r.ok()) + .map(|(_key, delegation)| delegation) + .collect::>(); + + Ok(all_delegations) +} + // queries for delegation value of given address for particular node pub(crate) fn query_mixnode_delegation( storage: &dyn Storage, api: &dyn Api, mix_identity: IdentityKey, delegator: String, + proxy: Option, ) -> Result, ContractError> { let validated_delegator = api.addr_validate(&delegator)?; + let proxy = proxy.map(|p| api.addr_validate(&p).expect("Invalid proxy address")); let storage_key = ( mix_identity.clone(), - validated_delegator.as_bytes().to_vec(), + mixnet_contract_common::delegation::generate_storage_key( + &validated_delegator, + proxy.as_ref(), + ), ); let delegations = storage::delegations() @@ -94,29 +151,35 @@ pub(crate) fn query_mixnode_delegations_paged( start_after: Option<(String, u64)>, limit: Option, ) -> StdResult { - let arg_start_after = start_after.clone(); - let limit = limit .unwrap_or(storage::DELEGATION_PAGE_DEFAULT_LIMIT) .min(storage::DELEGATION_PAGE_MAX_LIMIT) as usize; - let start = start_after - .map(|(addr, height)| Bound::ExclusiveRaw((addr.as_bytes(), height).joined_key())); + let start = start_after.map(|(addr, height)| { + Bound::exclusive(( + hex::decode(addr).expect("Could not hex decode proxy_storage_key"), + height, + )) + }); let delegations = storage::delegations() .sub_prefix(mix_identity) - .range_raw(deps.storage, start, None, Order::Ascending) + .range(deps.storage, start, None, Order::Ascending) .take(limit) - .map(|record| record.map(|r| r.1)) - .collect::>>()?; + .filter_map(|r| r.ok()) + .map(|record| record.1) + .collect::>(); - let mut start_next_after = delegations - .last() - .map(|delegation| (delegation.owner().to_string(), delegation.block_height())); - - if arg_start_after == start_next_after { - start_next_after = None; - } + let start_next_after = if delegations.len() < limit { + None + } else { + delegations.last().map(|delegation| { + ( + hex::encode(delegation.proxy_storage_key()), + delegation.block_height(), + ) + }) + }; Ok(PagedMixDelegationsResponse::new( delegations, @@ -254,7 +317,10 @@ pub(crate) mod tests { let start_after = page1.start_next_after.unwrap(); assert_eq!(100, page1.delegations.len()); assert_eq!( - (("XtsZrLRXvyegwyZDjuJtlYiG5B1eiJ".to_string(), 1594717548)), + (( + "5874735a724c52587679656777795a446a754a746c59694735423165694a".to_string(), + 1594717548 + )), start_after ); @@ -274,7 +340,10 @@ pub(crate) mod tests { let start_after = page2.start_next_after.unwrap(); assert_eq!( - ("zkHTlcgOWAyH8NoIJ2lkZcvvhYsFik".to_string(), 3448133410), + ( + "7a6b48546c63674f57417948384e6f494a326c6b5a63767668597346696b".to_string(), + 3448133410 + ), start_after ); @@ -322,7 +391,8 @@ pub(crate) mod tests { &deps.storage, &deps.api, node_identity, - delegation_owner.to_string() + delegation_owner.to_string(), + None ) ) } @@ -345,7 +415,8 @@ pub(crate) mod tests { &deps.storage, &deps.api, node_identity1.clone(), - delegation_owner1.to_string() + delegation_owner1.to_string(), + None ) ); @@ -371,7 +442,8 @@ pub(crate) mod tests { &deps.storage, &deps.api, node_identity1.clone(), - delegation_owner1.to_string() + delegation_owner1.to_string(), + None ) ); @@ -397,7 +469,8 @@ pub(crate) mod tests { &deps.storage, &deps.api, node_identity1, - delegation_owner1.to_string() + delegation_owner1.to_string(), + None ) ) } diff --git a/contracts/mixnet/src/delegations/transactions.rs b/contracts/mixnet/src/delegations/transactions.rs index c28e6539f2..c43411eb80 100644 --- a/contracts/mixnet/src/delegations/transactions.rs +++ b/contracts/mixnet/src/delegations/transactions.rs @@ -727,6 +727,7 @@ mod tests { &deps.api, identity, delegation_owner.to_string(), + None, ) .unwrap(); @@ -1063,6 +1064,7 @@ mod tests { &deps.api, identity.clone(), delegation_owner.clone().into_string(), + None, ) .unwrap(); @@ -1132,6 +1134,7 @@ mod tests { &deps.api, identity.clone(), delegation_owner.clone().into_string(), + None, ) .unwrap(); From a63a94623f80ad0d7a5c3afdddb3e26a116a8e39 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Mon, 4 Apr 2022 16:55:46 +0200 Subject: [PATCH 07/16] Update and query rewarding validator address (#1193) --- .../mixnet-contract/src/msg.rs | 4 ++ contracts/mixnet/src/contract.rs | 9 +++- .../src/mixnet_contract_settings/queries.rs | 6 +++ .../mixnet_contract_settings/transactions.rs | 51 +++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs index 75a0bc272b..12c20d08fb 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs @@ -15,6 +15,9 @@ pub struct InstantiateMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum ExecuteMsg { + UpdateRewardingValidatorAddress { + address: String, + }, InitEpoch {}, ReconcileDelegations {}, CheckpointMixnodes {}, @@ -101,6 +104,7 @@ pub enum ExecuteMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { + GetRewardingValidatorAddress {}, GetAllDelegationKeys {}, DebugGetAllDelegationValues {}, GetContractVersion {}, diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 7023434db2..a81e0b538a 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -18,9 +18,10 @@ use crate::interval::queries::{ use crate::interval::transactions::{init_epoch, try_init_epoch}; use crate::mixnet_contract_settings::models::ContractState; use crate::mixnet_contract_settings::queries::{ - query_contract_settings_params, query_contract_version, + query_contract_settings_params, query_contract_version, query_rewarding_validator_address, }; use crate::mixnet_contract_settings::storage as mixnet_params_storage; +use crate::mixnet_contract_settings::transactions::try_update_rewarding_validator_address; use crate::mixnodes::bonding_queries as mixnode_queries; use crate::mixnodes::bonding_queries::query_mixnodes_paged; use crate::mixnodes::layer_queries::query_layer_distribution; @@ -96,6 +97,9 @@ pub fn execute( msg: ExecuteMsg, ) -> Result { match msg { + ExecuteMsg::UpdateRewardingValidatorAddress { address } => { + try_update_rewarding_validator_address(deps, info, address) + } ExecuteMsg::InitEpoch {} => try_init_epoch(info, deps.storage, env), ExecuteMsg::BondMixnode { mix_node, @@ -276,6 +280,9 @@ pub fn execute( #[entry_point] pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result { let query_res = match msg { + QueryMsg::GetRewardingValidatorAddress {} => { + to_binary(&query_rewarding_validator_address(deps)?) + } QueryMsg::GetContractVersion {} => to_binary(&query_contract_version()), QueryMsg::GetMixNodes { start_after, limit } => { to_binary(&query_mixnodes_paged(deps, start_after, limit)?) diff --git a/contracts/mixnet/src/mixnet_contract_settings/queries.rs b/contracts/mixnet/src/mixnet_contract_settings/queries.rs index e36791b947..40c5274e37 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/queries.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/queries.rs @@ -11,6 +11,12 @@ pub(crate) fn query_contract_settings_params(deps: Deps<'_>) -> StdResult) -> StdResult { + storage::CONTRACT_STATE + .load(deps.storage) + .map(|settings| settings.rewarding_validator_address.to_string()) +} + pub(crate) fn query_contract_version() -> MixnetContractVersion { // as per docs // env! macro will expand to the value of the named environment variable at diff --git a/contracts/mixnet/src/mixnet_contract_settings/transactions.rs b/contracts/mixnet/src/mixnet_contract_settings/transactions.rs index 2901270b5b..bf4e7613e6 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/transactions.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/transactions.rs @@ -3,12 +3,30 @@ use super::storage; use crate::error::ContractError; +use cosmwasm_std::Addr; use cosmwasm_std::DepsMut; use cosmwasm_std::MessageInfo; use cosmwasm_std::Response; use mixnet_contract_common::events::new_settings_update_event; use mixnet_contract_common::ContractStateParams; +pub fn try_update_rewarding_validator_address( + deps: DepsMut<'_>, + info: MessageInfo, + address: String, +) -> Result { + let mut state = storage::CONTRACT_STATE.load(deps.storage)?; + + if info.sender != state.owner { + return Err(ContractError::Unauthorized); + } + + state.rewarding_validator_address = Addr::unchecked(address); + storage::CONTRACT_STATE.save(deps.storage, &state)?; + + Ok(Response::default()) +} + pub(crate) fn try_update_contract_settings( deps: DepsMut<'_>, info: MessageInfo, @@ -48,12 +66,45 @@ pub mod tests { use super::*; use crate::contract::{INITIAL_GATEWAY_PLEDGE, INITIAL_MIXNODE_PLEDGE}; use crate::error::ContractError; + use crate::mixnet_contract_settings::queries::query_rewarding_validator_address; use crate::mixnet_contract_settings::transactions::try_update_contract_settings; use crate::support::tests::test_helpers; use cosmwasm_std::testing::mock_info; use cosmwasm_std::Response; use mixnet_contract_common::ContractStateParams; + #[test] + fn update_contract_rewarding_validtor_address() { + let mut deps = test_helpers::init_contract(); + + let info = mock_info("not-the-creator", &[]); + let res = try_update_rewarding_validator_address( + deps.as_mut(), + info, + "not-the-creator".to_string(), + ); + assert_eq!(res, Err(ContractError::Unauthorized)); + + let info = mock_info("creator", &[]); + let res = try_update_rewarding_validator_address( + deps.as_mut(), + info, + "new-good-address".to_string(), + ); + assert_eq!(res, Ok(Response::default())); + + let state = storage::CONTRACT_STATE.load(&deps.storage).unwrap(); + assert_eq!( + state.rewarding_validator_address, + Addr::unchecked("new-good-address") + ); + + assert_eq!( + state.rewarding_validator_address, + query_rewarding_validator_address(deps.as_ref()).unwrap() + ); + } + #[test] fn updating_contract_settings() { let mut deps = test_helpers::init_contract(); From b083335f56ae80324a19bce78cae968db28f5abe Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Mon, 4 Apr 2022 11:13:21 +0100 Subject: [PATCH 08/16] Add updater config to `tauri.conf.json` --- nym-wallet/src-tauri/tauri.conf.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nym-wallet/src-tauri/tauri.conf.json b/nym-wallet/src-tauri/tauri.conf.json index 929536616f..2ce9d0a5df 100644 --- a/nym-wallet/src-tauri/tauri.conf.json +++ b/nym-wallet/src-tauri/tauri.conf.json @@ -46,7 +46,12 @@ } }, "updater": { - "active": false + "active": true, + "endpoints": [ + "https://nymtech.net/.wellknown/wallet/updater.json" + ], + "dialog": true, + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IENCNzQ2M0E5N0VFODE2NApSV1JrZ2U2WE9rYTNETTg1OTBKdE5uWUEra0hML2syOVUvQ2lxZmFZRzZ1T3NWbGM0eVRzUTVhVwo=" }, "allowlist": { "window": { From 467bda8dddf7bb6e50aa5768681bbed9e51742fe Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Mon, 4 Apr 2022 11:31:29 +0100 Subject: [PATCH 09/16] Add tauri updater feature --- nym-wallet/Cargo.lock | 378 ++++++++++++++++++++++++++++++++ nym-wallet/src-tauri/Cargo.toml | 2 +- 2 files changed, 379 insertions(+), 1 deletion(-) diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index e7616df351..a3bf1b10e6 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -103,6 +103,101 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "ashpd" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eea0a7a98b3bd2832eb087e1078f6f58db5a54447574d3007cdac6309c1e9f1" +dependencies = [ + "enumflags2", + "futures", + "rand 0.8.5", + "serde", + "serde_repr", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90622698a1218e0b2fb846c97b5f19a0831f6baddee73d9454156365ccfa473b" +dependencies = [ + "easy-parallel", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "slab", +] + +[[package]] +name = "async-io" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +dependencies = [ + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-recursion" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-task" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" + [[package]] name = "async-trait" version = "0.1.52" @@ -138,6 +233,24 @@ dependencies = [ "system-deps 6.0.2", ] +[[package]] +name = "attohttpc" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e69e13a99a7e6e070bb114f7ff381e58c7ccc188630121fc4c2fe4bcf24cd072" +dependencies = [ + "flate2", + "http", + "log", + "native-tls", + "openssl", + "serde", + "serde_json", + "serde_urlencoded", + "url", + "wildmatch", +] + [[package]] name = "atty" version = "0.2.14" @@ -411,6 +524,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + [[package]] name = "cairo-rs" version = "0.15.6" @@ -572,6 +691,15 @@ dependencies = [ "serde", ] +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", +] + [[package]] name = "config" version = "0.1.0" @@ -1080,6 +1208,17 @@ dependencies = [ "const-oid 0.7.1", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -1190,6 +1329,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" +[[package]] +name = "easy-parallel" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" + [[package]] name = "ecdsa" version = "0.12.4" @@ -1306,6 +1451,27 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enumflags2" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b3ab37dc79652c9d85f1f7b6070d77d321d2467f5fe7b00d6b7a86c57b092ae" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.7.1" @@ -1319,6 +1485,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "event-listener" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" + [[package]] name = "eyre" version = "0.6.7" @@ -2591,6 +2763,12 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minisign-verify" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" + [[package]] name = "miniz_oxide" version = "0.3.7" @@ -2738,6 +2916,19 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2910,6 +3101,17 @@ dependencies = [ "malloc_buf", ] +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + [[package]] name = "objc_id" version = "0.1.1" @@ -2980,6 +3182,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-stream" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "pairing" version = "0.20.0" @@ -3352,6 +3564,25 @@ dependencies = [ "miniz_oxide 0.3.7", ] +[[package]] +name = "polling" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +dependencies = [ + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + +[[package]] +name = "pollster" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" + [[package]] name = "polyval" version = "0.5.3" @@ -3839,6 +4070,32 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rfd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aaf1d71ccd44689f7c2c72da1117fd8db71f72a76fe9b5c5dbb17ab903007e0" +dependencies = [ + "ashpd", + "block", + "dispatch", + "glib-sys 0.15.6", + "gobject-sys 0.15.5", + "gtk-sys", + "js-sys", + "lazy_static", + "log", + "objc", + "objc-foundation", + "objc_id", + "pollster", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows", +] + [[package]] name = "ring" version = "0.16.20" @@ -4226,6 +4483,21 @@ dependencies = [ "digest 0.10.3", ] +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" version = "0.9.9" @@ -4637,6 +4909,8 @@ version = "1.0.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3571de0bcfd1f4f7599cbb3fe42f28ea9f52c3e89914ff04eaba68b5ee36bb51" dependencies = [ + "attohttpc", + "base64", "bincode", "cfg_aliases", "dirs-next", @@ -4650,12 +4924,14 @@ dependencies = [ "gtk", "http", "ignore", + "minisign-verify", "once_cell", "open", "percent-encoding", "rand 0.8.5", "raw-window-handle", "regex", + "rfd", "semver 1.0.6", "serde", "serde_json", @@ -5559,6 +5835,21 @@ dependencies = [ "windows-bindgen", ] +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "wildmatch" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c48bd20df7e4ced539c12f570f937c6b4884928a87fee70a479d72f031d4e0" + [[package]] name = "winapi" version = "0.3.9" @@ -5766,6 +6057,67 @@ dependencies = [ "libc", ] +[[package]] +name = "zbus" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb86f3d4592e26a48b2719742aec94f8ae6238ebde20d98183ee185d1275e9a" +dependencies = [ + "async-broadcast", + "async-channel", + "async-executor", + "async-io", + "async-lock", + "async-recursion", + "async-task", + "async-trait", + "byteorder", + "derivative", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "lazy_static", + "nix", + "once_cell", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "winapi", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36823cc10fddc3c6b19f048903262dacaf8274170e9a255784bdd8b4570a8040" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "zbus_names" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45dfcdcf87b71dad505d30cc27b1b7b88a64b6d1c435648f48f9dbc1fdc4b7e1" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + [[package]] name = "zeroize" version = "1.4.3" @@ -5829,3 +6181,29 @@ dependencies = [ "cc", "libc", ] + +[[package]] +name = "zvariant" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ea5dc38b2058fae6a5b79009388143dadce1e91c26a67f984a0fc0381c8033" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2cecc5a61c2a053f7f653a24cd15b3b0195d7f7ddb5042c837fb32e161fb7a" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "syn", +] diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index e2118fb646..7a894b86fe 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -30,7 +30,7 @@ reqwest = "0.11.9" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" strum = { version = "0.23", features = ["derive"] } -tauri = { version = "=1.0.0-rc.2", features = ["clipboard-all", "shell-open", "window-maximize"] } +tauri = { version = "=1.0.0-rc.2", features = ["clipboard-all", "shell-open", "updater", "window-maximize"] } tendermint-rpc = "0.23.0" thiserror = "1.0" tokio = { version = "1.10", features = ["sync", "time"] } From 3712b38230dbe4f9a290cd3762dd8c925ff4f02d Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Mon, 4 Apr 2022 15:02:36 +0100 Subject: [PATCH 10/16] Fix wallet lock file version --- nym-wallet/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index a3bf1b10e6..8b6f88cba6 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -3028,7 +3028,7 @@ dependencies = [ [[package]] name = "nym_wallet" -version = "1.0.1" +version = "1.0.2" dependencies = [ "aes-gcm", "argon2", From 1b37ff224299a9876fc50afe0c532f02ec96367e Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Mon, 4 Apr 2022 18:17:42 +0100 Subject: [PATCH 11/16] Update wallet lock file --- nym-wallet/Cargo.lock | 49 ++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 8b6f88cba6..bb2eda024e 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -820,35 +820,36 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.0.0-beta5" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8904127a5b9e325ef5d6b2b3f997dcd74943cd35097139b1a4d15b1b6bccae66" +checksum = "88c2565b1e73a816fb659ef4838fc356143fbd35f43c48a51d2d7d4e5d6679d3" dependencies = [ "digest 0.9.0", "ed25519-zebra", "k256 0.9.6", - "rand_core 0.5.1", + "rand_core 0.6.3", "thiserror", ] [[package]] name = "cosmwasm-derive" -version = "1.0.0-beta5" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a14364ac4d9d085867929d0cf3e94b1d2100121ce02c33c72961406830002613" +checksum = "fa89fcdf8dbbe0088e663d0a814aa7368e7ebe8fb045a3a150fb5fdc2ffe3b45" dependencies = [ "syn", ] [[package]] name = "cosmwasm-std" -version = "1.0.0-beta5" +version = "1.0.0-beta7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2ece12e5bbde434b93937d7b2107e6291f11d69ffa72398c50e8bab41d451d3" +checksum = "bcb8f99a61d0b9069e1afc80a4ffea87dcc3523edd992080923870b13a677da0" dependencies = [ "base64", "cosmwasm-crypto", "cosmwasm-derive", + "forward_ref", "schemars", "serde", "serde-json-wasm", @@ -1080,20 +1081,9 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "0.11.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7ee1963302b0ac2a9d42fe0faec826209c17452bfd36fbfd9d002a88929261" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-storage-plus" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c087ff98fb0475db4c2b5298a5fd12b2848d2854b39d1115d930ee6da24d1eed" +checksum = "5e8b7f9a758c030d375520df947323c052704f784561fc28dcaab4f988c50a30" dependencies = [ "cosmwasm-std", "schemars", @@ -1384,16 +1374,17 @@ dependencies = [ [[package]] name = "ed25519-zebra" -version = "2.2.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a128b76af6dd4b427e34a6fd43dc78dbfe73672ec41ff615a2414c1a0ad0409" +checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" dependencies = [ "curve25519-dalek", "hex", - "rand_core 0.5.1", + "rand_core 0.6.3", "serde", "sha2 0.9.9", "thiserror", + "zeroize", ] [[package]] @@ -1624,6 +1615,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -5594,11 +5591,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vesting-contract" -version = "0.1.0" +version = "1.0.0-rc.1" dependencies = [ "config", "cosmwasm-std", - "cw-storage-plus 0.12.1", + "cw-storage-plus", "mixnet-contract-common", "schemars", "serde", @@ -5612,7 +5609,7 @@ version = "0.1.0" dependencies = [ "config", "cosmwasm-std", - "cw-storage-plus 0.11.1", + "cw-storage-plus", "mixnet-contract-common", "schemars", "serde", From ca49fe22938b28eb025c43d11c5f6f7f36528401 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Tue, 5 Apr 2022 09:42:37 +0100 Subject: [PATCH 12/16] GitHub Actions fixes for publishing wallet --- .github/workflows/nym-wallet-publish-macos.yml | 6 +++++- .github/workflows/nym-wallet-publish-ubuntu.yml | 14 ++++++++++---- .github/workflows/nym-wallet-publish-windows10.yml | 6 +++++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/.github/workflows/nym-wallet-publish-macos.yml b/.github/workflows/nym-wallet-publish-macos.yml index 7cd484a7ee..23044a79f6 100644 --- a/.github/workflows/nym-wallet-publish-macos.yml +++ b/.github/workflows/nym-wallet-publish-macos.yml @@ -64,12 +64,16 @@ jobs: APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} run: yarn && yarn build - name: Upload to release based on tag name uses: softprops/action-gh-release@v1 with: - files: nym-wallet/target/release/bundle/dmg/*.dmg + files: | + nym-wallet/target/release/bundle/dmg/*.dmg + nym-wallet/target/release/bundle/macos/*.app.tar.gz* - name: Clean up keychain if: ${{ always() }} diff --git a/.github/workflows/nym-wallet-publish-ubuntu.yml b/.github/workflows/nym-wallet-publish-ubuntu.yml index 3b2c37ef20..36893ba388 100644 --- a/.github/workflows/nym-wallet-publish-ubuntu.yml +++ b/.github/workflows/nym-wallet-publish-ubuntu.yml @@ -37,10 +37,16 @@ jobs: uses: actions-rs/toolchain@v1 with: toolchain: stable - - name: Install app dependencies and build it - run: yarn && yarn build - + - name: Install app dependencies + run: yarn + - name: Build app + run: yarn build + env: + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - name: Upload to release based on tag name uses: softprops/action-gh-release@v1 with: - files: nym-wallet/target/release/bundle/appimage/*.AppImage + files: | + nym-wallet/target/release/bundle/appimage/*.AppImage + nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz* diff --git a/.github/workflows/nym-wallet-publish-windows10.yml b/.github/workflows/nym-wallet-publish-windows10.yml index c9e9e1ba83..132cb71df6 100644 --- a/.github/workflows/nym-wallet-publish-windows10.yml +++ b/.github/workflows/nym-wallet-publish-windows10.yml @@ -63,9 +63,13 @@ jobs: ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }} WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} run: yarn build - name: Upload to release based on tag name uses: softprops/action-gh-release@v1 with: - files: nym-wallet/target/release/bundle/msi/*.msi + files: | + nym-wallet/target/release/bundle/msi/*.msi + nym-wallet/target/release/bundle/msi/*.msi.zip* From c056269f0eebd9633c8a244e733402efd608a2b1 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Tue, 5 Apr 2022 15:37:38 +0100 Subject: [PATCH 13/16] Tagging release contracts --- Cargo.lock | 2 +- contracts/mixnet/Cargo.toml | 2 +- contracts/vesting/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac7e05cddf..39552decd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6052,7 +6052,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vesting-contract" -version = "1.0.0-rc.1" +version = "1.0.0" dependencies = [ "config", "cosmwasm-std", diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 59f04c9406..c7214c9d62 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mixnet-contract" -version = "1.0.0-rc.1" +version = "1.0.0" authors = ["Dave Hrycyszyn "] edition = "2021" diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index 1d0799e596..c11f8b8f65 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vesting-contract" -version = "1.0.0-rc.1" +version = "1.0.0" authors = ["Drazen Urch "] edition = "2021" From 515d4b73f745dc53095dce073db5bbc163204e88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 5 Apr 2022 16:52:16 +0100 Subject: [PATCH 14/16] Updated mainnet defaults to the most recent values --- common/network-defaults/src/mainnet.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index 87e9c1e562..c8f46de121 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -6,15 +6,17 @@ use crate::ValidatorDetails; pub(crate) const BECH32_PREFIX: &str = "n"; pub const DENOM: &str = "unym"; -pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; -pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; +pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = + "n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g"; +pub(crate) const VESTING_CONTRACT_ADDRESS: &str = + "n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw"; pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; pub(crate) const _ETH_CONTRACT_ADDRESS: [u8; 20] = hex_literal::hex!("0000000000000000000000000000000000000000"); pub(crate) const _ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = hex_literal::hex!("0000000000000000000000000000000000000000"); -pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "n17zujduc46wvkwvp6f062mm5xhr7jc3fewvqu9e"; +pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy"; pub(crate) fn validators() -> Vec { vec![ValidatorDetails::new( From c177f14073221199f8562bddfaa083b46d8f6470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 5 Apr 2022 17:35:50 +0100 Subject: [PATCH 15/16] Using fork of cosmrs with different address length validation --- common/client-libs/validator-client/Cargo.toml | 6 +----- nym-wallet/src-tauri/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 8e24671666..3d98efdbf6 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -29,11 +29,7 @@ validator-api-requests = { path = "../../../validator-api/validator-api-requests async-trait = { version = "0.1.51", optional = true } bip39 = { version = "1", features = ["rand"], optional = true } config = { path = "../../config", optional = true } -cosmrs = { version = "0.4.1", features = [ - "rpc", - "bip32", - "cosmwasm", -], optional = true } +cosmrs = { git = "https://github.com/nymtech/cosmos-rust", branch = "bugfix/account-id-length-validation", features = ["rpc", "bip32", "cosmwasm"], optional = true} prost = { version = "0.9", default-features = false, optional = true } flate2 = { version = "1.0.20", optional = true } sha2 = { version = "0.9.5", optional = true } diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 7a894b86fe..7456c1c219 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -42,7 +42,7 @@ argon2 = { version = "0.3.2", features = ["std"] } base64 = "0.13" zeroize = "1.4.3" -cosmrs = { version = "0.4.1", features = ["rpc", "bip32", "cosmwasm"] } +cosmrs = { git = "https://github.com/nymtech/cosmos-rust", branch = "bugfix/account-id-length-validation", features = ["rpc", "bip32", "cosmwasm"] } cosmwasm-std = "1.0.0-beta3" validator-client = { path = "../../common/client-libs/validator-client", features = [ From 9aa5b98465a149e7838e252091ff581adcd86367 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Thu, 7 Apr 2022 18:13:29 +0200 Subject: [PATCH 16/16] Debugging validator (#1198) * Checkpoint * Replace Stream logic with StreamMap * Ignore blacklisted mixnodes and gateways * Moar logging * Remove version checks * Cleanup * Some more cleanup --- Cargo.lock | 1 + .../gateway-client/src/packet_router.rs | 7 +- .../gateway-client/src/socket_state.rs | 2 +- validator-api/Cargo.toml | 1 + .../src/network_monitor/gateways_reader.rs | 176 ++---------------- .../monitor/gateways_pinger.rs | 24 ++- .../src/network_monitor/monitor/mod.rs | 22 ++- .../src/network_monitor/monitor/preparer.rs | 66 ++----- .../src/network_monitor/monitor/receiver.rs | 14 +- .../src/network_monitor/monitor/sender.rs | 8 +- 10 files changed, 84 insertions(+), 237 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 39552decd0..a79522613a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3100,6 +3100,7 @@ dependencies = [ "thiserror", "time 0.3.7", "tokio", + "tokio-stream", "topology", "url", "validator-api-requests", diff --git a/common/client-libs/gateway-client/src/packet_router.rs b/common/client-libs/gateway-client/src/packet_router.rs index 8fb35aed5f..7d650ad695 100644 --- a/common/client-libs/gateway-client/src/packet_router.rs +++ b/common/client-libs/gateway-client/src/packet_router.rs @@ -72,7 +72,12 @@ impl PacketRouter { if !received_acks.is_empty() { trace!("routing acks"); - self.ack_sender.unbounded_send(received_acks).unwrap(); + match self.ack_sender.unbounded_send(received_acks) { + Ok(_) => {} + Err(e) => { + error!("failed to send ack: {:?}", e); + } + }; } } } diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index 9fba57208f..5de854921c 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -74,7 +74,7 @@ impl PartiallyDelegated { // This would also require NOT discarding any text responses here. // TODO: those can return the "send confirmations" - perhaps it should be somehow worked around? - Message::Text(text) => debug!( + Message::Text(text) => trace!( "received a text message - probably a response to some previous query! - {}", text ), diff --git a/validator-api/Cargo.toml b/validator-api/Cargo.toml index c28d62d1af..c9f88f076a 100644 --- a/validator-api/Cargo.toml +++ b/validator-api/Cargo.toml @@ -15,6 +15,7 @@ rust-version = "1.56" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +tokio-stream = "0.1.8" clap = "2.33.0" dirs = "3.0" dotenv = "0.15.0" diff --git a/validator-api/src/network_monitor/gateways_reader.rs b/validator-api/src/network_monitor/gateways_reader.rs index 2d3b140885..53c0fd224c 100644 --- a/validator-api/src/network_monitor/gateways_reader.rs +++ b/validator-api/src/network_monitor/gateways_reader.rs @@ -2,181 +2,41 @@ // SPDX-License-Identifier: Apache-2.0 use crypto::asymmetric::identity; -use futures::stream::Stream; -use futures::task::Context; use gateway_client::{AcknowledgementReceiver, MixnetMessageReceiver}; -use std::pin::Pin; -use std::task::{Poll, Waker}; +use tokio_stream::StreamMap; -/// Constant used to determine maximum number of times the GatewayReader can poll. It basically -/// tries to solve the same problem that `FuturesUnordered` has: https://github.com/rust-lang/futures-rs/issues/2047 -const YIELD_EVERY: usize = 32; - -// TODO: Originally I set it to (identity::PublicKey, Vec>) and I definitely -// had a reason for doing so, but right now I can't remember what that was... pub(crate) type GatewayMessages = Vec>; -pub(crate) struct GatewayChannel { - id: identity::PublicKey, - message_receiver: MixnetMessageReceiver, - ack_receiver: AcknowledgementReceiver, - is_closed: bool, -} - -impl GatewayChannel { - pub(crate) fn new( - id: identity::PublicKey, - message_receiver: MixnetMessageReceiver, - ack_receiver: AcknowledgementReceiver, - ) -> Self { - GatewayChannel { - id, - message_receiver, - ack_receiver, - is_closed: false, - } - } -} - -impl Stream for GatewayChannel { - type Item = Vec>; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.is_closed { - return Poll::Ready(None); - } - - let mut polled = 0; - - // empty the ack channel if anything is on it (we don't care about the content at all at the - // moment) - while let Poll::Ready(_ack) = Pin::new(&mut self.ack_receiver).poll_next(cx) { - polled += 1; - } - - let item = futures::ready!(Pin::new(&mut self.message_receiver).poll_next(cx)); - - match item { - None => Poll::Ready(None), - // if we managed to get an item, try to also read additional ones - Some(mut messages) => { - while let Poll::Ready(new_item) = Pin::new(&mut self.message_receiver).poll_next(cx) - { - polled += 1; - match new_item { - None => { - self.is_closed = true; - cx.waker().wake_by_ref(); - return Poll::Ready(Some(messages)); - } - Some(mut additional_messages) => { - messages.append(&mut additional_messages); - - // it is fine enough to use the same constant here as in the main GatewayReader - // as only a single channel, i.e. the main gateway will be capable - // of returning more than 2 values - if polled >= YIELD_EVERY { - cx.waker().wake_by_ref(); - break; - } - } - } - } - Poll::Ready(Some(messages)) - } - } - } -} - pub(crate) struct GatewaysReader { - latest_read: usize, - // channels: FuturesUnordered, - channels: Vec, - waker: Option, + ack_map: StreamMap, + stream_map: StreamMap, } impl GatewaysReader { pub(crate) fn new() -> Self { GatewaysReader { - latest_read: 0, - channels: Vec::new(), - waker: None, + ack_map: StreamMap::new(), + stream_map: StreamMap::new(), } } - fn remove_nth(&mut self, i: usize) { - self.channels.remove(i); + pub fn stream_map(&mut self) -> &mut StreamMap { + &mut self.stream_map } - // todo: if we find that this method is called frequently, perhaps the vector should get - // replaced with different data structure - pub(crate) fn remove_by_key(&mut self, key: identity::PublicKey) { - match self.channels.iter().position(|item| item.id == key) { - Some(i) => { - self.channels.remove(i); - } - // this shouldn't ever get thrown, so perhaps a panic would be more in order? - None => error!( - "tried to remove gateway reader {} but it doesn't exist!", - key.to_base58_string() - ), - } - } - - fn poll_nth( + pub fn add_recievers( &mut self, - cx: &mut Context<'_>, - i: usize, - ) -> Option>> { - if let Poll::Ready(item) = Pin::new(&mut self.channels[i]).poll_next(cx) { - self.latest_read = i; - match item { - // Some(messages) => return Some(Poll::Ready(Some((self.channels[i].id, messages)))), - Some(messages) => return Some(Poll::Ready(Some(messages))), - // remove dead channel - None => self.remove_nth(i), - } - } - None + id: identity::PublicKey, + message_receiver: MixnetMessageReceiver, + ack_receiver: AcknowledgementReceiver, + ) { + let channel_id = id.to_string(); + self.stream_map.insert(channel_id.clone(), message_receiver); + self.ack_map.insert(channel_id, ack_receiver); } - pub(crate) fn insert_channel(&mut self, channel: GatewayChannel) { - self.channels.push(channel); - if let Some(waker) = self.waker.take() { - waker.wake() - } - } -} - -// TODO: not sure if this will scale well, but I don't know what would be a good alternative, -// perhaps try to somehow incorporate FuturesUnordered? -// also, perhaps reading should be done in parallel? -impl Stream for GatewaysReader { - // item represents gateway that returned messages alongside the actual messages - type Item = GatewayMessages; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.latest_read >= self.channels.len() { - self.latest_read = 0; - } - - // don't start reading from beginning each time to at least slightly help with the bias - for i in self.latest_read..self.channels.len() { - if let Some(item) = self.poll_nth(cx, i) { - return item; - } - } - - for i in 0..self.latest_read { - if let Some(item) = self.poll_nth(cx, i) { - return item; - } - } - - // if we have no channels available, store the waker to be woken when a new one is pushed - if self.channels.is_empty() { - self.waker = Some(cx.waker().clone()) - } - Poll::Pending + pub fn remove_recievers(&mut self, id: &str) { + self.stream_map.remove(id); + self.ack_map.remove(id); } } diff --git a/validator-api/src/network_monitor/monitor/gateways_pinger.rs b/validator-api/src/network_monitor/monitor/gateways_pinger.rs index b62c780db0..f7d47ca302 100644 --- a/validator-api/src/network_monitor/monitor/gateways_pinger.rs +++ b/validator-api/src/network_monitor/monitor/gateways_pinger.rs @@ -44,14 +44,17 @@ impl GatewayPinger { } async fn ping_and_cleanup_all_gateways(&self) { - info!(target: "GatewayPinger", "Pinging all active gateways"); + info!("Pinging all active gateways"); let lock_acquire_start = Instant::now(); let active_gateway_clients_guard = self.gateway_clients.lock().await; - trace!(target: "GatewayPinger", "Acquiring lock took {:?}", Instant::now().duration_since(lock_acquire_start)); + trace!( + "Acquiring lock took {:?}", + Instant::now().duration_since(lock_acquire_start) + ); if active_gateway_clients_guard.is_empty() { - debug!(target: "GatewayPinger", "no gateways to ping"); + debug!("no gateways to ping"); return; } @@ -89,7 +92,6 @@ impl GatewayPinger { { Err(_timeout) => { warn!( - target: "GatewayPinger", "we timed out trying to ping {} - assuming the connection is dead.", active_client.gateway_identity().to_base58_string(), ); @@ -97,7 +99,6 @@ impl GatewayPinger { } Ok(Err(err)) => { warn!( - target: "GatewayPinger", "failed to send ping message to gateway {} - {} - assuming the connection is dead.", active_client.gateway_identity().to_base58_string(), err, @@ -112,25 +113,34 @@ impl GatewayPinger { } } + info!( + "Purging {} gateways, acquiring lock", + clients_to_purge.len() + ); // purge all dead connections // reacquire the guard let lock_acquire_start = Instant::now(); let mut active_gateway_clients_guard = self.gateway_clients.lock().await; - trace!(target: "GatewayPinger", "Acquiring lock took {:?}", Instant::now().duration_since(lock_acquire_start)); + info!( + "Acquiring lock took {:?}", + Instant::now().duration_since(lock_acquire_start) + ); for gateway_id in clients_to_purge.into_iter() { if let Some(removed_handle) = active_gateway_clients_guard.remove(&gateway_id) { if !removed_handle.is_invalid().await { + info!("Handle is invalid, purging"); // it was not invalidated by the packet sender meaning it probably was some unbonded node // that was never cleared self.notify_connection_failure(gateway_id); } + info!("Handle is not invalid, not purged") } } let ping_end = Instant::now(); let time_taken = ping_end.duration_since(ping_start); - debug!(target: "GatewayPinger", "Pinging all active gateways took {:?}", time_taken); + info!("Pinging all active gateways took {:?}", time_taken); } pub(crate) async fn run(&self) { diff --git a/validator-api/src/network_monitor/monitor/mod.rs b/validator-api/src/network_monitor/monitor/mod.rs index ce3df86727..efd034710c 100644 --- a/validator-api/src/network_monitor/monitor/mod.rs +++ b/validator-api/src/network_monitor/monitor/mod.rs @@ -177,9 +177,9 @@ impl Monitor { for entry in results.iter() { if *entry.1 == self.route_test_packets { - debug!("✔️ {} succeeded", entry.0) + info!("✔️ {} succeeded", entry.0) } else { - debug!( + info!( "❌️ {} failed ({}/{} received)", entry.0, entry.1, self.route_test_packets ) @@ -200,7 +200,7 @@ impl Monitor { } async fn prepare_test_routes(&mut self) -> Option> { - info!(target: "Monitor", "Generating test routes..."); + info!("Generating test routes..."); // keep track of nodes that should not be used for route construction let mut blacklist = HashSet::new(); @@ -209,7 +209,7 @@ impl Monitor { let mut current_attempt = 0; // todo: tweak this to something more appropriate - let max_attempts = self.test_routes * 2; + let max_attempts = self.test_routes * 10; 'outer: loop { if current_attempt >= max_attempts { @@ -277,13 +277,12 @@ impl Monitor { .set_new_test_nonce(self.test_nonce) .await; - debug!("Sending packets to all gateways..."); + info!("Sending packets to all gateways..."); self.packet_sender .send_packets(prepared_packets.packets) .await; - debug!( - target: "Monitor", + info!( "Sending is over, waiting for {:?} before checking what we received", self.packet_delivery_timeout ); @@ -293,6 +292,8 @@ impl Monitor { let received = self.received_processor.return_received().await; let total_received = received.len(); + info!("Test routes: {:?}", routes); + info!("Received {}/{} packets", total_received, total_sent); let summary = self.summary_producer.produce_summary( prepared_packets.tested_mixnodes, @@ -310,11 +311,14 @@ impl Monitor { } async fn test_run(&mut self) { - info!(target: "Monitor", "Starting test run no. {}", self.test_nonce); + info!("Starting test run no. {}", self.test_nonce); let start = Instant::now(); if let Some(test_routes) = self.prepare_test_routes().await { - debug!(target: "Monitor", "Determined reliable routes to test all other nodes against. : {:?}", test_routes); + info!( + "Determined reliable routes to test all other nodes against. : {:?}", + test_routes + ); self.test_network_against(&test_routes).await; } else { error!("We failed to construct sufficient number of test routes to test the network against") diff --git a/validator-api/src/network_monitor/monitor/preparer.rs b/validator-api/src/network_monitor/monitor/preparer.rs index 2b48c8da1d..2169fc3cba 100644 --- a/validator-api/src/network_monitor/monitor/preparer.rs +++ b/validator-api/src/network_monitor/monitor/preparer.rs @@ -25,6 +25,7 @@ type Id = String; type Owner = Addr; #[derive(Clone)] +#[allow(dead_code)] pub(crate) enum InvalidNode { Outdated(Id, Owner, Version), Malformed(Id, Owner), @@ -188,8 +189,8 @@ impl PacketPreparer { info!("Waiting for minimal topology to be online"); let initialisation_backoff = Duration::from_secs(30); loop { - let gateways = self.validator_cache.gateways().await; - let mixnodes = self.validator_cache.rewarded_set().await; + let gateways = self.validator_cache.gateways_all().await; + let mixnodes = self.validator_cache.mixnodes_all().await; if gateways.len() < minimum_full_routes { info!( @@ -201,7 +202,7 @@ impl PacketPreparer { } let mut layered_mixes = HashMap::new(); - for mix in mixnodes.into_inner() { + for mix in mixnodes { let layer = mix.layer; let mixes = layered_mixes.entry(layer).or_insert_with(Vec::new); mixes.push(mix) @@ -229,7 +230,7 @@ impl PacketPreparer { } async fn all_mixnodes_and_gateways(&self) -> (Vec, Vec) { - info!(target: "Monitor", "Obtaining network topology..."); + info!("Obtaining network topology..."); let mixnodes = self.validator_cache.mixnodes_all().await; let gateways = self.validator_cache.gateways_all().await; @@ -239,9 +240,6 @@ impl PacketPreparer { pub(crate) fn try_parse_mix_bond(&self, mix: &MixNodeBond) -> Result { let identity = mix.mix_node.identity_key.clone(); - if !self.check_version_compatibility(&mix.mix_node.version) { - return Err(identity); - } mix.try_into().map_err(|_| identity) } @@ -250,9 +248,6 @@ impl PacketPreparer { gateway: &GatewayBond, ) -> Result { let identity = gateway.gateway.identity_key.clone(); - if !self.check_version_compatibility(&gateway.gateway.version) { - return Err(identity); - } gateway.try_into().map_err(|_| identity) } @@ -270,19 +265,10 @@ impl PacketPreparer { // separate mixes into layers for easier selection let mut layered_mixes = HashMap::new(); for mix in mixnodes { - // filter out mixes on the blacklist - if blacklist.contains(&mix.mix_node.identity_key) { - continue; - } let layer = mix.layer; let mixes = layered_mixes.entry(layer).or_insert_with(Vec::new); mixes.push(mix) } - // filter out gateways on the blacklist - let gateways = gateways - .into_iter() - .filter(|gateway| !blacklist.contains(&gateway.gateway.identity_key)) - .collect::>(); // get all nodes from each layer... let l1 = layered_mixes.get(&Layer::One)?; @@ -297,9 +283,6 @@ impl PacketPreparer { let rand_l3 = l3.choose_multiple(&mut rng, n).collect::>(); let rand_gateways = gateways.choose_multiple(&mut rng, n).collect::>(); - // let rand_gateways = gateways.iter().filter(|g| g.gateway.host == "109.74.196.254".to_string()).collect::>(); - // let rand_gateways = gateways.iter().filter(|g| g.gateway.host == "185.3.94.33".to_string()).collect::>(); - // the unwrap on `min()` is fine as we know the iterator is not empty let most_available = *[ rand_l1.len(), @@ -312,9 +295,10 @@ impl PacketPreparer { .unwrap(); if most_available == 0 { - // it's impossible to generate a single route + error!("Cannot construct test routes. No nodes or gateways available"); None } else { + trace!("Generating test routes..."); let mut routes = Vec::new(); for i in 0..most_available { let node_1 = match self.try_parse_mix_bond(rand_l1[i]) { @@ -358,14 +342,11 @@ impl PacketPreparer { gateway, )) } + info!("{:?}", routes); Some(routes) } } - fn check_version_compatibility(&self, node_version: &str) -> bool { - version_checker::is_minor_version_compatible(node_version, &self.system_version) - } - fn create_packet_sender(&self, gateway: &gateway::Node) -> Recipient { Recipient::new( self.self_public_identity, @@ -404,14 +385,6 @@ impl PacketPreparer { let mut parsed_nodes = Vec::new(); let mut invalid_nodes = Vec::new(); for mixnode in nodes { - if !self.check_version_compatibility(&mixnode.mix_node.version) { - invalid_nodes.push(InvalidNode::Outdated( - mixnode.mix_node.identity_key, - mixnode.owner, - mixnode.mix_node.version, - )); - continue; - } if let Ok(parsed_node) = (&mixnode).try_into() { parsed_nodes.push(parsed_node) } else { @@ -431,14 +404,6 @@ impl PacketPreparer { let mut parsed_nodes = Vec::new(); let mut invalid_nodes = Vec::new(); for gateway in nodes { - if !self.check_version_compatibility(&gateway.gateway.version) { - invalid_nodes.push(InvalidNode::Outdated( - gateway.gateway.identity_key, - gateway.owner, - gateway.gateway.version, - )); - continue; - } if let Ok(parsed_node) = (&gateway).try_into() { parsed_nodes.push(parsed_node) } else { @@ -460,18 +425,17 @@ impl PacketPreparer { // (remember that "idle" nodes are still part of that set) // we don't care about other nodes, i.e. nodes that are bonded but will not get // any reward during the current rewarding interval - let (rewarded_set, all_gateways) = self.all_mixnodes_and_gateways().await; + let (mixnodes, gateways) = self.all_mixnodes_and_gateways().await; - let (mixes, invalid_mixnodes) = self.filter_outdated_and_malformed_mixnodes(rewarded_set); - let (gateways, invalid_gateways) = - self.filter_outdated_and_malformed_gateways(all_gateways); + let (mixnodes, invalid_mixnodes) = self.filter_outdated_and_malformed_mixnodes(mixnodes); + let (gateways, invalid_gateways) = self.filter_outdated_and_malformed_gateways(gateways); - let tested_mixnodes = mixes.iter().map(|node| node.into()).collect::>(); + let tested_mixnodes = mixnodes.iter().map(|node| node.into()).collect::>(); let tested_gateways = gateways.iter().map(|node| node.into()).collect::>(); let packets_to_create = (test_routes.len() * self.per_node_test_packets) * (tested_mixnodes.len() + tested_gateways.len()); - info!(target: "TestPreparer", "Need to create {} mix packets", packets_to_create); + info!("Need to create {} mix packets", packets_to_create); let mut all_gateway_packets = HashMap::new(); @@ -483,10 +447,10 @@ impl PacketPreparer { let gateway_owner = test_route.gateway_owner(); // it's actually going to be a tiny bit more due to gateway testing, but it's a good enough approximation - let mut mix_packets = Vec::with_capacity(mixes.len() * self.per_node_test_packets); + let mut mix_packets = Vec::with_capacity(mixnodes.len() * self.per_node_test_packets); // and for each mixnode... - for mixnode in &mixes { + for mixnode in &mixnodes { let test_packet = TestPacket::from_mixnode(mixnode, test_route.id(), test_nonce); let topology = test_route.substitute_mix(mixnode); // produce n mix packets diff --git a/validator-api/src/network_monitor/monitor/receiver.rs b/validator-api/src/network_monitor/monitor/receiver.rs index 5cefb3894d..f837cb9f80 100644 --- a/validator-api/src/network_monitor/monitor/receiver.rs +++ b/validator-api/src/network_monitor/monitor/receiver.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::network_monitor::gateways_reader::{GatewayChannel, GatewayMessages, GatewaysReader}; +use crate::network_monitor::gateways_reader::{GatewayMessages, GatewaysReader}; use crate::network_monitor::monitor::processor::ReceivedProcessorSender; use crypto::asymmetric::identity; use futures::channel::mpsc; @@ -40,10 +40,12 @@ impl PacketReceiver { fn process_gateway_update(&mut self, update: GatewayClientUpdate) { match update { GatewayClientUpdate::New(id, (message_receiver, ack_receiver)) => { - let channel = GatewayChannel::new(id, message_receiver, ack_receiver); - self.gateways_reader.insert_channel(channel); + self.gateways_reader + .add_recievers(id, message_receiver, ack_receiver); + } + GatewayClientUpdate::Failure(id) => { + self.gateways_reader.remove_recievers(&id.to_string()); } - GatewayClientUpdate::Failure(id) => self.gateways_reader.remove_by_key(id), } } @@ -62,7 +64,9 @@ impl PacketReceiver { // similarly gateway reader will never return a `None` as it's implemented // as an infinite stream that returns Poll::Pending if it doesn't have anything // to return - messages = self.gateways_reader.next() => self.process_gateway_messages(messages.unwrap()), + Some((_gateway_id, message)) = self.gateways_reader.stream_map().next() => { + self.process_gateway_messages(message) + } } } } diff --git a/validator-api/src/network_monitor/monitor/sender.rs b/validator-api/src/network_monitor/monitor/sender.rs index f650cc4b04..29fd943321 100644 --- a/validator-api/src/network_monitor/monitor/sender.rs +++ b/validator-api/src/network_monitor/monitor/sender.rs @@ -232,14 +232,13 @@ impl PacketSender { ) -> Result<(), GatewayClientError> { let gateway_id = client.gateway_identity().to_base58_string(); info!( - target: "MessageSender", "Got {} packets to send to gateway {}", mix_packets.len(), gateway_id ); if mix_packets.len() <= max_sending_rate { - debug!(target: "MessageSender","Everything is going to get sent as one."); + debug!("Everything is going to get sent as one."); client.batch_send_mix_packets(mix_packets).await?; } else { let packets_per_time_chunk = @@ -248,7 +247,6 @@ impl PacketSender { let total_expected_time = Duration::from_secs_f64(mix_packets.len() as f64 / max_sending_rate as f64); info!( - target: "MessageSender", "With our rate of {} packets/s it should take around {:?} to send it all to {} ...", max_sending_rate, total_expected_time, gateway_id ); @@ -268,7 +266,7 @@ impl PacketSender { // this way we won't have to do reallocations in here as they're unavoidable when // splitting a vector into multiple vectors while let Some(retained) = split_off_vec(&mut mix_packets, packets_per_time_chunk) { - trace!(target: "MessageSender","Sending {} packets...", mix_packets.len()); + trace!("Sending {} packets...", mix_packets.len()); if mix_packets.len() == 1 { client.send_mix_packet(mix_packets.pop().unwrap()).await?; @@ -280,7 +278,7 @@ impl PacketSender { mix_packets = retained; } - debug!(target: "MessageSender", "Done sending"); + debug!("Done sending"); } Ok(())