diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..4b56a90efe --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,32 @@ +--- +name: Feature request +about: Suggest an enhancement to the product +title: "[Feature Request]" +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is... + +**Is your request a feature not related to an existing problem? A new feature.** +For example. +- Given I am using the nym wallet +- When I transfer nym tokens across the network +- Then I want to have an url link in the wallet which navigates outside the application to the nym-explorer + +**Where does the feature fit in the Nym real estate?** +- Application / UI + +**What is this solving?** +How will this improve the product... + +**Is this an update to packages or libraries?** +If so, please list them. If not, please ignore this section. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/report.md b/.github/ISSUE_TEMPLATE/report.md new file mode 100644 index 0000000000..3dac5eb4f5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/report.md @@ -0,0 +1,43 @@ +--- +name: Report +about: To help identify and reproduce issues +title: "[Issue]" +labels: bug, bug-needs-triage, qa +assignees: tommyv1987 + +--- + +**Describe the issue** +A clear and concise description of what the issue is... + +**Expected behaviour** +A clear and concise description of what you expected to happen... + +**Stack Traces** +If there are stack traces or logs, please provide them here... + +**Steps to Reproduce** +Steps to reproduce the behaviour, if you're familiar with BDD syntax, please write it in this style: +- Given I was doing X +- And I installed Y +- When I actioned Y +- Then I expect Z + +*An example:* +- Given I was setting up a mix-node following the instructions in the docs +- And I successfully bonded my node via the the wallet +- When I went to start my mixnode +- Then I was presented with an error + +**Screenshots** +If applicable, add screenshots to help explain your problem... + +**Which area of Nym were you using?** + - UI: [e.g. Websites - network-explorer, nym-website] + - Application: [e.g Gateway, Client, Wallet] + - OS: [e.g. Ubuntu 20.x, MacOs Big Sur, Windows 10] + - Browser: [e.g Chrome (if applicable)] + - Version: [e.g. nym binary(0.11.0), browser(94.0)] + +**Additional context** +Please provide any other information diff --git a/.github/workflows/nym-wallet-tests.yml b/.github/workflows/nym-wallet-tests.yml deleted file mode 100644 index 8b13789179..0000000000 --- a/.github/workflows/nym-wallet-tests.yml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/.github/workflows/nym_wallet.yml b/.github/workflows/nym_wallet.yml index 58a093c66b..47864cd3e2 100644 --- a/.github/workflows/nym_wallet.yml +++ b/.github/workflows/nym_wallet.yml @@ -1,9 +1,10 @@ -name: webdriverio tests for nym wallet +name: Webdriverio tests for nym wallet on: push: paths: - - '/tauri-wallet/*' + - 'tauri-wallet/**' + defaults: run: working-directory: tauri-wallet @@ -12,7 +13,6 @@ jobs: test: name: wallet tests runs-on: ubuntu-latest - steps: - uses: actions/checkout@v2 @@ -27,18 +27,44 @@ jobs: webkit2gtk-driver xvfb + - name: Install minimal stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + - name: Node v16 uses: actions/setup-node@v1 with: node-version: 16.x + - name: Install yarn for building application + run: yarn install + - name: Build application run: yarn run webpack:build & yarn run tauri:build - working-directory: tauri-wallet + + - name: Check binary exists + run: | + cd target/release/ + (test -f nym-wallet && echo nym binary exists) || echo wallet does not exist - - name: Yarn install + - name: Install dependencies run: yarn install - working-directory: webdriver/ + working-directory: tauri-wallet/webdriver + + - name: Remove existing user datafile + uses: JesseTG/rm@v1.0.2 + with: + path: tauri-wallet/webdriver/common/data/user-data.json + + - name: Create user data json file + id: create-json + uses: jsdaniell/create-json@1.1.2 + with: + name: "user-data.json" + json: ${{ secrets.WALLET_USERDATA }} + dir: 'tauri-wallet/webdriver/common/data/' - name: Install tauri-driver uses: actions-rs/cargo@v1 @@ -47,5 +73,5 @@ jobs: args: tauri-driver - name: Launch tests - run: xvfb-run yarn test:login - working-directory: webdriver/ + run: xvfb-run yarn test:newuser + working-directory: tauri-wallet/webdriver diff --git a/Cargo.lock b/Cargo.lock index afe8a1a2e3..51efe09911 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,15 +12,6 @@ dependencies = [ "regex", ] -[[package]] -name = "addr2line" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" @@ -66,15 +57,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "anomaly" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550632e31568ae1a5f47998c3aa48563030fc49b9ec91913ca337cf64fbc5ccb" -dependencies = [ - "backtrace", -] - [[package]] name = "ansi_term" version = "0.11.0" @@ -246,21 +228,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "backtrace" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide 0.4.4", - "object", - "rustc-demangle", -] - [[package]] name = "base-x" version = "0.2.8" @@ -864,9 +831,9 @@ dependencies = [ [[package]] name = "cosmos-sdk-proto" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7115eae4b8518967b8e737a3ef76025f2d007de7906d88c18f00b8bbfc70f51e" +checksum = "edb5204c6ddc4352c74297638b5561f2929d6334866c156e5f3c75e1e1a1436a" dependencies = [ "prost", "prost-types", @@ -875,9 +842,9 @@ dependencies = [ [[package]] name = "cosmrs" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609eba7eee6d9929927cbdf15f9fe96d250c316c5e1b983c4a47a10f60da5ea7" +checksum = "d31147fe89e547e74e2692e4bec35387e1ea406fe8cfb14c0ea177b58fd2a8a9" dependencies = [ "bip32", "cosmos-sdk-proto", @@ -888,6 +855,8 @@ dependencies = [ "prost", "prost-types", "rand_core 0.6.3", + "serde", + "serde_json", "subtle-encoding", "tendermint", "tendermint-rpc", @@ -1527,7 +1496,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" dependencies = [ - "serde", "signature", ] @@ -1541,7 +1509,6 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", - "serde_bytes", "sha2", "zeroize", ] @@ -1738,6 +1705,16 @@ dependencies = [ "miniz_oxide 0.4.4", ] +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "eyre", + "paste", +] + [[package]] name = "fluvio-wasm-timer" version = "0.2.5" @@ -2120,12 +2097,6 @@ dependencies = [ "syn", ] -[[package]] -name = "gimli" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" - [[package]] name = "gio" version = "0.14.6" @@ -2608,6 +2579,7 @@ dependencies = [ "tokio", "tokio-rustls", "webpki", + "webpki-roots", ] [[package]] @@ -2768,15 +2740,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.10.1" @@ -3716,15 +3679,6 @@ dependencies = [ "objc", ] -[[package]] -name = "object" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" -dependencies = [ - "memchr", -] - [[package]] name = "okapi" version = "0.6.0-alpha-1" @@ -3874,6 +3828,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "paste" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" + [[package]] name = "pbkdf2" version = "0.8.0" @@ -3906,6 +3866,33 @@ dependencies = [ "syn", ] +[[package]] +name = "peg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088" + [[package]] name = "pem" version = "0.8.3" @@ -4283,9 +4270,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e6984d2f1a23009bd270b8bb56d0926810a3d483f59c987d77969e9d8e840b2" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ "bytes", "prost-derive", @@ -4293,12 +4280,12 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", - "itertools 0.9.0", + "itertools", "proc-macro2", "quote", "syn", @@ -4306,9 +4293,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b518d7cdd93dab1d1122cf07fa9a60771836c668dde9d9e2a139f957f0d9f1bb" +checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ "bytes", "prost", @@ -4927,12 +4914,6 @@ dependencies = [ "quote", ] -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - [[package]] name = "rustc_version" version = "0.2.3" @@ -5513,7 +5494,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ - "itertools 0.10.1", + "itertools", "nom", "unicode_categories", ] @@ -5999,7 +5980,7 @@ dependencies = [ "anyhow", "cfg-expr", "heck", - "itertools 0.10.1", + "itertools", "pkg-config", "strum 0.21.0", "strum_macros 0.21.1", @@ -6214,16 +6195,16 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0752808f59b612916614e92e43be64e9ba566b762a266bcfcf7dce1b324e9319" +checksum = "50d1cdb0236becb17ab35a2ed1566503e412fd910944dc940239857bb7663652" dependencies = [ - "anomaly", "async-trait", "bytes", "chrono", "ed25519", "ed25519-dalek", + "flex-error", "futures", "k256", "num-traits", @@ -6240,21 +6221,32 @@ dependencies = [ "subtle 2.4.1", "subtle-encoding", "tendermint-proto", - "thiserror", - "toml", - "url", "zeroize", ] [[package]] -name = "tendermint-proto" -version = "0.21.0" +name = "tendermint-config" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd0371c6b0c7fc4f6b053b8a1bc868a2a47c49a1408c4cd6f595d9f3bd3c238" +checksum = "2a1f94250d30e3011130a09756b05985d8dbfbd562cf261b5a17e36d89a37992" +dependencies = [ + "flex-error", + "serde", + "serde_json", + "tendermint", + "toml", + "url", +] + +[[package]] +name = "tendermint-proto" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff16a7b42bdbcf31c8cd10a4cffc7631f2a301360ba3a3f71dde48eabfa5bced" dependencies = [ - "anomaly", "bytes", "chrono", + "flex-error", "num-derive", "num-traits", "prost", @@ -6262,30 +6254,32 @@ dependencies = [ "serde", "serde_bytes", "subtle-encoding", - "thiserror", ] [[package]] name = "tendermint-rpc" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fa8d172e3129802d28de980531993dd25cc01841c5bc8fe4a87c7750a7f222" +checksum = "c7842dcd5edb60b077572aa92ff8b29fc810b9b463310f9810a2607474130db4" dependencies = [ "async-trait", "bytes", "chrono", + "flex-error", "futures", "getrandom 0.1.16", "http", "hyper", "hyper-proxy", "hyper-rustls", + "peg", "pin-project", "serde", "serde_bytes", "serde_json", "subtle-encoding", "tendermint", + "tendermint-config", "tendermint-proto", "thiserror", "tokio", @@ -6577,21 +6571,9 @@ checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98863d0dd09fa59a1b79c6750ad80dbda6b75f4e71c437a6a1a8cb91a8bcbd77" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" version = "0.1.20" @@ -6812,7 +6794,7 @@ dependencies = [ "cosmrs", "cosmwasm-std", "flate2", - "itertools 0.10.1", + "itertools", "log", "mixnet-contract", "network-defaults", diff --git a/Cargo.toml b/Cargo.toml index 49f75e91b9..cd74684817 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ [profile.release] panic = "abort" opt-level = "s" +overflow-checks = true [profile.dev] panic = "abort" diff --git a/clients/client-core/src/client/topology_control.rs b/clients/client-core/src/client/topology_control.rs index 0863e1e867..f8a9949776 100644 --- a/clients/client-core/src/client/topology_control.rs +++ b/clients/client-core/src/client/topology_control.rs @@ -257,7 +257,7 @@ impl TopologyRefresher { Ok(mixes) => mixes, }; - let gateways = match self.validator_client.get_cached_active_gateways().await { + let gateways = match self.validator_client.get_cached_gateways().await { Err(err) => { error!("failed to get network gateways - {}", err); return None; diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 3691af376a..5b63e59310 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -3,6 +3,7 @@ name = "nym-client" version = "0.11.0" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] edition = "2018" +rust-version = "1.56" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index 9976db2ac7..a8c58b1a70 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -3,6 +3,7 @@ name = "nym-socks5-client" version = "0.11.0" authors = ["Dave Hrycyszyn "] edition = "2018" +rust-version = "1.56" [lib] name = "nym_socks5" diff --git a/clients/webassembly/Cargo.toml b/clients/webassembly/Cargo.toml index b128e1a974..6386867f44 100644 --- a/clients/webassembly/Cargo.toml +++ b/clients/webassembly/Cargo.toml @@ -7,6 +7,7 @@ keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"] license = "Apache-2.0" repository = "https://github.com/nymtech/nym" description = "A webassembly client which can be used to interact with the the Nym privacy platform. Wasm is used for Sphinx packet generation." +rust-version = "1.56" [lib] crate-type = ["cdylib", "rlib"] diff --git a/clients/webassembly/src/client/mod.rs b/clients/webassembly/src/client/mod.rs index 66a1a3817b..2712f42d66 100644 --- a/clients/webassembly/src/client/mod.rs +++ b/clients/webassembly/src/client/mod.rs @@ -301,7 +301,7 @@ impl NymClient { }; let gateways = match validator_client.get_cached_gateways().await { - Err(err) => panic!("{:?}", err), + Err(err) => panic!("{}", err), Ok(gateways) => gateways, }; diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index 80b8085499..b82e9907b3 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -173,9 +173,9 @@ impl PartiallyDelegated { // this call failing is incredibly unlikely, but not impossible. // basically the gateway connection must have failed after executing previous line but // before starting execution of this one. - if notify.send(()).is_err() { - return Err(GatewayClientError::ConnectionAbruptlyClosed); - } + notify + .send(()) + .map_err(|_| GatewayClientError::ConnectionAbruptlyClosed)?; let stream_results: Result<_, GatewayClientError> = stream_receiver .await diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 78c7519e4f..11f4c14119 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -3,6 +3,7 @@ name = "validator-client" version = "0.1.0" authors = ["Jędrzej Stuczyński "] edition = "2018" +rust-version = "1.56" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -25,8 +26,8 @@ network-defaults = { path = "../../network-defaults" } async-trait = { version = "0.1.51", optional = true } bip39 = { version = "1", features = ["rand"], optional = true } config = { path = "../../config", optional = true } -cosmrs = { version = "0.1", features = ["rpc", "bip32", "cosmwasm"], optional = true } -prost = { version = "0.7", default-features = false, optional = true } +cosmrs = { version = "0.3", 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 } itertools = { version = "0.10", optional = true } diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index 48535ba7d8..0e2533b37d 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -24,7 +24,6 @@ pub struct Config { mixnode_page_limit: Option, gateway_page_limit: Option, mixnode_delegations_page_limit: Option, - gateway_delegations_page_limit: Option, } #[cfg(feature = "nymd-client")] @@ -41,7 +40,6 @@ impl Config { mixnode_page_limit: None, gateway_page_limit: None, mixnode_delegations_page_limit: None, - gateway_delegations_page_limit: None, } } @@ -59,11 +57,6 @@ impl Config { self.mixnode_delegations_page_limit = limit; self } - - pub fn with_gateway_delegations_page_limit(mut self, limit: Option) -> Config { - self.gateway_delegations_page_limit = limit; - self - } } #[cfg(feature = "nymd-client")] @@ -74,7 +67,6 @@ pub struct Client { mixnode_page_limit: Option, gateway_page_limit: Option, mixnode_delegations_page_limit: Option, - gateway_delegations_page_limit: Option, // ideally they would have been read-only, but unfortunately rust doesn't have such features pub validator_api: validator_api::Client, @@ -100,7 +92,6 @@ impl Client { mixnode_page_limit: config.mixnode_page_limit, gateway_page_limit: config.gateway_page_limit, mixnode_delegations_page_limit: config.mixnode_delegations_page_limit, - gateway_delegations_page_limit: config.gateway_delegations_page_limit, validator_api: validator_api_client, nymd: nymd_client, }) @@ -136,7 +127,6 @@ impl Client { mixnode_page_limit: config.mixnode_page_limit, gateway_page_limit: config.gateway_page_limit, mixnode_delegations_page_limit: config.mixnode_delegations_page_limit, - gateway_delegations_page_limit: config.gateway_delegations_page_limit, validator_api: validator_api_client, nymd: nymd_client, }) @@ -339,116 +329,6 @@ impl Client { Ok(delegations) } - pub async fn get_all_nymd_single_gateway_delegations( - &self, - identity: mixnet_contract::IdentityKey, - ) -> Result, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - let mut delegations = Vec::new(); - let mut start_after = None; - loop { - let mut paged_response = self - .nymd - .get_gateway_delegations( - identity.clone(), - start_after.take(), - self.gateway_delegations_page_limit, - ) - .await?; - delegations.append(&mut paged_response.delegations); - - if let Some(start_after_res) = paged_response.start_next_after { - start_after = Some(start_after_res) - } else { - break; - } - } - - Ok(delegations) - } - - pub async fn get_all_nymd_gateway_delegations( - &self, - ) -> Result>, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - let mut delegations = Vec::new(); - let mut start_after = None; - loop { - let mut paged_response = self - .nymd - .get_all_gateway_delegations( - start_after.take(), - self.gateway_delegations_page_limit, - ) - .await?; - delegations.append(&mut paged_response.delegations); - - if let Some(start_after_res) = paged_response.start_next_after { - start_after = Some(start_after_res) - } else { - break; - } - } - - Ok(delegations) - } - - pub async fn get_all_nymd_reverse_gateway_delegations( - &self, - delegation_owner: &cosmrs::AccountId, - ) -> Result, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - let mut delegations = Vec::new(); - let mut start_after = None; - loop { - let mut paged_response = self - .nymd - .get_reverse_gateway_delegations_paged( - mixnet_contract::Addr::unchecked(delegation_owner.as_ref()), - start_after.take(), - self.mixnode_delegations_page_limit, - ) - .await?; - delegations.append(&mut paged_response.delegated_nodes); - - if let Some(start_after_res) = paged_response.start_next_after { - start_after = Some(start_after_res) - } else { - break; - } - } - - Ok(delegations) - } - - pub async fn get_all_nymd_gateway_delegations_of_owner( - &self, - delegation_owner: &cosmrs::AccountId, - ) -> Result, ValidatorClientError> - where - C: CosmWasmClient + Sync, - { - let mut delegations = Vec::new(); - for node_identity in self - .get_all_nymd_reverse_gateway_delegations(delegation_owner) - .await? - { - let delegation = self - .nymd - .get_gateway_delegation(node_identity, delegation_owner) - .await?; - delegations.push(delegation); - } - - Ok(delegations) - } - pub async fn blind_sign( &self, request_body: &BlindSignRequestBody, @@ -488,12 +368,6 @@ impl ApiClient { Ok(self.validator_api.get_active_mixnodes().await?) } - pub async fn get_cached_active_gateways( - &self, - ) -> Result, ValidatorClientError> { - Ok(self.validator_api.get_active_gateways().await?) - } - pub async fn get_cached_mixnodes(&self) -> Result, ValidatorClientError> { Ok(self.validator_api.get_mixnodes().await?) } diff --git a/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs b/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs index 8bd8a0b207..7edbcb39ae 100644 --- a/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs +++ b/common/client-libs/validator-client/src/nymd/cosmwasm_client/client.rs @@ -22,7 +22,7 @@ use cosmrs::rpc::query::Query; use cosmrs::rpc::{self, HttpClient, Order}; use cosmrs::tendermint::abci::Transaction; use cosmrs::tendermint::{abci, block, chain}; -use cosmrs::{AccountId, Coin, Denom}; +use cosmrs::{tx, AccountId, Coin, Denom}; use prost::Message; use serde::{Deserialize, Serialize}; use std::convert::{TryFrom, TryInto}; @@ -153,12 +153,9 @@ pub trait CosmWasmClient: rpc::Client { .map_err(|_| NymdError::SerializationError("Coins".to_owned())) } - // disabled until https://github.com/tendermint/tendermint/issues/6802 - // and consequently https://github.com/informalsystems/tendermint-rs/issues/942 is resolved - // - // async fn get_tx(&self, id: tx::Hash) -> Result { - // Ok(self.tx(id, false).await?) - // } + async fn get_tx(&self, id: tx::Hash) -> Result { + Ok(self.tx(id, false).await?) + } async fn search_tx(&self, query: Query) -> Result, NymdError> { // according to https://docs.tendermint.com/master/rpc/#/Info/tx_search diff --git a/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs b/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs index eebdbdf7fd..ab650b36c0 100644 --- a/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs +++ b/common/client-libs/validator-client/src/nymd/cosmwasm_client/signing_client.rs @@ -13,8 +13,8 @@ use cosmrs::distribution::MsgWithdrawDelegatorReward; use cosmrs::rpc::endpoint::broadcast; use cosmrs::rpc::{Error as TendermintRpcError, HttpClient, HttpClientUrl, SimpleRequest}; use cosmrs::staking::{MsgDelegate, MsgUndelegate}; -use cosmrs::tx::{Fee, Msg, MsgType, SignDoc, SignerInfo}; -use cosmrs::{cosmwasm, rpc, tx, AccountId, Coin}; +use cosmrs::tx::{Fee, Msg, SignDoc, SignerInfo}; +use cosmrs::{cosmwasm, rpc, tx, AccountId, Any, Coin}; use log::debug; use serde::Serialize; use sha2::Digest; @@ -52,7 +52,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { .unwrap_or_default(), instantiate_permission: Default::default(), } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgStoreCode".to_owned()))?; let tx_res = self @@ -114,7 +114,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { init_msg: serde_json::to_vec(msg)?, funds: options.map(|options| options.funds).unwrap_or_default(), } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgInstantiateContract".to_owned()))?; let tx_res = self @@ -154,7 +154,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { new_admin: new_admin.clone(), contract: contract_address.clone(), } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgUpdateAdmin".to_owned()))?; let tx_res = self @@ -179,7 +179,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { sender: sender_address.clone(), contract: contract_address.clone(), } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgClearAdmin".to_owned()))?; let tx_res = self @@ -211,7 +211,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { code_id, migrate_msg: serde_json::to_vec(msg)?, } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgMigrateContract".to_owned()))?; let tx_res = self @@ -243,7 +243,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { msg: serde_json::to_vec(msg)?, funds, } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgExecuteContract".to_owned()))?; let tx_res = self @@ -278,7 +278,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { msg: serde_json::to_vec(&msg)?, funds, } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgExecuteContract".to_owned())) }) .collect::>()?; @@ -312,7 +312,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { to_address: recipient_address.clone(), amount, } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgSend".to_owned()))?; self.sign_and_broadcast_commit(sender_address, vec![send_msg], fee, memo) @@ -332,7 +332,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { validator_address: validator_address.to_owned(), amount, } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgDelegate".to_owned()))?; self.sign_and_broadcast_commit(delegator_address, vec![delegate_msg], fee, memo) @@ -352,7 +352,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { validator_address: validator_address.to_owned(), amount: Some(amount), } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgUndelegate".to_owned()))?; self.sign_and_broadcast_commit(delegator_address, vec![undelegate_msg], fee, memo) @@ -370,7 +370,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { delegator_address: delegator_address.to_owned(), validator_address: validator_address.to_owned(), } - .to_msg() + .to_any() .map_err(|_| NymdError::SerializationError("MsgWithdrawDelegatorReward".to_owned()))?; self.sign_and_broadcast_commit(delegator_address, vec![withdraw_msg], fee, memo) @@ -381,7 +381,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { async fn sign_and_broadcast_async( &self, signer_address: &AccountId, - messages: Vec, + messages: Vec, fee: Fee, memo: impl Into + Send + 'static, ) -> Result { @@ -397,7 +397,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { async fn sign_and_broadcast_sync( &self, signer_address: &AccountId, - messages: Vec, + messages: Vec, fee: Fee, memo: impl Into + Send + 'static, ) -> Result { @@ -413,7 +413,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { async fn sign_and_broadcast_commit( &self, signer_address: &AccountId, - messages: Vec, + messages: Vec, fee: Fee, memo: impl Into + Send + 'static, ) -> Result { @@ -428,7 +428,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { fn sign_direct( &self, signer_address: &AccountId, - messages: Vec, + messages: Vec, fee: Fee, memo: impl Into + Send + 'static, signer_data: SignerData, @@ -466,7 +466,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient { async fn sign( &self, signer_address: &AccountId, - messages: Vec, + messages: Vec, fee: Fee, memo: impl Into + Send + 'static, ) -> Result { @@ -506,7 +506,7 @@ impl Client { #[async_trait] impl rpc::Client for Client { - async fn perform(&self, request: R) -> rpc::Result + async fn perform(&self, request: R) -> Result where R: SimpleRequest, { diff --git a/common/client-libs/validator-client/src/nymd/error.rs b/common/client-libs/validator-client/src/nymd/error.rs index a9a709b955..e1e2e114fd 100644 --- a/common/client-libs/validator-client/src/nymd/error.rs +++ b/common/client-libs/validator-client/src/nymd/error.rs @@ -7,7 +7,10 @@ use cosmrs::{bip32, tx, AccountId}; use std::io; use thiserror::Error; -pub use cosmrs::rpc::error::{Code, Error as TendermintRpcError}; +pub use cosmrs::rpc::error::{ + Error as TendermintRpcError, ErrorDetail as TendermintRpcErrorDetail, +}; +pub use cosmrs::rpc::response_error::{Code, ResponseError}; #[derive(Debug, Error)] pub enum NymdError { @@ -102,17 +105,21 @@ pub enum NymdError { } impl NymdError { - pub fn is_tendermint_timeout(&self) -> bool { + pub fn is_tendermint_response_timeout(&self) -> bool { match &self { - NymdError::TendermintError(tm_err) => { - if tm_err.code() == Code::InternalError { + NymdError::TendermintError(TendermintRpcError( + TendermintRpcErrorDetail::Response(err), + _, + )) => { + let response = &err.source; + if response.code() == Code::InternalError { // 0.34 (and earlier) versions of tendermint seemed to be using phrase "timed out waiting ..." // (https://github.com/tendermint/tendermint/blob/v0.34.13/rpc/core/mempool.go#L124) // while 0.35+ has "timeout waiting for ..." // https://github.com/tendermint/tendermint/blob/v0.35.0-rc3/internal/rpc/core/mempool.go#L99 // note that as of the time of writing this comment (08.10.2021), the most recent version // of cosmos-sdk (v0.44.1) uses tendermint 0.34.13 - if let Some(data) = tm_err.data() { + if let Some(data) = response.data() { data.contains("timed out") || data.contains("timeout") } else { false @@ -125,14 +132,18 @@ impl NymdError { } } - pub fn is_tendermint_duplicate(&self) -> bool { + pub fn is_tendermint_response_duplicate(&self) -> bool { match &self { - NymdError::TendermintError(tm_err) => { - if tm_err.code() == Code::InternalError { + NymdError::TendermintError(TendermintRpcError( + TendermintRpcErrorDetail::Response(err), + _, + )) => { + let response = &err.source; + if response.code() == Code::InternalError { // this particular error message seems to be unchanged between 0.34 and newer versions // https://github.com/tendermint/tendermint/blob/v0.34.13/mempool/errors.go#L10 // https://github.com/tendermint/tendermint/blob/v0.35.0-rc3/types/mempool.go#L10 - if let Some(data) = tm_err.data() { + if let Some(data) = response.data() { data.contains("tx already exists in cache") } else { false diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 2ec670fb6e..54477ca013 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -15,8 +15,7 @@ use cosmwasm_std::Coin; use mixnet_contract::{ Addr, Delegation, ExecuteMsg, Gateway, GatewayOwnershipResponse, IdentityKey, LayerDistribution, MixNode, MixOwnershipResponse, PagedAllDelegationsResponse, - PagedGatewayDelegationsResponse, PagedGatewayResponse, PagedMixDelegationsResponse, - PagedMixnodeResponse, PagedReverseGatewayDelegationsResponse, + PagedGatewayResponse, PagedMixDelegationsResponse, PagedMixnodeResponse, PagedReverseMixDelegationsResponse, QueryMsg, RawDelegationData, StateParams, }; use serde::Serialize; @@ -354,82 +353,6 @@ impl NymdClient { .await } - /// Gets list of all delegations towards particular gateway on particular page. - pub async fn get_gateway_delegations( - &self, - gateway_identity: IdentityKey, - start_after: Option, - page_limit: Option, - ) -> Result - where - C: CosmWasmClient + Sync, - { - let request = QueryMsg::GetGatewayDelegations { - gateway_identity, - start_after, - limit: page_limit, - }; - self.client - .query_contract_smart(self.contract_address()?, &request) - .await - } - - /// Gets list of all gateway delegations on particular page. - pub async fn get_all_gateway_delegations( - &self, - start_after: Option>, - page_limit: Option, - ) -> Result, NymdError> - where - C: CosmWasmClient + Sync, - { - let request = QueryMsg::GetAllGatewayDelegations { - start_after, - limit: page_limit, - }; - self.client - .query_contract_smart(self.contract_address()?, &request) - .await - } - - /// Gets list of all the gateways on which a particular address delegated. - pub async fn get_reverse_gateway_delegations_paged( - &self, - delegation_owner: Addr, - start_after: Option, - page_limit: Option, - ) -> Result - where - C: CosmWasmClient + Sync, - { - let request = QueryMsg::GetReverseGatewayDelegations { - delegation_owner, - start_after, - limit: page_limit, - }; - self.client - .query_contract_smart(self.contract_address()?, &request) - .await - } - - /// Checks value of delegation of given client towards particular gateway. - pub async fn get_gateway_delegation( - &self, - gateway_identity: IdentityKey, - delegator: &AccountId, - ) -> Result - where - C: CosmWasmClient + Sync, - { - let request = QueryMsg::GetGatewayDelegation { - gateway_identity, - address: Addr::unchecked(delegator.as_ref()), - }; - self.client - .query_contract_smart(self.contract_address()?, &request) - .await - } - /// Send funds from one address to another pub async fn send( &self, @@ -698,57 +621,6 @@ impl NymdClient { .await } - /// Delegates specified amount of stake to particular gateway. - pub async fn delegate_to_gateway( - &self, - gateway_identity: &str, - amount: &Coin, - ) -> Result - where - C: SigningCosmWasmClient + Sync, - { - let fee = self.get_fee(Operation::DelegateToGateway); - - let req = ExecuteMsg::DelegateToGateway { - gateway_identity: gateway_identity.to_string(), - }; - self.client - .execute( - self.address(), - self.contract_address()?, - &req, - fee, - "Delegating to gateway from rust!", - vec![cosmwasm_coin_ptr_to_cosmos_coin(amount)], - ) - .await - } - - /// Removes stake delegation from a particular gateway. - pub async fn remove_gateway_delegation( - &self, - gateway_identity: &str, - ) -> Result - where - C: SigningCosmWasmClient + Sync, - { - let fee = self.get_fee(Operation::UndelegateFromGateway); - - let req = ExecuteMsg::UndelegateFromGateway { - gateway_identity: gateway_identity.to_string(), - }; - self.client - .execute( - self.address(), - self.contract_address()?, - &req, - fee, - "Removing gateway delegation from rust!", - Vec::new(), - ) - .await - } - pub async fn update_state_params( &self, new_params: StateParams, diff --git a/common/client-libs/validator-client/src/validator_api/mod.rs b/common/client-libs/validator-client/src/validator_api/mod.rs index dcc448d7d9..8b993a5b7e 100644 --- a/common/client-libs/validator-client/src/validator_api/mod.rs +++ b/common/client-libs/validator-client/src/validator_api/mod.rs @@ -73,11 +73,6 @@ impl Client { .await } - pub async fn get_active_gateways(&self) -> Result, ValidatorAPIError> { - self.query_validator_api(&[routes::API_VERSION, routes::GATEWAYS, routes::ACTIVE]) - .await - } - pub async fn blind_sign( &self, request_body: &BlindSignRequestBody, diff --git a/common/crypto/src/hkdf.rs b/common/crypto/src/hkdf.rs index 8791ea1bbf..5300947448 100644 --- a/common/crypto/src/hkdf.rs +++ b/common/crypto/src/hkdf.rs @@ -5,18 +5,13 @@ use digest::{BlockInput, FixedOutput, Reset, Update}; use generic_array::ArrayLength; use hkdf::Hkdf; -#[derive(Debug)] -pub enum HkdfError { - InvalidOkmLength, -} - /// Perform HKDF `extract` then `expand` as a single step. pub fn extract_then_expand( salt: Option<&[u8]>, ikm: &[u8], info: Option<&[u8]>, okm_length: usize, -) -> Result, HkdfError> +) -> Result, hkdf::InvalidLength> where D: Update + BlockInput + FixedOutput + Reset + Default + Clone, D::BlockSize: ArrayLength, @@ -27,9 +22,7 @@ where let hkdf = Hkdf::::new(salt, ikm); let mut okm = vec![0u8; okm_length]; - if hkdf.expand(info.unwrap_or_else(|| &[]), &mut okm).is_err() { - return Err(HkdfError::InvalidOkmLength); - } + hkdf.expand(info.unwrap_or_else(|| &[]), &mut okm)?; Ok(okm) } diff --git a/common/mixnet-contract/src/delegation.rs b/common/mixnet-contract/src/delegation.rs index 65fc4c1dd2..87d6e63a51 100644 --- a/common/mixnet-contract/src/delegation.rs +++ b/common/mixnet-contract/src/delegation.rs @@ -120,48 +120,6 @@ impl PagedReverseMixDelegationsResponse { } } -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] -pub struct PagedGatewayDelegationsResponse { - pub node_identity: IdentityKey, - pub delegations: Vec, - pub start_next_after: Option, -} - -impl PagedGatewayDelegationsResponse { - pub fn new( - node_identity: IdentityKey, - delegations: Vec, - start_next_after: Option, - ) -> Self { - PagedGatewayDelegationsResponse { - node_identity, - delegations, - start_next_after, - } - } -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] -pub struct PagedReverseGatewayDelegationsResponse { - pub delegation_owner: Addr, - pub delegated_nodes: Vec, - pub start_next_after: Option, -} - -impl PagedReverseGatewayDelegationsResponse { - pub fn new( - delegation_owner: Addr, - delegated_nodes: Vec, - start_next_after: Option, - ) -> Self { - PagedReverseGatewayDelegationsResponse { - delegation_owner, - delegated_nodes, - start_next_after, - } - } -} - #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct PagedAllDelegationsResponse { pub delegations: Vec>, diff --git a/common/mixnet-contract/src/gateway.rs b/common/mixnet-contract/src/gateway.rs index 6318452ecb..25c9fe0bab 100644 --- a/common/mixnet-contract/src/gateway.rs +++ b/common/mixnet-contract/src/gateway.rs @@ -2,15 +2,13 @@ #![allow(clippy::field_reassign_with_default)] use crate::{IdentityKey, SphinxKey}; -use cosmwasm_std::{coin, Addr, Coin}; +use cosmwasm_std::{Addr, Coin}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use std::fmt::Display; use ts_rs::TS; -use crate::current_block_height; - #[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize, JsonSchema, TS)] pub struct Gateway { pub host: String, @@ -26,9 +24,7 @@ pub struct Gateway { #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)] pub struct GatewayBond { pub bond_amount: Coin, - pub total_delegation: Coin, pub owner: Addr, - #[serde(default = "current_block_height")] pub block_height: u64, pub gateway: Gateway, } @@ -36,7 +32,6 @@ pub struct GatewayBond { impl GatewayBond { pub fn new(bond_amount: Coin, owner: Addr, block_height: u64, gateway: Gateway) -> Self { GatewayBond { - total_delegation: coin(0, &bond_amount.denom), bond_amount, owner, block_height, @@ -64,27 +59,11 @@ impl GatewayBond { impl PartialOrd for GatewayBond { fn partial_cmp(&self, other: &Self) -> Option { // first remove invalid cases - if self.bond_amount.denom != self.total_delegation.denom { - return None; - } - - if other.bond_amount.denom != other.total_delegation.denom { - return None; - } - if self.bond_amount.denom != other.bond_amount.denom { return None; } - // try to order by total bond + delegation - let total_cmp = (self.bond_amount.amount + self.total_delegation.amount) - .partial_cmp(&(self.bond_amount.amount + self.total_delegation.amount))?; - - if total_cmp != Ordering::Equal { - return Some(total_cmp); - } - - // then if those are equal, prefer higher bond over delegation + // try to order by total bond let bond_cmp = self .bond_amount .amount @@ -93,15 +72,6 @@ impl PartialOrd for GatewayBond { return Some(bond_cmp); } - // then look at delegation (I'm not sure we can get here, but better safe than sorry) - let delegation_cmp = self - .total_delegation - .amount - .partial_cmp(&other.total_delegation.amount)?; - if delegation_cmp != Ordering::Equal { - return Some(delegation_cmp); - } - // then check block height let height_cmp = self.block_height.partial_cmp(&other.block_height)?; if height_cmp != Ordering::Equal { @@ -175,20 +145,19 @@ mod tests { #[test] fn gateway_bond_partial_ord() { let _150foos = Coin::new(150, "foo"); + let _140foos = Coin::new(140, "foo"); let _50foos = Coin::new(50, "foo"); let _0foos = Coin::new(0, "foo"); let gate1 = GatewayBond { bond_amount: _150foos.clone(), - total_delegation: _50foos.clone(), owner: Addr::unchecked("foo1"), block_height: 100, gateway: gateway_fixture(), }; let gate2 = GatewayBond { - bond_amount: _150foos.clone(), - total_delegation: _50foos.clone(), + bond_amount: _150foos, owner: Addr::unchecked("foo2"), block_height: 120, gateway: gateway_fixture(), @@ -196,15 +165,13 @@ mod tests { let gate3 = GatewayBond { bond_amount: _50foos, - total_delegation: _150foos.clone(), owner: Addr::unchecked("foo3"), block_height: 120, gateway: gateway_fixture(), }; let gate4 = GatewayBond { - bond_amount: _150foos.clone(), - total_delegation: _0foos.clone(), + bond_amount: _140foos, owner: Addr::unchecked("foo4"), block_height: 120, gateway: gateway_fixture(), @@ -212,21 +179,19 @@ mod tests { let gate5 = GatewayBond { bond_amount: _0foos, - total_delegation: _150foos, owner: Addr::unchecked("foo5"), block_height: 120, gateway: gateway_fixture(), }; // summary: - // gate1: 150bond + 50delegation, foo1, 100 - // gate2: 150bond + 50delegation, foo2, 120 - // gate3: 50bond + 150delegation, foo3, 120 - // gate4: 150bond + 0delegation, foo4, 120 - // gate5: 0bond + 150delegation, foo5, 120 + // gate1: 150bond, foo1, 100 + // gate2: 150bond, foo2, 120 + // gate3: 50bond, foo3, 120 + // gate4: 140bond, foo4, 120 + // gate5: 0bond, foo5, 120 - // highest total bond+delegation is used - // then bond followed by delegation + // highest total bond is used // finally just the rest of the fields // gate1 has higher total than gate4 or gate5 diff --git a/common/mixnet-contract/src/lib.rs b/common/mixnet-contract/src/lib.rs index 23295df1a2..ffecdea57c 100644 --- a/common/mixnet-contract/src/lib.rs +++ b/common/mixnet-contract/src/lib.rs @@ -9,18 +9,10 @@ mod types; pub use cosmwasm_std::{Addr, Coin}; pub use delegation::{ - Delegation, PagedAllDelegationsResponse, PagedGatewayDelegationsResponse, - PagedMixDelegationsResponse, PagedReverseGatewayDelegationsResponse, + Delegation, PagedAllDelegationsResponse, PagedMixDelegationsResponse, PagedReverseMixDelegationsResponse, RawDelegationData, UnpackedDelegation, }; pub use gateway::{Gateway, GatewayBond, GatewayOwnershipResponse, PagedGatewayResponse}; pub use mixnode::{Layer, MixNode, MixNodeBond, MixOwnershipResponse, PagedMixnodeResponse}; pub use msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; pub use types::{IdentityKey, IdentityKeyRef, LayerDistribution, SphinxKey, StateParams}; - -use std::sync::atomic::{AtomicU64, Ordering}; -pub static CURRENT_BLOCK_HEIGHT: AtomicU64 = AtomicU64::new(0); - -pub fn current_block_height() -> u64 { - CURRENT_BLOCK_HEIGHT.load(Ordering::Relaxed) -} diff --git a/common/mixnet-contract/src/mixnode.rs b/common/mixnet-contract/src/mixnode.rs index 53610ab36e..25cce43c11 100644 --- a/common/mixnet-contract/src/mixnode.rs +++ b/common/mixnet-contract/src/mixnode.rs @@ -10,8 +10,6 @@ use std::cmp::Ordering; use std::fmt::Display; use ts_rs::TS; -use crate::current_block_height; - #[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize, JsonSchema, TS)] pub struct MixNode { pub host: String, @@ -41,7 +39,6 @@ pub struct MixNodeBond { pub total_delegation: Coin, pub owner: Addr, pub layer: Layer, - #[serde(default = "current_block_height")] pub block_height: u64, pub mix_node: MixNode, } diff --git a/common/mixnet-contract/src/msg.rs b/common/mixnet-contract/src/msg.rs index 15b4193369..dfda40befa 100644 --- a/common/mixnet-contract/src/msg.rs +++ b/common/mixnet-contract/src/msg.rs @@ -31,25 +31,11 @@ pub enum ExecuteMsg { mix_identity: IdentityKey, }, - DelegateToGateway { - gateway_identity: IdentityKey, - }, - - UndelegateFromGateway { - gateway_identity: IdentityKey, - }, - RewardMixnode { identity: IdentityKey, // percentage value in range 0-100 uptime: u32, }, - - RewardGateway { - identity: IdentityKey, - // percentage value in range 0-100 - uptime: u32, - }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -88,24 +74,6 @@ pub enum QueryMsg { mix_identity: IdentityKey, address: Addr, }, - GetGatewayDelegations { - gateway_identity: IdentityKey, - start_after: Option, - limit: Option, - }, - GetAllGatewayDelegations { - start_after: Option>, - limit: Option, - }, - GetReverseGatewayDelegations { - delegation_owner: Addr, - start_after: Option, - limit: Option, - }, - GetGatewayDelegation { - gateway_identity: IdentityKey, - address: Addr, - }, LayerDistribution {}, } diff --git a/common/mixnet-contract/src/types.rs b/common/mixnet-contract/src/types.rs index bc3e3eb24f..b2a16515fe 100644 --- a/common/mixnet-contract/src/types.rs +++ b/common/mixnet-contract/src/types.rs @@ -32,12 +32,10 @@ pub struct StateParams { pub minimum_mixnode_bond: Uint128, // minimum amount a mixnode must bond to get into the system pub minimum_gateway_bond: Uint128, // minimum amount a gateway must bond to get into the system + pub mixnode_bond_reward_rate: Decimal, // annual reward rate, expressed as a decimal like 1.25 - pub gateway_bond_reward_rate: Decimal, // annual reward rate, expressed as a decimal like 1.25 pub mixnode_delegation_reward_rate: Decimal, // annual reward rate, expressed as a decimal like 1.25 - pub gateway_delegation_reward_rate: Decimal, // annual reward rate, expressed as a decimal like 1.25 pub mixnode_active_set_size: u32, - pub gateway_active_set_size: u32, } impl Display for StateParams { @@ -51,30 +49,15 @@ impl Display for StateParams { "mixnode bond reward rate: {}; ", self.mixnode_bond_reward_rate )?; - write!( - f, - "gateway bond reward rate: {}; ", - self.gateway_bond_reward_rate - )?; write!( f, "mixnode delegation reward rate: {}; ", self.mixnode_delegation_reward_rate )?; - write!( - f, - "gateway delegation reward rate: {}; ", - self.gateway_delegation_reward_rate - )?; write!( f, "mixnode active set size: {}", self.mixnode_active_set_size - )?; - write!( - f, - "gateway active set size: {} ]", - self.gateway_active_set_size ) } } diff --git a/common/nymsphinx/src/receiver.rs b/common/nymsphinx/src/receiver.rs index 01f308ac75..c3e9aebd9d 100644 --- a/common/nymsphinx/src/receiver.rs +++ b/common/nymsphinx/src/receiver.rs @@ -156,11 +156,9 @@ impl MessageReceiver { }; // Finally, remove the zero padding from the message - if Self::remove_padding(&mut message).is_err() { - return Err(MessageRecoveryError::MalformedReconstructedMessage( - used_sets, - )); - }; + Self::remove_padding(&mut message).map_err(|_| { + MessageRecoveryError::MalformedReconstructedMessage(used_sets.clone()) + })?; Ok(Some(( ReconstructedMessage { @@ -270,7 +268,6 @@ mod message_receiver { vec![gateway::Node { owner: "foomp4".to_string(), stake: 123, - delegation: 456, location: "unknown".to_string(), host: "1.2.3.4".parse().unwrap(), mix_host: "1.2.3.4:1789".parse().unwrap(), diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index 45fb7b0dfd..f617089592 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -72,7 +72,6 @@ pub struct Node { // somebody correct me if I'm wrong, but we should only ever have a single denom of currency // on the network at a type, right? pub stake: u128, - pub delegation: u128, pub location: String, pub host: NetworkAddress, // we're keeping this as separate resolved field since we do not want to be resolving the potential @@ -127,7 +126,6 @@ impl<'a> TryFrom<&'a GatewayBond> for Node { Ok(Node { owner: bond.owner.as_str().to_owned(), stake: bond.bond_amount.amount.into(), - delegation: bond.total_delegation.amount.into(), location: bond.gateway.location.clone(), host, mix_host, diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 8321e1fc3a..4dc9dac8e4 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -22,18 +22,13 @@ pub const INITIAL_MIXNODE_BOND: Uint128 = Uint128(100_000000); // percentage annual increase. Given starting value of x, we expect to have 1.1x at the end of the year pub const INITIAL_MIXNODE_BOND_REWARD_RATE: u64 = 110; -pub const INITIAL_GATEWAY_BOND_REWARD_RATE: u64 = 110; pub const INITIAL_MIXNODE_DELEGATION_REWARD_RATE: u64 = 110; -pub const INITIAL_GATEWAY_DELEGATION_REWARD_RATE: u64 = 110; pub const INITIAL_MIXNODE_ACTIVE_SET_SIZE: u32 = 100; -pub const INITIAL_GATEWAY_ACTIVE_SET_SIZE: u32 = 20; fn default_initial_state(owner: Addr) -> State { let mixnode_bond_reward_rate = Decimal::percent(INITIAL_MIXNODE_BOND_REWARD_RATE); - let gateway_bond_reward_rate = Decimal::percent(INITIAL_GATEWAY_BOND_REWARD_RATE); let mixnode_delegation_reward_rate = Decimal::percent(INITIAL_MIXNODE_DELEGATION_REWARD_RATE); - let gateway_delegation_reward_rate = Decimal::percent(INITIAL_GATEWAY_DELEGATION_REWARD_RATE); State { owner, @@ -43,28 +38,17 @@ fn default_initial_state(owner: Addr) -> State { minimum_mixnode_bond: INITIAL_MIXNODE_BOND, minimum_gateway_bond: INITIAL_GATEWAY_BOND, mixnode_bond_reward_rate, - gateway_bond_reward_rate, mixnode_delegation_reward_rate, - gateway_delegation_reward_rate, mixnode_active_set_size: INITIAL_MIXNODE_ACTIVE_SET_SIZE, - gateway_active_set_size: INITIAL_GATEWAY_ACTIVE_SET_SIZE, }, mixnode_epoch_bond_reward: calculate_epoch_reward_rate( INITIAL_DEFAULT_EPOCH_LENGTH, mixnode_bond_reward_rate, ), - gateway_epoch_bond_reward: calculate_epoch_reward_rate( - INITIAL_DEFAULT_EPOCH_LENGTH, - gateway_bond_reward_rate, - ), mixnode_epoch_delegation_reward: calculate_epoch_reward_rate( INITIAL_DEFAULT_EPOCH_LENGTH, mixnode_delegation_reward_rate, ), - gateway_epoch_delegation_reward: calculate_epoch_reward_rate( - INITIAL_DEFAULT_EPOCH_LENGTH, - gateway_delegation_reward_rate, - ), } } @@ -110,21 +94,12 @@ pub fn execute( ExecuteMsg::RewardMixnode { identity, uptime } => { transactions::try_reward_mixnode(deps, env, info, identity, uptime) } - ExecuteMsg::RewardGateway { identity, uptime } => { - transactions::try_reward_gateway(deps, env, info, identity, uptime) - } ExecuteMsg::DelegateToMixnode { mix_identity } => { transactions::try_delegate_to_mixnode(deps, env, info, mix_identity) } ExecuteMsg::UndelegateFromMixnode { mix_identity } => { transactions::try_remove_delegation_from_mixnode(deps, info, mix_identity) } - ExecuteMsg::DelegateToGateway { gateway_identity } => { - transactions::try_delegate_to_gateway(deps, env, info, gateway_identity) - } - ExecuteMsg::UndelegateFromGateway { gateway_identity } => { - transactions::try_remove_delegation_from_gateway(deps, info, gateway_identity) - } } } @@ -176,37 +151,6 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result to_binary(&queries::query_gateway_delegations_paged( - deps, - gateway_identity, - start_after, - limit, - )?), - QueryMsg::GetAllGatewayDelegations { start_after, limit } => to_binary( - &queries::query_all_gateway_delegations_paged(deps, start_after, limit)?, - ), - QueryMsg::GetReverseGatewayDelegations { - delegation_owner, - start_after, - limit, - } => to_binary(&queries::query_reverse_gateway_delegations_paged( - deps, - delegation_owner, - start_after, - limit, - )?), - QueryMsg::GetGatewayDelegation { - gateway_identity, - address, - } => to_binary(&queries::query_gateway_delegation( - deps, - gateway_identity, - address, - )?), }; Ok(query_res?) diff --git a/contracts/mixnet/src/error.rs b/contracts/mixnet/src/error.rs index 652533d6d0..3610edee30 100644 --- a/contracts/mixnet/src/error.rs +++ b/contracts/mixnet/src/error.rs @@ -48,15 +48,9 @@ pub enum ContractError { #[error("The bond reward rate for mixnode was set to be lower than 1")] DecreasingMixnodeBondReward, - #[error("The bond reward rate for gateway was set to be lower than 1")] - DecreasingGatewayBondReward, - #[error("The delegation reward rate for mixnode was set to be lower than 1")] DecreasingMixnodeDelegationReward, - #[error("The delegation reward rate for gateway was set to be lower than 1")] - DecreasingGatewayDelegationReward, - #[error("The node had uptime larger than 100%")] UnexpectedUptime, @@ -83,10 +77,4 @@ pub enum ContractError { identity: IdentityKey, address: Addr, }, - - #[error("Could not find any delegation information associated with gateway {identity} for {address}")] - NoGatewayDelegationFound { - identity: IdentityKey, - address: Addr, - }, } diff --git a/contracts/mixnet/src/helpers.rs b/contracts/mixnet/src/helpers.rs index 0bb672dbad..de5636a0ac 100644 --- a/contracts/mixnet/src/helpers.rs +++ b/contracts/mixnet/src/helpers.rs @@ -209,10 +209,7 @@ impl<'a, T: Clone + Serialize + DeserializeOwned> Iterator for Delegations<'a, T mod tests { use super::*; use crate::queries::tests::store_n_mix_delegations; - use crate::storage::{ - all_gateway_delegations_read, all_mix_delegations_read, gateway_delegations, - mix_delegations, - }; + use crate::storage::{all_mix_delegations_read, mix_delegations}; use crate::support::tests::helpers; use cosmwasm_std::testing::mock_dependencies; use mixnet_contract::RawDelegationData; @@ -389,66 +386,4 @@ mod tests { UnpackedDelegation::new(delegation_owner2, node_identity2, raw_delegation.clone()), ); } - - #[test] - fn all_gateway_delegations() { - let mut deps = mock_dependencies(&[]); - let node_identity1: IdentityKey = "foo1".into(); - let delegation_owner1 = Addr::unchecked("bar1"); - let node_identity2: IdentityKey = "foo2".into(); - let delegation_owner2 = Addr::unchecked("bar2"); - let raw_delegation = RawDelegationData::new(1000u128.into(), 42); - let mut start_after = None; - - gateway_delegations(&mut deps.storage, &node_identity1) - .save(delegation_owner1.as_bytes(), &raw_delegation) - .unwrap(); - - let bucket = all_gateway_delegations_read::(&deps.storage); - let response = - get_all_delegations_paged::(&bucket, &start_after, 10).unwrap(); - start_after = response.start_next_after; - let delegations = response.delegations; - assert_eq!(delegations.len(), 1); - assert_eq!( - delegations[0], - UnpackedDelegation::new( - delegation_owner1.clone(), - node_identity1.clone(), - raw_delegation.clone() - ) - ); - - gateway_delegations(&mut deps.storage, &node_identity2) - .save(delegation_owner2.as_bytes(), &raw_delegation) - .unwrap(); - - let bucket = all_gateway_delegations_read::(&deps.storage); - let response = - get_all_delegations_paged::(&bucket, &start_after, 10).unwrap(); - start_after = response.start_next_after; - let delegations = response.delegations; - assert_eq!(delegations.len(), 2); - assert_eq!( - delegations[1], - UnpackedDelegation::new( - delegation_owner2.clone(), - node_identity2.clone(), - raw_delegation.clone() - ) - ); - - gateway_delegations(&mut deps.storage, &node_identity1) - .remove(delegation_owner1.as_bytes()); - - let bucket = all_gateway_delegations_read::(&deps.storage); - let response = - get_all_delegations_paged::(&bucket, &start_after, 10).unwrap(); - let delegations = response.delegations; - assert_eq!(delegations.len(), 1); - assert_eq!( - delegations[0], - UnpackedDelegation::new(delegation_owner2, node_identity2, raw_delegation.clone()), - ); - } } diff --git a/contracts/mixnet/src/queries.rs b/contracts/mixnet/src/queries.rs index 0d2c3826aa..e76d62a93c 100644 --- a/contracts/mixnet/src/queries.rs +++ b/contracts/mixnet/src/queries.rs @@ -4,19 +4,17 @@ use crate::error::ContractError; use crate::helpers::get_all_delegations_paged; use crate::storage::{ - all_gateway_delegations_read, all_mix_delegations_read, gateway_delegations_read, - gateways_owners_read, gateways_read, mix_delegations_read, mixnodes_owners_read, mixnodes_read, - read_layer_distribution, read_state_params, reverse_gateway_delegations_read, + all_mix_delegations_read, gateways_owners_read, gateways_read, mix_delegations_read, + mixnodes_owners_read, mixnodes_read, read_layer_distribution, read_state_params, reverse_mix_delegations_read, }; use config::defaults::DENOM; use cosmwasm_std::{coin, Addr, Deps, Order, StdResult}; use mixnet_contract::{ Delegation, GatewayBond, GatewayOwnershipResponse, IdentityKey, LayerDistribution, MixNodeBond, - MixOwnershipResponse, PagedAllDelegationsResponse, PagedGatewayDelegationsResponse, - PagedGatewayResponse, PagedMixDelegationsResponse, PagedMixnodeResponse, - PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse, RawDelegationData, - StateParams, + MixOwnershipResponse, PagedAllDelegationsResponse, PagedGatewayResponse, + PagedMixDelegationsResponse, PagedMixnodeResponse, PagedReverseMixDelegationsResponse, + RawDelegationData, StateParams, }; const BOND_PAGE_MAX_LIMIT: u32 = 100; @@ -211,114 +209,11 @@ pub(crate) fn query_mixnode_delegation( } } -pub(crate) fn query_gateway_delegations_paged( - deps: Deps, - gateway_identity: IdentityKey, - start_after: Option, - limit: Option, -) -> StdResult { - let limit = limit - .unwrap_or(DELEGATION_PAGE_DEFAULT_LIMIT) - .min(DELEGATION_PAGE_MAX_LIMIT) as usize; - let start = calculate_start_value(start_after); - - let delegations = gateway_delegations_read(deps.storage, &gateway_identity) - .range(start.as_deref(), None, Order::Ascending) - .take(limit) - .map(|res| { - res.map(|entry| { - Delegation::new( - Addr::unchecked(String::from_utf8(entry.0).expect( - "Non-UTF8 address used as key in bucket. The storage is corrupted!", - )), - coin(entry.1.amount.u128(), DENOM), - entry.1.block_height, - ) - }) - }) - .collect::>>()?; - - let start_next_after = delegations.last().map(|delegation| delegation.owner()); - - Ok(PagedGatewayDelegationsResponse::new( - gateway_identity, - delegations, - start_next_after, - )) -} - -pub(crate) fn query_all_gateway_delegations_paged( - deps: Deps, - start_after: Option>, - limit: Option, -) -> StdResult> { - let limit = limit - .unwrap_or(DELEGATION_PAGE_DEFAULT_LIMIT) - .min(DELEGATION_PAGE_MAX_LIMIT) as usize; - - let bucket = all_gateway_delegations_read::(deps.storage); - let start = start_after.map(|mut v| { - v.push(0); - v - }); - get_all_delegations_paged::(&bucket, &start, limit) -} - -pub(crate) fn query_reverse_gateway_delegations_paged( - deps: Deps, - delegation_owner: Addr, - start_after: Option, - limit: Option, -) -> StdResult { - let limit = limit - .unwrap_or(DELEGATION_PAGE_DEFAULT_LIMIT) - .min(DELEGATION_PAGE_MAX_LIMIT) as usize; - let start = calculate_start_value(start_after); - - let delegations = reverse_gateway_delegations_read(deps.storage, &delegation_owner) - .range(start.as_deref(), None, Order::Ascending) - .take(limit) - .map(|res| { - res.map(|entry| { - String::from_utf8(entry.0) - .expect("Non-UTF8 address used as key in bucket. The storage is corrupted!") - }) - }) - .collect::>>()?; - - let start_next_after = delegations.last().cloned(); - - Ok(PagedReverseGatewayDelegationsResponse::new( - delegation_owner, - delegations, - start_next_after, - )) -} - -// queries for delegation value of given address for particular node -pub(crate) fn query_gateway_delegation( - deps: Deps, - gateway_identity: IdentityKey, - address: Addr, -) -> Result { - match gateway_delegations_read(deps.storage, &gateway_identity).may_load(address.as_bytes())? { - Some(delegation_value) => Ok(Delegation::new( - address, - coin(delegation_value.amount.u128(), DENOM), - delegation_value.block_height, - )), - None => Err(ContractError::NoGatewayDelegationFound { - identity: gateway_identity, - address, - }), - } -} - #[cfg(test)] pub(crate) mod tests { use super::*; use crate::state::State; - use crate::storage::{config, gateway_delegations, gateways, mix_delegations, mixnodes}; + use crate::storage::{config, gateways, mix_delegations, mixnodes}; use crate::support::tests::helpers; use crate::support::tests::helpers::{ good_gateway_bond, good_mixnode_bond, raw_delegation_fixture, @@ -673,16 +568,11 @@ pub(crate) mod tests { minimum_mixnode_bond: 123u128.into(), minimum_gateway_bond: 456u128.into(), mixnode_bond_reward_rate: "1.23".parse().unwrap(), - gateway_bond_reward_rate: "4.56".parse().unwrap(), mixnode_delegation_reward_rate: "7.89".parse().unwrap(), - gateway_delegation_reward_rate: "0.12".parse().unwrap(), mixnode_active_set_size: 1000, - gateway_active_set_size: 20, }, mixnode_epoch_bond_reward: "1.23".parse().unwrap(), - gateway_epoch_bond_reward: "4.56".parse().unwrap(), mixnode_epoch_delegation_reward: "7.89".parse().unwrap(), - gateway_epoch_delegation_reward: "0.12".parse().unwrap(), }; config(deps.as_mut().storage).save(&dummy_state).unwrap(); @@ -1203,524 +1093,4 @@ pub(crate) mod tests { assert_eq!(2, page2.delegated_nodes.len()); } } - - pub fn store_n_gateway_delegations( - n: u32, - storage: &mut dyn Storage, - node_identity: &IdentityKey, - ) { - for i in 0..n { - let address = format!("address{}", i); - gateway_delegations(storage, node_identity) - .save(address.as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - } - } - - #[cfg(test)] - mod querying_for_gateway_delegations_paged { - use super::*; - use crate::storage::gateway_delegations; - - #[test] - fn retrieval_obeys_limits() { - let mut deps = helpers::init_contract(); - let limit = 2; - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations(100, &mut deps.storage, &node_identity); - - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity, - None, - Option::from(limit), - ) - .unwrap(); - assert_eq!(limit, page1.delegations.len() as u32); - } - - #[test] - fn retrieval_has_default_limit() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - - // query without explicitly setting a limit - let page1 = - query_gateway_delegations_paged(deps.as_ref(), node_identity, None, None).unwrap(); - assert_eq!( - DELEGATION_PAGE_DEFAULT_LIMIT, - page1.delegations.len() as u32 - ); - } - - #[test] - fn retrieval_has_max_limit() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - - // query with a crazily high limit in an attempt to use too many resources - let crazy_limit = 1000 * DELEGATION_PAGE_DEFAULT_LIMIT; - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity, - None, - Option::from(crazy_limit), - ) - .unwrap(); - - // we default to a decent sized upper bound instead - let expected_limit = DELEGATION_PAGE_MAX_LIMIT; - assert_eq!(expected_limit, page1.delegations.len() as u32); - } - - #[test] - fn pagination_works() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - - gateway_delegations(&mut deps.storage, &node_identity) - .save("1".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - let per_page = 2; - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - - // page should have 1 result on it - assert_eq!(1, page1.delegations.len()); - - // save another - gateway_delegations(&mut deps.storage, &node_identity) - .save("2".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - // page1 should have 2 results on it - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - gateway_delegations(&mut deps.storage, &node_identity) - .save("3".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - // page1 still has 2 results - let page1 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity.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 = Addr::unchecked("2"); - let page2 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity.clone(), - Option::from(start_after), - Option::from(per_page), - ) - .unwrap(); - - assert_eq!(1, page2.delegations.len()); - - // save another one - gateway_delegations(&mut deps.storage, &node_identity) - .save("4".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - let start_after = Addr::unchecked("2"); - let page2 = query_gateway_delegations_paged( - deps.as_ref(), - node_identity, - Option::from(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()); - } - } - - #[test] - fn gateway_deletion_query_returns_current_delegation_value() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - let delegation_owner = Addr::unchecked("bar"); - - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegation_owner.as_bytes(), - &&RawDelegationData::new(42u128.into(), 12_345), - ) - .unwrap(); - - assert_eq!( - Ok(Delegation::new( - delegation_owner.clone(), - coin(42, DENOM), - 12_345 - )), - query_gateway_delegation(deps.as_ref(), node_identity, delegation_owner) - ) - } - - #[test] - fn gateway_deletion_query_returns_error_if_delegation_doesnt_exist() { - let mut deps = helpers::init_contract(); - - let node_identity1: IdentityKey = "foo1".into(); - let node_identity2: IdentityKey = "foo2".into(); - let delegation_owner1 = Addr::unchecked("bar"); - let delegation_owner2 = Addr::unchecked("bar2"); - - assert_eq!( - Err(ContractError::NoGatewayDelegationFound { - identity: node_identity1.clone(), - address: delegation_owner1.clone(), - }), - query_gateway_delegation( - deps.as_ref(), - node_identity1.clone(), - delegation_owner1.clone() - ) - ); - - // add delegation from a different address - gateway_delegations(&mut deps.storage, &node_identity1) - .save(delegation_owner2.as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - assert_eq!( - Err(ContractError::NoGatewayDelegationFound { - identity: node_identity1.clone(), - address: delegation_owner1.clone(), - }), - query_gateway_delegation( - deps.as_ref(), - node_identity1.clone(), - delegation_owner1.clone() - ) - ); - - // add delegation for a different node - gateway_delegations(&mut deps.storage, &node_identity2) - .save(delegation_owner1.as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - assert_eq!( - Err(ContractError::NoGatewayDelegationFound { - identity: node_identity1.clone(), - address: delegation_owner1.clone() - }), - query_gateway_delegation(deps.as_ref(), node_identity1, delegation_owner1) - ) - } - - #[cfg(test)] - mod querying_for_all_gateway_delegations_paged { - use super::*; - use crate::helpers::identity_and_owner_to_bytes; - use crate::storage::gateway_delegations; - - #[test] - fn retrieval_obeys_limits() { - let mut deps = helpers::init_contract(); - let limit = 2; - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations(100, &mut deps.storage, &node_identity); - - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(limit)) - .unwrap(); - assert_eq!(limit, page1.delegations.len() as u32); - } - - #[test] - fn retrieval_has_default_limit() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - - // query without explicitly setting a limit - let page1 = query_all_gateway_delegations_paged(deps.as_ref(), None, None).unwrap(); - assert_eq!( - DELEGATION_PAGE_DEFAULT_LIMIT, - page1.delegations.len() as u32 - ); - } - - #[test] - fn retrieval_has_max_limit() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - - // query with a crazily high limit in an attempt to use too many resources - let crazy_limit = 1000 * DELEGATION_PAGE_DEFAULT_LIMIT; - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(crazy_limit)) - .unwrap(); - - // we default to a decent sized upper bound instead - let expected_limit = DELEGATION_PAGE_MAX_LIMIT; - assert_eq!(expected_limit, page1.delegations.len() as u32); - } - - #[test] - fn pagination_works() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - - gateway_delegations(&mut deps.storage, &node_identity) - .save("1".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - let per_page = 2; - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(per_page)) - .unwrap(); - - // page should have 1 result on it - assert_eq!(1, page1.delegations.len()); - - // save another - gateway_delegations(&mut deps.storage, &node_identity) - .save("2".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - // page1 should have 2 results on it - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), None, Option::from(per_page)) - .unwrap(); - assert_eq!(2, page1.delegations.len()); - - gateway_delegations(&mut deps.storage, &node_identity) - .save("3".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - // page1 still has 2 results - let page1 = - query_all_gateway_delegations_paged(deps.as_ref(), 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 = identity_and_owner_to_bytes(&node_identity, &Addr::unchecked("2")); - let page2 = query_all_gateway_delegations_paged( - deps.as_ref(), - Option::from(start_after.clone()), - Option::from(per_page), - ) - .unwrap(); - - assert_eq!(1, page2.delegations.len()); - - // save another one - gateway_delegations(&mut deps.storage, &node_identity) - .save("4".as_bytes(), &raw_delegation_fixture(42)) - .unwrap(); - - let page2 = query_all_gateway_delegations_paged( - deps.as_ref(), - Option::from(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()); - } - } - - #[cfg(test)] - mod querying_for_reverse_gateway_delegations_paged { - use super::*; - use crate::storage::reverse_gateway_delegations; - - fn store_n_reverse_delegations(n: u32, storage: &mut dyn Storage, delegation_owner: &Addr) { - for i in 0..n { - let node_identity = format!("node{}", i); - reverse_gateway_delegations(storage, delegation_owner) - .save(node_identity.as_bytes(), &()) - .unwrap(); - } - } - - #[test] - fn retrieval_obeys_limits() { - let mut deps = helpers::init_contract(); - let limit = 2; - let delegation_owner = Addr::unchecked("foo"); - store_n_reverse_delegations(100, &mut deps.storage, &delegation_owner); - - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner, - None, - Option::from(limit), - ) - .unwrap(); - assert_eq!(limit, page1.delegated_nodes.len() as u32); - } - - #[test] - fn retrieval_has_default_limit() { - let mut deps = helpers::init_contract(); - let delegation_owner = Addr::unchecked("foo"); - store_n_reverse_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &delegation_owner, - ); - - // query without explicitly setting a limit - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner, - None, - None, - ) - .unwrap(); - assert_eq!( - DELEGATION_PAGE_DEFAULT_LIMIT, - page1.delegated_nodes.len() as u32 - ); - } - - #[test] - fn retrieval_has_max_limit() { - let mut deps = helpers::init_contract(); - let delegation_owner = Addr::unchecked("foo"); - store_n_reverse_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &delegation_owner, - ); - - // query with a crazy high limit in an attempt to use too many resources - let crazy_limit = 1000 * DELEGATION_PAGE_DEFAULT_LIMIT; - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner, - None, - Option::from(crazy_limit), - ) - .unwrap(); - - // we default to a decent sized upper bound instead - let expected_limit = DELEGATION_PAGE_MAX_LIMIT; - assert_eq!(expected_limit, page1.delegated_nodes.len() as u32); - } - - #[test] - fn pagination_works() { - let mut deps = helpers::init_contract(); - let delegation_owner = Addr::unchecked("bar"); - - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save("1".as_bytes(), &()) - .unwrap(); - - let per_page = 2; - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - - // page should have 1 result on it - assert_eq!(1, page1.delegated_nodes.len()); - - // save another - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save("2".as_bytes(), &()) - .unwrap(); - - // page1 should have 2 results on it - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegated_nodes.len()); - - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save("3".as_bytes(), &()) - .unwrap(); - - // page1 still has 2 results - let page1 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - None, - Option::from(per_page), - ) - .unwrap(); - assert_eq!(2, page1.delegated_nodes.len()); - - // retrieving the next page should start after the last key on this page - let start_after: IdentityKey = String::from("2"); - let page2 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner.clone(), - Option::from(start_after), - Option::from(per_page), - ) - .unwrap(); - - assert_eq!(1, page2.delegated_nodes.len()); - - // save another one - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save("4".as_bytes(), &()) - .unwrap(); - - let start_after = String::from("2"); - let page2 = query_reverse_gateway_delegations_paged( - deps.as_ref(), - delegation_owner, - Option::from(start_after), - Option::from(per_page), - ) - .unwrap(); - - // now we have 2 pages, with 2 results on the second page - assert_eq!(2, page2.delegated_nodes.len()); - } - } } diff --git a/contracts/mixnet/src/state.rs b/contracts/mixnet/src/state.rs index c537366f07..6371e6529f 100644 --- a/contracts/mixnet/src/state.rs +++ b/contracts/mixnet/src/state.rs @@ -14,7 +14,5 @@ pub struct State { // helper values to avoid having to recalculate them on every single payment operation pub mixnode_epoch_bond_reward: Decimal, // reward per epoch expressed as a decimal like 0.05 - pub gateway_epoch_bond_reward: Decimal, // reward per epoch expressed as a decimal like 0.05 pub mixnode_epoch_delegation_reward: Decimal, // reward per epoch expressed as a decimal like 0.05 - pub gateway_epoch_delegation_reward: Decimal, // reward per epoch expressed as a decimal like 0.05 } diff --git a/contracts/mixnet/src/storage.rs b/contracts/mixnet/src/storage.rs index 21cd2c41da..80aaddecf3 100644 --- a/contracts/mixnet/src/storage.rs +++ b/contracts/mixnet/src/storage.rs @@ -32,9 +32,7 @@ const PREFIX_GATEWAYS: &[u8] = b"gt"; const PREFIX_GATEWAYS_OWNERS: &[u8] = b"go"; const PREFIX_MIX_DELEGATION: &[u8] = b"md"; -const PREFIX_GATEWAY_DELEGATION: &[u8] = b"gd"; const PREFIX_REVERSE_MIX_DELEGATION: &[u8] = b"dm"; -const PREFIX_REVERSE_GATEWAY_DELEGATION: &[u8] = b"dg"; // Contract-level stuff @@ -63,14 +61,6 @@ pub(crate) fn read_mixnode_epoch_bond_reward_rate(storage: &dyn Storage) -> Deci .mixnode_epoch_bond_reward } -pub(crate) fn read_gateway_epoch_bond_reward_rate(storage: &dyn Storage) -> Decimal { - // same justification as in `read_state_params` for the unwrap - config_read(storage) - .load() - .unwrap() - .gateway_epoch_bond_reward -} - pub(crate) fn read_mixnode_epoch_delegation_reward_rate(storage: &dyn Storage) -> Decimal { // same justification as in `read_state_params` for the unwrap config_read(storage) @@ -79,14 +69,6 @@ pub(crate) fn read_mixnode_epoch_delegation_reward_rate(storage: &dyn Storage) - .mixnode_epoch_delegation_reward } -pub(crate) fn read_gateway_epoch_delegation_reward_rate(storage: &dyn Storage) -> Decimal { - // same justification as in `read_state_params` for the unwrap - config_read(storage) - .load() - .unwrap() - .gateway_epoch_delegation_reward -} - pub fn layer_distribution(storage: &mut dyn Storage) -> Singleton { singleton(storage, LAYER_DISTRIBUTION_KEY) } @@ -214,56 +196,6 @@ pub(crate) fn increase_mix_delegated_stakes( Ok(total_rewarded) } -pub(crate) fn increase_gateway_delegated_stakes( - storage: &mut dyn Storage, - gateway_identity: IdentityKeyRef, - scaled_reward_rate: Decimal, - reward_blockstamp: u64, -) -> StdResult { - let chunk_size = queries::DELEGATION_PAGE_MAX_LIMIT as usize; - - let mut total_rewarded = Uint128::zero(); - let mut chunk_start: Option> = None; - loop { - // get `chunk_size` of delegations - let delegations_chunk = gateway_delegations_read(storage, gateway_identity) - .range(chunk_start.as_deref(), None, Order::Ascending) - .take(chunk_size) - .collect::>>()?; - - if delegations_chunk.is_empty() { - break; - } - - // append 0 byte to the last value to start with whatever is the next suceeding key - chunk_start = Some( - delegations_chunk - .last() - .unwrap() - .0 - .iter() - .cloned() - .chain(std::iter::once(0u8)) - .collect(), - ); - - // and for each of them increase the stake proportionally to the reward - // if at least `MINIMUM_BLOCK_AGE_FOR_REWARDING` blocks have been created - // since they delegated - for (delegator_address, mut delegation) in delegations_chunk.into_iter() { - if delegation.block_height + MINIMUM_BLOCK_AGE_FOR_REWARDING <= reward_blockstamp { - let reward = delegation.amount * scaled_reward_rate; - delegation.amount += reward; - total_rewarded += reward; - gateway_delegations(storage, gateway_identity) - .save(&delegator_address, &delegation)?; - } - } - } - - Ok(total_rewarded) -} - // currently not used outside tests #[cfg(test)] pub(crate) fn read_mixnode_bond( @@ -338,53 +270,6 @@ pub fn reverse_mix_delegations_read<'a>( ReadonlyBucket::multilevel(storage, &[PREFIX_REVERSE_MIX_DELEGATION, owner.as_bytes()]) } -pub fn all_gateway_delegations_read(storage: &dyn Storage) -> ReadonlyBucket -where - T: Serialize + DeserializeOwned, -{ - bucket_read(storage, PREFIX_GATEWAY_DELEGATION) -} - -pub fn gateway_delegations<'a>( - storage: &'a mut dyn Storage, - gateway_identity: IdentityKeyRef, -) -> Bucket<'a, RawDelegationData> { - Bucket::multilevel( - storage, - &[PREFIX_GATEWAY_DELEGATION, gateway_identity.as_bytes()], - ) -} - -pub fn gateway_delegations_read<'a>( - storage: &'a dyn Storage, - gateway_identity: IdentityKeyRef, -) -> ReadonlyBucket<'a, RawDelegationData> { - ReadonlyBucket::multilevel( - storage, - &[PREFIX_GATEWAY_DELEGATION, gateway_identity.as_bytes()], - ) -} - -pub fn reverse_gateway_delegations<'a>( - storage: &'a mut dyn Storage, - owner: &Addr, -) -> Bucket<'a, ()> { - Bucket::multilevel( - storage, - &[PREFIX_REVERSE_GATEWAY_DELEGATION, owner.as_bytes()], - ) -} - -pub fn reverse_gateway_delegations_read<'a>( - storage: &'a dyn Storage, - owner: &Addr, -) -> ReadonlyBucket<'a, ()> { - ReadonlyBucket::multilevel( - storage, - &[PREFIX_REVERSE_GATEWAY_DELEGATION, owner.as_bytes()], - ) -} - // currently not used outside tests #[cfg(test)] pub(crate) fn read_gateway_bond( @@ -396,17 +281,6 @@ pub(crate) fn read_gateway_bond( Ok(node.bond_amount.amount) } -// currently not used outside tests -#[cfg(test)] -pub(crate) fn read_gateway_delegation( - storage: &dyn Storage, - identity: &[u8], -) -> StdResult { - let bucket = gateways_read(storage); - let node = bucket.load(identity)?; - Ok(node.total_delegation.amount) -} - #[cfg(test)] mod tests { use super::*; @@ -499,7 +373,6 @@ mod tests { let gateway_bond = GatewayBond { bond_amount: coin(bond_value, DENOM), - total_delegation: coin(0, DENOM), owner: node_owner.clone(), block_height: 12_345, gateway: Gateway { @@ -551,39 +424,6 @@ mod tests { assert_eq!(raw_delegation2, res2); } - #[test] - fn all_gateway_delegations_read_retrieval() { - let mut deps = mock_dependencies(&[]); - let node_identity1: IdentityKey = "foo1".into(); - let delegation_owner1 = Addr::unchecked("bar1"); - let node_identity2: IdentityKey = "foo2".into(); - let delegation_owner2 = Addr::unchecked("bar2"); - let raw_delegation1 = RawDelegationData::new(1u128.into(), 1000); - let raw_delegation2 = RawDelegationData::new(2u128.into(), 2000); - - gateway_delegations(&mut deps.storage, &node_identity1) - .save(delegation_owner1.as_bytes(), &raw_delegation1) - .unwrap(); - gateway_delegations(&mut deps.storage, &node_identity2) - .save(delegation_owner2.as_bytes(), &raw_delegation2) - .unwrap(); - - let res1 = all_gateway_delegations_read::(&deps.storage) - .load(&*identity_and_owner_to_bytes( - &node_identity1, - &delegation_owner1, - )) - .unwrap(); - let res2 = all_gateway_delegations_read::(&deps.storage) - .load(&*identity_and_owner_to_bytes( - &node_identity2, - &delegation_owner2, - )) - .unwrap(); - assert_eq!(raw_delegation1, res1); - assert_eq!(raw_delegation2, res2); - } - #[cfg(test)] mod increasing_mix_delegated_stakes { use super::*; @@ -858,279 +698,4 @@ mod tests { ); } } - - #[cfg(test)] - mod increasing_gateway_delegated_stakes { - use super::*; - use crate::queries::query_gateway_delegations_paged; - use cosmwasm_std::testing::mock_dependencies; - - #[test] - fn when_there_are_no_delegations() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - 42, - ) - .unwrap(); - - // there was no increase - assert!(total_increase.is_zero()); - - // there are no 'new' delegations magically added - assert!( - query_gateway_delegations_paged(deps.as_ref(), node_identity, None, None) - .unwrap() - .delegations - .is_empty() - ) - } - - #[test] - fn when_there_is_a_single_delegation() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - let delegation_blockstamp = 42; - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - let delegator_address = Addr::unchecked("bob"); - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegator_address.as_bytes(), - &RawDelegationData::new(1000u128.into(), delegation_blockstamp), - ) - .unwrap(); - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING, - ) - .unwrap(); - - assert_eq!(Uint128(1), total_increase); - - // amount is incremented, block height remains the same - assert_eq!( - RawDelegationData::new(1001u128.into(), 42), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ) - } - - #[test] - fn when_there_is_a_single_delegation_depending_on_blockstamp() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - let delegation_blockstamp = 42; - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - let delegator_address = Addr::unchecked("bob"); - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegator_address.as_bytes(), - &RawDelegationData::new(1000u128.into(), delegation_blockstamp), - ) - .unwrap(); - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + MINIMUM_BLOCK_AGE_FOR_REWARDING - 1, - ) - .unwrap(); - - // there was no increase - assert!(total_increase.is_zero()); - - // amount is not incremented - assert_eq!( - RawDelegationData::new(1000u128.into(), delegation_blockstamp), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ); - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + MINIMUM_BLOCK_AGE_FOR_REWARDING, - ) - .unwrap(); - - // there is an increase now, that the lock period has passed - assert_eq!(Uint128(1), total_increase); - - // amount is incremented - assert_eq!( - RawDelegationData::new(1001u128.into(), delegation_blockstamp), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ) - } - - #[test] - fn when_there_are_multiple_delegations() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - let delegation_blockstamp = 42; - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - for i in 0..100 { - let delegator_address = Addr::unchecked(format!("address{}", i)); - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegator_address.as_bytes(), - &RawDelegationData::new(1000u128.into(), delegation_blockstamp), - ) - .unwrap(); - } - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING, - ) - .unwrap(); - - assert_eq!(Uint128(100), total_increase); - - for i in 0..100 { - let delegator_address = Addr::unchecked(format!("address{}", i)); - assert_eq!( - raw_delegation_fixture(1001), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ) - } - } - - #[test] - fn when_there_are_more_delegations_than_page_size() { - let mut deps = mock_dependencies(&[]); - let node_identity: IdentityKey = "nodeidentity".into(); - let delegation_blockstamp = 42; - - // 0.001 - let reward = Decimal::from_ratio(1u128, 1000u128); - - for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 { - let delegator_address = Addr::unchecked(format!("address{}", i)); - gateway_delegations(&mut deps.storage, &node_identity) - .save( - delegator_address.as_bytes(), - &RawDelegationData::new(1000u128.into(), delegation_blockstamp), - ) - .unwrap(); - } - - let total_increase = increase_gateway_delegated_stakes( - &mut deps.storage, - node_identity.as_ref(), - reward, - delegation_blockstamp + 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING, - ) - .unwrap(); - - assert_eq!( - Uint128(queries::DELEGATION_PAGE_MAX_LIMIT as u128 * 10), - total_increase - ); - - for i in 0..queries::DELEGATION_PAGE_MAX_LIMIT * 10 { - let delegator_address = Addr::unchecked(format!("address{}", i)); - assert_eq!( - raw_delegation_fixture(1001), - gateway_delegations_read(&mut deps.storage, &node_identity) - .load(delegator_address.as_bytes()) - .unwrap() - ) - } - } - } - - #[cfg(test)] - mod reverse_gateway_delegations { - use super::*; - use crate::support::tests::helpers; - - #[test] - fn reverse_gateway_delegation_exists() { - let mut deps = helpers::init_contract(); - let node_identity: IdentityKey = "foo".into(); - let delegation_owner = Addr::unchecked("bar"); - - reverse_gateway_delegations(&mut deps.storage, &delegation_owner) - .save(node_identity.as_bytes(), &()) - .unwrap(); - - assert!( - reverse_gateway_delegations_read(deps.as_ref().storage, &delegation_owner) - .may_load(node_identity.as_bytes()) - .unwrap() - .is_some(), - ); - } - - #[test] - fn reverse_gateway_delegation_returns_none_if_delegation_doesnt_exist() { - let mut deps = helpers::init_contract(); - - let node_identity1: IdentityKey = "foo1".into(); - let node_identity2: IdentityKey = "foo2".into(); - let delegation_owner1 = Addr::unchecked("bar"); - let delegation_owner2 = Addr::unchecked("bar2"); - - assert!( - reverse_gateway_delegations_read(deps.as_ref().storage, &delegation_owner1) - .may_load(node_identity1.as_bytes()) - .unwrap() - .is_none() - ); - - // add delegation for a different node - reverse_gateway_delegations(&mut deps.storage, &delegation_owner1) - .save(node_identity2.as_bytes(), &()) - .unwrap(); - - assert!( - reverse_gateway_delegations_read(deps.as_ref().storage, &delegation_owner1) - .may_load(node_identity1.as_bytes()) - .unwrap() - .is_none() - ); - - // add delegation from a different owner - reverse_gateway_delegations(&mut deps.storage, &delegation_owner2) - .save(node_identity1.as_bytes(), &()) - .unwrap(); - - assert!( - reverse_gateway_delegations_read(deps.as_ref().storage, &delegation_owner1) - .may_load(node_identity1.as_bytes()) - .unwrap() - .is_none() - ); - } - } } diff --git a/contracts/mixnet/src/transactions.rs b/contracts/mixnet/src/transactions.rs index 7b2ec5c14c..8173243bbc 100644 --- a/contracts/mixnet/src/transactions.rs +++ b/contracts/mixnet/src/transactions.rs @@ -226,18 +226,13 @@ pub(crate) fn try_add_gateway( let minimum_bond = read_state_params(deps.storage).minimum_gateway_bond; validate_gateway_bond(&info.funds, minimum_bond)?; - let mut bond = GatewayBond::new( + let bond = GatewayBond::new( info.funds[0].clone(), info.sender.clone(), env.block.height, gateway, ); - // this might potentially require more gas if a significant number of delegations was there - let delegations_bucket = gateway_delegations_read(deps.storage, &bond.gateway.identity_key); - let existing_delegation = total_delegations(delegations_bucket)?; - bond.total_delegation = existing_delegation; - let identity = bond.identity(); gateways(deps.storage).save(identity.as_bytes(), &bond)?; gateways_owners(deps.storage).save(sender_bytes, identity)?; @@ -315,50 +310,28 @@ pub(crate) fn try_update_state_params( return Err(ContractError::DecreasingMixnodeBondReward); } - if params.gateway_bond_reward_rate < Decimal::one() { - return Err(ContractError::DecreasingGatewayBondReward); - } - if params.mixnode_delegation_reward_rate < Decimal::one() { return Err(ContractError::DecreasingMixnodeDelegationReward); } - if params.gateway_delegation_reward_rate < Decimal::one() { - return Err(ContractError::DecreasingGatewayDelegationReward); - } - - // if we're updating epoch length, recalculate rewards for both mixnodes and gateways + // if we're updating epoch length, recalculate rewards for mixnodes if state.params.epoch_length != params.epoch_length { state.mixnode_epoch_bond_reward = calculate_epoch_reward_rate(params.epoch_length, params.mixnode_bond_reward_rate); - state.gateway_epoch_bond_reward = - calculate_epoch_reward_rate(params.epoch_length, params.gateway_bond_reward_rate); state.mixnode_epoch_delegation_reward = calculate_epoch_reward_rate(params.epoch_length, params.mixnode_delegation_reward_rate); - state.gateway_epoch_delegation_reward = - calculate_epoch_reward_rate(params.epoch_length, params.gateway_delegation_reward_rate); } else { - // if mixnode or gateway rewards changed, recalculate respective values + // if mixnode rewards changed, recalculate respective values if state.params.mixnode_bond_reward_rate != params.mixnode_bond_reward_rate { state.mixnode_epoch_bond_reward = calculate_epoch_reward_rate(params.epoch_length, params.mixnode_bond_reward_rate); } - if state.params.gateway_bond_reward_rate != params.gateway_bond_reward_rate { - state.gateway_epoch_bond_reward = - calculate_epoch_reward_rate(params.epoch_length, params.gateway_bond_reward_rate); - } if state.params.mixnode_delegation_reward_rate != params.mixnode_delegation_reward_rate { state.mixnode_epoch_delegation_reward = calculate_epoch_reward_rate( params.epoch_length, params.mixnode_delegation_reward_rate, ); } - if state.params.gateway_delegation_reward_rate != params.gateway_delegation_reward_rate { - state.gateway_epoch_delegation_reward = calculate_epoch_reward_rate( - params.epoch_length, - params.gateway_delegation_reward_rate, - ); - } } state.params = params; @@ -443,81 +416,6 @@ pub(crate) fn try_reward_mixnode( }) } -// Note: if any changes are made to this function or anything it is calling down the stack, -// for example delegation reward distribution, the gas limits must be retested and both -// validator-api/src/rewarding/mod.rs::{GATEWAY_REWARD_OP_BASE_GAS_LIMIT, PER_GATEWAY_DELEGATION_GAS_INCREASE} -// must be updated appropriately. -pub(crate) fn try_reward_gateway( - deps: DepsMut, - env: Env, - info: MessageInfo, - gateway_identity: IdentityKey, - uptime: u32, -) -> Result { - let state = config_read(deps.storage).load().unwrap(); - - // check if this is executed by the owner, if not reject the transaction - if info.sender != state.network_monitor_address { - return Err(ContractError::Unauthorized); - } - - // optimisation for uptime being 0. No rewards will be given so just terminate here - if uptime == 0 { - return Ok(Response { - submessages: vec![], - messages: vec![], - attributes: vec![ - attr("bond increase", Uint128(0)), - attr("total delegation increase", Uint128(0)), - ], - data: None, - }); - } - - // check if the bond even exists - let mut current_bond = match gateways_read(deps.storage).load(gateway_identity.as_bytes()) { - Ok(bond) => bond, - Err(_) => { - return Ok(Response { - attributes: vec![attr("result", "bond not found")], - ..Default::default() - }); - } - }; - - let bond_reward_rate = read_gateway_epoch_bond_reward_rate(deps.storage); - let delegation_reward_rate = read_gateway_epoch_delegation_reward_rate(deps.storage); - let scaled_bond_reward_rate = scale_reward_by_uptime(bond_reward_rate, uptime)?; - let scaled_delegation_reward_rate = scale_reward_by_uptime(delegation_reward_rate, uptime)?; - - let mut node_reward = Uint128(0); - let total_delegation_reward = increase_gateway_delegated_stakes( - deps.storage, - &gateway_identity, - scaled_delegation_reward_rate, - env.block.height, - )?; - - // update current bond with the reward given to the node and the delegators - // if it has been bonded for long enough - if current_bond.block_height + MINIMUM_BLOCK_AGE_FOR_REWARDING <= env.block.height { - node_reward = current_bond.bond_amount.amount * scaled_bond_reward_rate; - current_bond.bond_amount.amount += node_reward; - current_bond.total_delegation.amount += total_delegation_reward; - gateways(deps.storage).save(gateway_identity.as_bytes(), ¤t_bond)?; - } - - Ok(Response { - submessages: vec![], - messages: vec![], - attributes: vec![ - attr("bond increase", node_reward), - attr("total delegation increase", total_delegation_reward), - ], - data: None, - }) -} - fn validate_delegation_stake(delegation: &[Coin]) -> Result<(), ContractError> { // check if anything was put as delegation if delegation.is_empty() { @@ -630,119 +528,19 @@ pub(crate) fn try_remove_delegation_from_mixnode( } } -pub(crate) fn try_delegate_to_gateway( - deps: DepsMut, - env: Env, - info: MessageInfo, - gateway_identity: IdentityKey, -) -> Result { - // check if the delegation contains any funds of the appropriate denomination - validate_delegation_stake(&info.funds)?; - - // check if the target node actually exists - let mut gateways_bucket = gateways(deps.storage); - let mut current_bond = match gateways_bucket.load(gateway_identity.as_bytes()) { - Ok(bond) => bond, - Err(_) => { - return Err(ContractError::GatewayBondNotFound { - identity: gateway_identity, - }); - } - }; - - // update total_delegation of this node - current_bond.total_delegation.amount += info.funds[0].amount; - gateways_bucket.save(gateway_identity.as_bytes(), ¤t_bond)?; - - let mut delegation_bucket = gateway_delegations(deps.storage, &gateway_identity); - let sender_bytes = info.sender.as_bytes(); - - // write the delegation - let new_amount = match delegation_bucket.may_load(sender_bytes)? { - Some(existing_delegation) => existing_delegation.amount + info.funds[0].amount, - None => info.funds[0].amount, - }; - // the block height is reset, if it existed - let new_delegation = RawDelegationData::new(new_amount, env.block.height); - delegation_bucket.save(sender_bytes, &new_delegation)?; - - reverse_gateway_delegations(deps.storage, &info.sender) - .save(gateway_identity.as_bytes(), &())?; - - Ok(Response::default()) -} - -pub(crate) fn try_remove_delegation_from_gateway( - deps: DepsMut, - info: MessageInfo, - gateway_identity: IdentityKey, -) -> Result { - let mut delegation_bucket = gateway_delegations(deps.storage, &gateway_identity); - let sender_bytes = info.sender.as_bytes(); - match delegation_bucket.may_load(sender_bytes)? { - Some(delegation) => { - // remove delegation from the buckets - delegation_bucket.remove(sender_bytes); - reverse_gateway_delegations(deps.storage, &info.sender) - .remove(gateway_identity.as_bytes()); - - // send delegated funds back to the delegation owner - let messages = vec![BankMsg::Send { - to_address: info.sender.to_string(), - amount: coins(delegation.amount.u128(), DENOM), - } - .into()]; - - // update total_delegation of this node - let mut gateways_bucket = gateways(deps.storage); - // in some rare cases the gateway bond might no longer exist as the node unbonded - // before delegation was removed. that is fine - if let Some(mut existing_bond) = - gateways_bucket.may_load(gateway_identity.as_bytes())? - { - // we should NEVER underflow here, if we do, it means we have some serious error in our logic - existing_bond.total_delegation.amount = existing_bond - .total_delegation - .amount - .checked_sub(delegation.amount) - .unwrap(); - gateways_bucket.save(gateway_identity.as_bytes(), &existing_bond)?; - } - - Ok(Response { - submessages: Vec::new(), - messages, - attributes: Vec::new(), - data: None, - }) - } - None => Err(ContractError::NoGatewayDelegationFound { - identity: gateway_identity, - address: info.sender, - }), - } -} - #[cfg(test)] pub mod tests { use super::*; use crate::contract::{ - execute, query, INITIAL_DEFAULT_EPOCH_LENGTH, INITIAL_GATEWAY_BOND, - INITIAL_GATEWAY_BOND_REWARD_RATE, INITIAL_GATEWAY_DELEGATION_REWARD_RATE, - INITIAL_MIXNODE_BOND, INITIAL_MIXNODE_BOND_REWARD_RATE, - INITIAL_MIXNODE_DELEGATION_REWARD_RATE, + execute, query, INITIAL_DEFAULT_EPOCH_LENGTH, INITIAL_GATEWAY_BOND, INITIAL_MIXNODE_BOND, + INITIAL_MIXNODE_BOND_REWARD_RATE, INITIAL_MIXNODE_DELEGATION_REWARD_RATE, }; use crate::helpers::calculate_epoch_reward_rate; use crate::queries::DELEGATION_PAGE_DEFAULT_LIMIT; - use crate::storage::{ - gateway_delegations, gateway_delegations_read, layer_distribution_read, - mix_delegations_read, read_gateway_bond, read_gateway_epoch_bond_reward_rate, - read_mixnode_bond, - }; + use crate::storage::{layer_distribution_read, mix_delegations_read, read_mixnode_bond}; use crate::support::tests::helpers; use crate::support::tests::helpers::{ - add_gateway, add_mixnode, gateway_fixture, good_gateway_bond, good_mixnode_bond, - mix_node_fixture, raw_delegation_fixture, + add_mixnode, good_gateway_bond, good_mixnode_bond, mix_node_fixture, raw_delegation_fixture, }; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coin, coins, from_binary, Addr, Uint128}; @@ -750,7 +548,7 @@ pub mod tests { ExecuteMsg, LayerDistribution, PagedGatewayResponse, PagedMixnodeResponse, QueryMsg, UnpackedDelegation, }; - use queries::tests::{store_n_gateway_delegations, store_n_mix_delegations}; + use queries::tests::store_n_mix_delegations; #[test] fn validating_mixnode_bond() { @@ -1596,15 +1394,10 @@ pub mod tests { minimum_mixnode_bond: INITIAL_MIXNODE_BOND, minimum_gateway_bond: INITIAL_GATEWAY_BOND, mixnode_bond_reward_rate: Decimal::percent(INITIAL_MIXNODE_BOND_REWARD_RATE), - gateway_bond_reward_rate: Decimal::percent(INITIAL_GATEWAY_BOND_REWARD_RATE), mixnode_delegation_reward_rate: Decimal::percent( INITIAL_MIXNODE_DELEGATION_REWARD_RATE, ), - gateway_delegation_reward_rate: Decimal::percent( - INITIAL_GATEWAY_DELEGATION_REWARD_RATE, - ), mixnode_active_set_size: 42, // change something - gateway_active_set_size: 5, }; // cannot be updated from non-owner account @@ -1656,93 +1449,7 @@ pub mod tests { new_state.mixnode_epoch_delegation_reward ); - // gateway_epoch_rewards are recalculated if annual reward rate is changed - let current_gateway_bond_reward_rate = - read_gateway_epoch_bond_reward_rate(deps.as_ref().storage); - let current_gateway_delegation_reward_rate = - read_gateway_epoch_delegation_reward_rate(deps.as_ref().storage); - let new_gateway_bond_reward_rate = Decimal::percent(120); - let new_gateway_delegation_reward_rate = Decimal::percent(120); - - // sanity check to make sure we are actually updating the values (in case we changed defaults at some point) - assert_ne!( - new_gateway_bond_reward_rate, - current_gateway_bond_reward_rate - ); - assert_ne!( - new_gateway_delegation_reward_rate, - current_gateway_delegation_reward_rate - ); - - let mut new_params = current_state.params.clone(); - new_params.gateway_bond_reward_rate = new_gateway_bond_reward_rate; - new_params.gateway_delegation_reward_rate = new_gateway_delegation_reward_rate; - - let info = mock_info("creator", &[]); - try_update_state_params(deps.as_mut(), info, new_params.clone()).unwrap(); - - let new_state = config_read(deps.as_ref().storage).load().unwrap(); - let expected_bond = - calculate_epoch_reward_rate(new_params.epoch_length, new_gateway_bond_reward_rate); - let expected_delegation = calculate_epoch_reward_rate( - new_params.epoch_length, - new_gateway_delegation_reward_rate, - ); - assert_eq!(expected_bond, new_state.gateway_epoch_bond_reward); - assert_eq!( - expected_delegation, - new_state.gateway_epoch_delegation_reward - ); - - // if annual reward rate is changed for both mixnodes and gateways in a single update operation, - // both mixnode_epoch_rewards and gateway_epoch_rewards are recalculated - let current_state = config_read(deps.as_ref().storage).load().unwrap(); - let new_mixnode_bond_reward_rate = Decimal::percent(130); - let new_gateway_bond_reward_rate = Decimal::percent(130); - assert_ne!( - new_mixnode_bond_reward_rate, - current_state.params.mixnode_bond_reward_rate - ); - assert_ne!( - new_gateway_bond_reward_rate, - current_state.params.gateway_bond_reward_rate - ); - - let mut new_params = current_state.params.clone(); - new_params.mixnode_bond_reward_rate = new_mixnode_bond_reward_rate; - new_params.mixnode_delegation_reward_rate = new_mixnode_delegation_reward_rate; - new_params.gateway_bond_reward_rate = new_gateway_bond_reward_rate; - new_params.gateway_delegation_reward_rate = new_gateway_delegation_reward_rate; - - let info = mock_info("creator", &[]); - try_update_state_params(deps.as_mut(), info, new_params.clone()).unwrap(); - - let new_state = config_read(deps.as_ref().storage).load().unwrap(); - let expected_mixnode_bond = - calculate_epoch_reward_rate(new_params.epoch_length, new_mixnode_bond_reward_rate); - let expected_mixnode_delegation = calculate_epoch_reward_rate( - new_params.epoch_length, - new_mixnode_delegation_reward_rate, - ); - assert_eq!(expected_mixnode_bond, new_state.mixnode_epoch_bond_reward); - assert_eq!( - expected_mixnode_delegation, - new_state.mixnode_epoch_delegation_reward - ); - - let expected_gateway_bond = - calculate_epoch_reward_rate(new_params.epoch_length, new_gateway_bond_reward_rate); - let expected_gateway_delegation = calculate_epoch_reward_rate( - new_params.epoch_length, - new_gateway_delegation_reward_rate, - ); - assert_eq!(expected_gateway_bond, new_state.gateway_epoch_bond_reward); - assert_eq!( - expected_gateway_delegation, - new_state.gateway_epoch_delegation_reward - ); - - // both mixnode_epoch_rewards and gateway_epoch_rewards are updated on epoch length change + // mixnode_epoch_rewards is updated on epoch length change let new_epoch_length = 42; // sanity check to make sure we are actually updating the value (in case we changed defaults at some point) assert_ne!(new_epoch_length, current_state.params.epoch_length); @@ -1764,18 +1471,6 @@ pub mod tests { expected_mixnode_delegation, new_state.mixnode_epoch_delegation_reward ); - - let expected_gateway_bond = - calculate_epoch_reward_rate(new_epoch_length, new_params.gateway_bond_reward_rate); - let expected_gateway_delegation = calculate_epoch_reward_rate( - new_epoch_length, - new_params.gateway_delegation_reward_rate, - ); - assert_eq!(expected_gateway_bond, new_state.gateway_epoch_bond_reward); - assert_eq!( - expected_gateway_delegation, - new_state.gateway_epoch_delegation_reward - ); } #[test] @@ -2016,241 +1711,6 @@ pub mod tests { ); } - #[test] - fn rewarding_gateway() { - let mut deps = helpers::init_contract(); - let mut env = mock_env(); - let current_state = config(deps.as_mut().storage).load().unwrap(); - let network_monitor_address = current_state.network_monitor_address; - - let node_owner: Addr = Addr::unchecked("node-owner"); - let node_identity: IdentityKey = "nodeidentity".into(); - - // errors out if executed by somebody else than network monitor - let info = mock_info("not-the-monitor", &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100); - assert_eq!(res, Err(ContractError::Unauthorized)); - - // returns bond not found attribute if the target owner hasn't bonded any gateways - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - assert_eq!(vec![attr("result", "bond not found")], res.attributes); - - let initial_bond = 100_000000; - let initial_delegation = 200_000000; - let gateway_bond = GatewayBond { - bond_amount: coin(initial_bond, DENOM), - total_delegation: coin(initial_delegation, DENOM), - owner: node_owner.clone(), - block_height: env.block.height, - gateway: Gateway { - identity_key: node_identity.clone(), - ..gateway_fixture() - }, - }; - - gateways(deps.as_mut().storage) - .save(node_identity.as_bytes(), &gateway_bond) - .unwrap(); - - gateway_delegations(&mut deps.storage, &node_identity) - .save(b"delegator", &raw_delegation_fixture(initial_delegation)) - .unwrap(); - - env.block.height += 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING; - - let bond_reward_rate = read_gateway_epoch_bond_reward_rate(deps.as_ref().storage); - let delegation_reward_rate = - read_gateway_epoch_delegation_reward_rate(deps.as_ref().storage); - let expected_bond_reward = Uint128(initial_bond) * bond_reward_rate; - let expected_delegation_reward = Uint128(initial_delegation) * delegation_reward_rate; - - // the node's bond and delegations are correctly increased and scaled by uptime - // if node was 100% up, it will get full epoch reward - let expected_bond = expected_bond_reward + Uint128(initial_bond); - let expected_delegation = expected_delegation_reward + Uint128(initial_delegation); - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - - // if node was 20% up, it will get 1/5th of epoch reward - let scaled_bond_reward = scale_reward_by_uptime(bond_reward_rate, 20).unwrap(); - let scaled_delegation_reward = scale_reward_by_uptime(delegation_reward_rate, 20).unwrap(); - let expected_bond_reward = expected_bond * scaled_bond_reward; - let expected_delegation_reward = expected_delegation * scaled_delegation_reward; - let expected_bond = expected_bond_reward + expected_bond; - let expected_delegation = expected_delegation_reward + expected_delegation; - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 20) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - } - - #[test] - fn rewarding_gateway_blockstamp_based() { - let mut deps = helpers::init_contract(); - let mut env = mock_env(); - let current_state = config(deps.as_mut().storage).load().unwrap(); - let network_monitor_address = current_state.network_monitor_address; - - let node_owner: Addr = Addr::unchecked("node-owner"); - let node_identity: IdentityKey = "nodeidentity".into(); - - let initial_bond = 100_000000; - let initial_delegation = 200_000000; - let gateway_bond = GatewayBond { - bond_amount: coin(initial_bond, DENOM), - total_delegation: coin(initial_delegation, DENOM), - owner: node_owner.clone(), - block_height: env.block.height, - gateway: Gateway { - identity_key: node_identity.clone(), - ..gateway_fixture() - }, - }; - - gateways(deps.as_mut().storage) - .save(node_identity.as_bytes(), &gateway_bond) - .unwrap(); - - // delegation happens later, but not later enough - env.block.height += MINIMUM_BLOCK_AGE_FOR_REWARDING - 1; - - gateway_delegations(&mut deps.storage, &node_identity) - .save( - b"delegator", - &RawDelegationData::new(initial_delegation.into(), env.block.height), - ) - .unwrap(); - - let bond_reward_rate = read_gateway_epoch_bond_reward_rate(deps.as_ref().storage); - let delegation_reward_rate = - read_gateway_epoch_delegation_reward_rate(deps.as_ref().storage); - let scaled_bond_reward = scale_reward_by_uptime(bond_reward_rate, 100).unwrap(); - let scaled_delegation_reward = scale_reward_by_uptime(delegation_reward_rate, 100).unwrap(); - - // no reward is due - let expected_bond_reward = Uint128(0); - let expected_delegation_reward = Uint128(0); - let expected_bond = expected_bond_reward + Uint128(initial_bond); - let expected_delegation = expected_delegation_reward + Uint128(initial_delegation); - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - - // reward can happen now, but only for bonded node - env.block.height += 1; - let expected_bond_reward = expected_bond * scaled_bond_reward; - let expected_delegation_reward = Uint128(0); - let expected_bond = expected_bond_reward + expected_bond; - let expected_delegation = expected_delegation_reward + expected_delegation; - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - - // reward happens now, both for node owner and delegators - env.block.height += MINIMUM_BLOCK_AGE_FOR_REWARDING - 1; - let expected_bond_reward = expected_bond * scaled_bond_reward; - let expected_delegation_reward = expected_delegation * scaled_delegation_reward; - let expected_bond = expected_bond_reward + expected_bond; - let expected_delegation = expected_delegation_reward + expected_delegation; - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = try_reward_gateway(deps.as_mut(), env.clone(), info, node_identity.clone(), 100) - .unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - assert_eq!( - expected_delegation, - read_gateway_delegation(deps.as_ref().storage, node_identity.as_bytes()).unwrap() - ); - - assert_eq!( - vec![ - attr("bond increase", expected_bond_reward), - attr("total delegation increase", expected_delegation_reward), - ], - res.attributes - ); - } - #[cfg(test)] mod delegation_stake_validation { use super::*; @@ -3100,800 +2560,6 @@ pub mod tests { ); } - #[cfg(test)] - mod gateway_stake_delegation { - use super::*; - use crate::storage::gateway_delegations_read; - use crate::support::tests::helpers::add_gateway; - - #[test] - fn fails_if_node_doesnt_exist() { - let mut deps = helpers::init_contract(); - assert_eq!( - Err(ContractError::GatewayBondNotFound { - identity: "non-existent-gateway-identity".into() - }), - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info("sender", &coins(123, DENOM)), - "non-existent-gateway-identity".into() - ) - ); - } - - #[test] - fn succeeds_for_existing_node() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - let delegation = coin(123, DENOM); - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation.clone()]), - identity.clone() - ) - .is_ok()); - - assert_eq!( - RawDelegationData::new(delegation.amount, mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity.as_bytes()) - .is_ok() - ); - - // node's "total_delegation" is increased - assert_eq!( - delegation, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - ) - } - - #[test] - fn fails_if_node_unbonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - - assert_eq!( - Err(ContractError::GatewayBondNotFound { - identity: identity.clone() - }), - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(123, DENOM)), - identity - ) - ); - } - - #[test] - fn succeeds_if_node_rebonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation = coin(123, DENOM); - let delegation_owner = Addr::unchecked("sender"); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation.clone()]), - identity.clone() - ) - .is_ok()); - - assert_eq!( - RawDelegationData::new(delegation.amount, mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity.as_bytes()) - .is_ok() - ); - - // node's "total_delegation" is increased - assert_eq!( - delegation, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - ) - } - - #[test] - fn is_possible_for_an_already_delegated_node() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - let delegation1 = coin(100, DENOM); - let delegation2 = coin(50, DENOM); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation1.clone()]), - identity.clone(), - ) - .unwrap(); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation2.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new( - delegation1.amount + delegation2.amount, - mock_env().block.height - ), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity.as_bytes()) - .is_ok() - ); - - // node's "total_delegation" is sum of both - assert_eq!( - delegation1.amount + delegation2.amount, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - .amount - ) - } - - #[test] - fn block_height_is_updated_on_new_delegation() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - let delegation = coin(100, DENOM); - - let env1 = mock_env(); - let mut env2 = mock_env(); - let initial_height = env1.block.height; - let updated_height = initial_height + 42; - // second env has grown in block height - env2.block.height = updated_height; - - try_delegate_to_gateway( - deps.as_mut(), - env1, - mock_info(delegation_owner.as_str(), &vec![delegation.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new(delegation.amount, initial_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - - try_delegate_to_gateway( - deps.as_mut(), - env2, - mock_info(delegation_owner.as_str(), &vec![delegation.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new(delegation.amount + delegation.amount, updated_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - } - - #[test] - fn block_height_is_not_updated_on_different_delegator() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner1 = Addr::unchecked("sender1"); - let delegation_owner2 = Addr::unchecked("sender2"); - let delegation1 = coin(100, DENOM); - let delegation2 = coin(120, DENOM); - - let env1 = mock_env(); - let mut env2 = mock_env(); - let initial_height = env1.block.height; - let second_height = initial_height + 42; - // second env has grown in block height - env2.block.height = second_height; - - try_delegate_to_gateway( - deps.as_mut(), - env1, - mock_info(delegation_owner1.as_str(), &vec![delegation1.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new(delegation1.amount, initial_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner1.as_bytes()) - .unwrap() - ); - - try_delegate_to_gateway( - deps.as_mut(), - env2, - mock_info(delegation_owner2.as_str(), &vec![delegation2.clone()]), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - RawDelegationData::new(delegation1.amount, initial_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner1.as_bytes()) - .unwrap() - ); - assert_eq!( - RawDelegationData::new(delegation2.amount, second_height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner2.as_bytes()) - .unwrap() - ); - } - - #[test] - fn is_disallowed_for_already_delegated_node_if_it_unbonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(100, DENOM)), - identity.clone(), - ) - .unwrap(); - - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - - assert_eq!( - Err(ContractError::GatewayBondNotFound { - identity: identity.clone() - }), - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(50, DENOM)), - identity.clone() - ) - ); - } - - #[test] - fn is_allowed_for_multiple_nodes() { - let mut deps = helpers::init_contract(); - let gateway_owner1 = "bob"; - let gateway_owner2 = "fred"; - let identity1 = add_gateway(gateway_owner1, good_gateway_bond(), &mut deps); - let identity2 = add_gateway(gateway_owner2, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(123, DENOM)), - identity1.clone() - ) - .is_ok()); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(42, DENOM)), - identity2.clone() - ) - .is_ok()); - - assert_eq!( - RawDelegationData::new(123u128.into(), mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity1) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity1.as_bytes()) - .is_ok() - ); - - assert_eq!( - RawDelegationData::new(42u128.into(), mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity2) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity2.as_bytes()) - .is_ok() - ); - } - - #[test] - fn is_allowed_by_multiple_users() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - - let delegation1 = coin(123, DENOM); - let delegation2 = coin(234, DENOM); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info("sender1", &vec![delegation1.clone()]), - identity.clone() - ) - .is_ok()); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info("sender2", &vec![delegation2.clone()]), - identity.clone() - ) - .is_ok()); - - // node's "total_delegation" is sum of both - assert_eq!( - delegation1.amount + delegation2.amount, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - .amount - ) - } - - #[test] - fn delegation_is_not_removed_if_node_unbonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(100, DENOM)), - identity.clone(), - ) - .unwrap(); - - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - - assert_eq!( - RawDelegationData::new(100u128.into(), mock_env().block.height), - gateway_delegations_read(&deps.storage, &identity) - .load(delegation_owner.as_bytes()) - .unwrap() - ); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .load(identity.as_bytes()) - .is_ok() - ); - } - } - - #[cfg(test)] - mod removing_gateway_stake_delegation { - use super::*; - use crate::storage::gateway_delegations_read; - use crate::support::tests::helpers::add_gateway; - - #[test] - fn fails_if_delegation_never_existed() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - assert_eq!( - Err(ContractError::NoGatewayDelegationFound { - identity: identity.clone(), - address: delegation_owner.clone(), - }), - try_remove_delegation_from_gateway( - deps.as_mut(), - mock_info(delegation_owner.as_str(), &[]), - identity, - ) - ); - } - - #[test] - fn succeeds_if_delegation_existed() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(100, DENOM)), - identity.clone(), - ) - .unwrap(); - - assert_eq!( - Ok(Response { - submessages: vec![], - messages: vec![BankMsg::Send { - to_address: delegation_owner.clone().into(), - amount: coins(100, DENOM), - } - .into()], - attributes: Vec::new(), - data: None, - }), - try_remove_delegation_from_gateway( - deps.as_mut(), - mock_info(delegation_owner.as_str(), &[]), - identity.clone(), - ) - ); - - assert!(gateway_delegations_read(&deps.storage, &identity) - .may_load(delegation_owner.as_bytes()) - .unwrap() - .is_none()); - assert!( - reverse_mix_delegations_read(&deps.storage, &delegation_owner) - .may_load(identity.as_bytes()) - .unwrap() - .is_none() - ); - - // and total delegation is cleared - assert_eq!( - Uint128::zero(), - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - .amount - ) - } - - #[test] - fn succeeds_if_delegation_existed_even_if_node_unbonded() { - let mut deps = helpers::init_contract(); - - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner = Addr::unchecked("sender"); - - try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner.as_str(), &coins(100, DENOM)), - identity.clone(), - ) - .unwrap(); - - try_remove_gateway(deps.as_mut(), mock_info(gateway_owner, &[])).unwrap(); - - assert_eq!( - Ok(Response { - submessages: vec![], - messages: vec![BankMsg::Send { - to_address: delegation_owner.clone().into(), - amount: coins(100, DENOM), - } - .into()], - attributes: Vec::new(), - data: None, - }), - try_remove_delegation_from_gateway( - deps.as_mut(), - mock_info(delegation_owner.as_str(), &[]), - identity.clone(), - ) - ); - - assert!(gateway_delegations_read(&deps.storage, &identity) - .may_load(delegation_owner.as_bytes()) - .unwrap() - .is_none()); - assert!( - reverse_gateway_delegations_read(&deps.storage, &delegation_owner) - .may_load(identity.as_bytes()) - .unwrap() - .is_none() - ); - } - - #[test] - fn total_delegation_is_preserved_if_only_some_undelegate() { - let mut deps = helpers::init_contract(); - let gateway_owner = "bob"; - let identity = add_gateway(gateway_owner, good_gateway_bond(), &mut deps); - let delegation_owner1 = Addr::unchecked("sender1"); - let delegation_owner2 = Addr::unchecked("sender2"); - - let delegation1 = coin(123, DENOM); - let delegation2 = coin(234, DENOM); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner1.as_str(), &vec![delegation1.clone()]), - identity.clone() - ) - .is_ok()); - - assert!(try_delegate_to_gateway( - deps.as_mut(), - mock_env(), - mock_info(delegation_owner2.as_str(), &vec![delegation2.clone()]), - identity.clone() - ) - .is_ok()); - - // sender1 undelegates - try_remove_delegation_from_gateway( - deps.as_mut(), - mock_info(delegation_owner1.as_str(), &[]), - identity.clone(), - ) - .unwrap(); - - // but total delegation should still equal to what sender2 sent - // node's "total_delegation" is sum of both - assert_eq!( - delegation2, - gateways_read(&deps.storage) - .load(identity.as_bytes()) - .unwrap() - .total_delegation - ) - } - } - - #[test] - fn delegators_on_gateway_reward_rate() { - let mut deps = helpers::init_contract(); - let mut env = mock_env(); - let current_state = config(deps.as_mut().storage).load().unwrap(); - let network_monitor_address = current_state.network_monitor_address; - - let initial_gateway_bond = 100_000000; - let initial_delegation1 = 50000; // will see single digits rewards - let initial_delegation2 = 100; // won't see any rewards due to such a small delegation - let initial_delegation3 = 100000_000000; // will see big proper rewards - - let node_owner = "node-owner"; - let identity = add_gateway(node_owner, good_gateway_bond(), &mut deps); - - gateway_delegations(&mut deps.storage, &identity) - .save(b"delegator1", &raw_delegation_fixture(initial_delegation1)) - .unwrap(); - gateway_delegations(&mut deps.storage, &identity) - .save(b"delegator2", &raw_delegation_fixture(initial_delegation2)) - .unwrap(); - gateway_delegations(&mut deps.storage, &identity) - .save(b"delegator3", &raw_delegation_fixture(initial_delegation3)) - .unwrap(); - - env.block.height += 2 * MINIMUM_BLOCK_AGE_FOR_REWARDING; - - let bond_reward = read_gateway_epoch_bond_reward_rate(deps.as_ref().storage); - let delegation_reward = read_gateway_epoch_delegation_reward_rate(deps.as_ref().storage); - - // the node's bond and delegations are correctly increased and scaled by uptime - // if node was 100% up, it will get full epoch reward - let expected_gateway_reward = Uint128(initial_gateway_bond) * bond_reward; - let expected_delegation1_reward = Uint128(initial_delegation1) * delegation_reward; - let expected_delegation2_reward = Uint128(initial_delegation2) * delegation_reward; - let expected_delegation3_reward = Uint128(initial_delegation3) * delegation_reward; - - let expected_bond = expected_gateway_reward + Uint128(initial_gateway_bond); - let expected_delegation1 = expected_delegation1_reward + Uint128(initial_delegation1); - let expected_delegation2 = expected_delegation2_reward + Uint128(initial_delegation2); - let expected_delegation3 = expected_delegation3_reward + Uint128(initial_delegation3); - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = - try_reward_gateway(deps.as_mut(), env.clone(), info, identity.clone(), 100).unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation1, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator1".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation2, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator2".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation3, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator3".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - vec![ - attr("bond increase", expected_gateway_reward), - attr( - "total delegation increase", - expected_delegation1_reward - + expected_delegation2_reward - + expected_delegation3_reward - ), - ], - res.attributes - ); - - // if node was 20% up, it will get 1/5th of epoch reward - let scaled_bond_reward = scale_reward_by_uptime(bond_reward, 20).unwrap(); - let scaled_delegation_reward = scale_reward_by_uptime(delegation_reward, 20).unwrap(); - - let expected_gateway_reward = expected_bond * scaled_bond_reward; - let expected_delegation1_reward = expected_delegation1 * scaled_delegation_reward; - let expected_delegation2_reward = expected_delegation2 * scaled_delegation_reward; - let expected_delegation3_reward = expected_delegation3 * scaled_delegation_reward; - - let expected_bond = expected_gateway_reward + expected_bond; - let expected_delegation1 = expected_delegation1_reward + expected_delegation1; - let expected_delegation2 = expected_delegation2_reward + expected_delegation2; - let expected_delegation3 = expected_delegation3_reward + expected_delegation3; - - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = - try_reward_gateway(deps.as_mut(), env.clone(), info, identity.clone(), 20).unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation1, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator1".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation2, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator2".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation3, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator3".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - vec![ - attr("bond increase", expected_gateway_reward), - attr( - "total delegation increase", - expected_delegation1_reward - + expected_delegation2_reward - + expected_delegation3_reward - ), - ], - res.attributes - ); - - // if the node was 0% up, nobody will get any rewards - let info = mock_info(network_monitor_address.as_ref(), &[]); - let res = - try_reward_gateway(deps.as_mut(), env.clone(), info, identity.clone(), 0).unwrap(); - - assert_eq!( - expected_bond, - read_gateway_bond(deps.as_ref().storage, identity.as_bytes()).unwrap() - ); - - assert_eq!( - expected_delegation1, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator1".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation2, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator2".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - expected_delegation3, - gateway_delegations_read(deps.as_ref().storage, &identity) - .load("delegator3".as_bytes()) - .unwrap() - .amount - ); - - assert_eq!( - vec![ - attr("bond increase", Uint128(0)), - attr("total delegation increase", Uint128(0)), - ], - res.attributes - ); - } - #[test] fn multiple_page_delegations() { let mut deps = helpers::init_contract(); @@ -3911,19 +2577,6 @@ pub mod tests { DELEGATION_PAGE_DEFAULT_LIMIT * 10, mix_delegations.len() as u32 ); - - store_n_gateway_delegations( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - &mut deps.storage, - &node_identity, - ); - let gateway_bucket = all_gateway_delegations_read::(&deps.storage); - let gateway_delegations = Delegations::new(gateway_bucket) - .collect::>>(); - assert_eq!( - DELEGATION_PAGE_DEFAULT_LIMIT * 10, - gateway_delegations.len() as u32 - ); } #[cfg(test)] diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 384b28b720..272ee47925 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -6,6 +6,7 @@ name = "nym-gateway" version = "0.11.0" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] edition = "2018" +rust-version = "1.56" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 968df4a9e1..9100df26ef 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -10,6 +10,7 @@ authors = [ "Drazen Urch ", ] edition = "2018" +rust-version = "1.56" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tauri-wallet/Cargo.lock b/tauri-wallet/Cargo.lock index 43097c64a4..8e846a0cc1 100644 --- a/tauri-wallet/Cargo.lock +++ b/tauri-wallet/Cargo.lock @@ -12,15 +12,6 @@ dependencies = [ "regex", ] -[[package]] -name = "addr2line" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" @@ -42,15 +33,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "anomaly" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550632e31568ae1a5f47998c3aa48563030fc49b9ec91913ca337cf64fbc5ccb" -dependencies = [ - "backtrace", -] - [[package]] name = "anyhow" version = "1.0.43" @@ -148,21 +130,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "backtrace" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide 0.4.4", - "object", - "rustc-demangle", -] - [[package]] name = "base64" version = "0.13.0" @@ -430,12 +397,9 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "libc", "num-integer", "num-traits", "serde", - "time 0.1.43", - "winapi", ] [[package]] @@ -632,9 +596,9 @@ dependencies = [ [[package]] name = "cosmos-sdk-proto" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7115eae4b8518967b8e737a3ef76025f2d007de7906d88c18f00b8bbfc70f51e" +checksum = "edb5204c6ddc4352c74297638b5561f2929d6334866c156e5f3c75e1e1a1436a" dependencies = [ "prost", "prost-types", @@ -643,9 +607,9 @@ dependencies = [ [[package]] name = "cosmrs" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609eba7eee6d9929927cbdf15f9fe96d250c316c5e1b983c4a47a10f60da5ea7" +checksum = "d31147fe89e547e74e2692e4bec35387e1ea406fe8cfb14c0ea177b58fd2a8a9" dependencies = [ "bip32", "cosmos-sdk-proto", @@ -656,6 +620,8 @@ dependencies = [ "prost", "prost-types", "rand_core 0.6.3", + "serde", + "serde_json", "subtle-encoding", "tendermint", "tendermint-rpc", @@ -1077,7 +1043,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" dependencies = [ - "serde", "signature", ] @@ -1089,9 +1054,6 @@ checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ "curve25519-dalek", "ed25519", - "rand 0.7.3", - "serde", - "serde_bytes", "sha2", "zeroize", ] @@ -1228,6 +1190,16 @@ dependencies = [ "miniz_oxide 0.4.4", ] +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "eyre", + "paste", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1531,12 +1503,6 @@ dependencies = [ "syn", ] -[[package]] -name = "gimli" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" - [[package]] name = "gio" version = "0.14.5" @@ -1976,6 +1942,7 @@ dependencies = [ "tokio", "tokio-rustls", "webpki", + "webpki-roots", ] [[package]] @@ -2098,15 +2065,6 @@ dependencies = [ "syn", ] -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.10.1" @@ -2610,15 +2568,6 @@ dependencies = [ "objc", ] -[[package]] -name = "object" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.8.0" @@ -2744,6 +2693,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "paste" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" + [[package]] name = "pbkdf2" version = "0.8.0" @@ -2753,6 +2708,33 @@ dependencies = [ "crypto-mac", ] +[[package]] +name = "peg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -3061,9 +3043,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e6984d2f1a23009bd270b8bb56d0926810a3d483f59c987d77969e9d8e840b2" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ "bytes", "prost-derive", @@ -3071,12 +3053,12 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", - "itertools 0.9.0", + "itertools", "proc-macro2", "quote", "syn", @@ -3084,9 +3066,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b518d7cdd93dab1d1122cf07fa9a60771836c668dde9d9e2a139f957f0d9f1bb" +checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ "bytes", "prost", @@ -3476,12 +3458,6 @@ dependencies = [ "opaque-debug 0.3.0", ] -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - [[package]] name = "rustc_version" version = "0.3.3" @@ -4193,7 +4169,7 @@ dependencies = [ "anyhow", "cfg-expr", "heck", - "itertools 0.10.1", + "itertools", "pkg-config", "strum 0.21.0", "strum_macros 0.21.1", @@ -4408,16 +4384,16 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0752808f59b612916614e92e43be64e9ba566b762a266bcfcf7dce1b324e9319" +checksum = "50d1cdb0236becb17ab35a2ed1566503e412fd910944dc940239857bb7663652" dependencies = [ - "anomaly", "async-trait", "bytes", "chrono", "ed25519", "ed25519-dalek", + "flex-error", "futures", "k256", "num-traits", @@ -4434,21 +4410,32 @@ dependencies = [ "subtle", "subtle-encoding", "tendermint-proto", - "thiserror", - "toml", - "url", "zeroize", ] [[package]] -name = "tendermint-proto" -version = "0.21.0" +name = "tendermint-config" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd0371c6b0c7fc4f6b053b8a1bc868a2a47c49a1408c4cd6f595d9f3bd3c238" +checksum = "2a1f94250d30e3011130a09756b05985d8dbfbd562cf261b5a17e36d89a37992" +dependencies = [ + "flex-error", + "serde", + "serde_json", + "tendermint", + "toml", + "url", +] + +[[package]] +name = "tendermint-proto" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff16a7b42bdbcf31c8cd10a4cffc7631f2a301360ba3a3f71dde48eabfa5bced" dependencies = [ - "anomaly", "bytes", "chrono", + "flex-error", "num-derive", "num-traits", "prost", @@ -4456,30 +4443,32 @@ dependencies = [ "serde", "serde_bytes", "subtle-encoding", - "thiserror", ] [[package]] name = "tendermint-rpc" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fa8d172e3129802d28de980531993dd25cc01841c5bc8fe4a87c7750a7f222" +checksum = "c7842dcd5edb60b077572aa92ff8b29fc810b9b463310f9810a2607474130db4" dependencies = [ "async-trait", "bytes", "chrono", + "flex-error", "futures", "getrandom 0.1.16", "http", "hyper", "hyper-proxy", "hyper-rustls", + "peg", "pin-project", "serde", "serde_bytes", "serde_json", "subtle-encoding", "tendermint", + "tendermint-config", "tendermint-proto", "thiserror", "tokio", @@ -4656,21 +4645,9 @@ checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" version = "0.1.19" @@ -4812,7 +4789,7 @@ dependencies = [ "cosmrs", "cosmwasm-std", "flate2", - "itertools 0.10.1", + "itertools", "log", "mixnet-contract", "network-defaults", @@ -5023,6 +5000,15 @@ dependencies = [ "untrusted", ] +[[package]] +name = "webpki-roots" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki", +] + [[package]] name = "webview2" version = "0.1.1" diff --git a/tauri-wallet/README.md b/tauri-wallet/README.md index 465cd18132..5cd0fdd60a 100644 --- a/tauri-wallet/README.md +++ b/tauri-wallet/README.md @@ -7,12 +7,19 @@ SPDX-License-Identifier: Apache-2.0 A Rust and Tauri desktop wallet implementation. -## Installation prerequisites +## Installation prerequisites Linux / Mac - `Yarn` - `NodeJS >= v16.8.0` - `Rust & cargo >= v1.51` +## Installation prerequisites Windows + +- When running on Windows you will need to install c++ build tools +- An easy guide to get rust up and running [Installation]("http://kennykerr.ca/2019/11/18/rust-getting-started/") +- When installing NodeJS please use the `current features` version +- Using a package manager like [Chocolatey]("chocolatey.org") is recommended + ## Installation Inside of the `tauri-wallet` folder, run the following commands diff --git a/tauri-wallet/src-tauri/Cargo.toml b/tauri-wallet/src-tauri/Cargo.toml index 9737017ee4..5689dec128 100644 --- a/tauri-wallet/src-tauri/Cargo.toml +++ b/tauri-wallet/src-tauri/Cargo.toml @@ -8,6 +8,7 @@ repository = "" default-run = "nym_wallet" edition = "2018" build = "src/build.rs" +rust-version = "1.56" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -23,12 +24,12 @@ dirs = "3.0" # url = "2.2" bip39 = "1.0" thiserror = "1.0" -tendermint-rpc = "0.21.0" +tendermint-rpc = "0.23.0" ts-rs = "3.0" url = "2.0" rand = "0.6.5" -cosmrs = { version = "0.1", features = ["rpc", "bip32", "cosmwasm"] } +cosmrs = { version = "0.3", features = ["rpc", "bip32", "cosmwasm"] } cosmwasm-std = { git = "https://github.com/jstuczyn/cosmwasm", branch = "0.14.1-updatedk256" } validator-client = { path = "../../common/client-libs/validator-client", features = [ diff --git a/tauri-wallet/src-tauri/src/main.rs b/tauri-wallet/src-tauri/src/main.rs index 28aecff021..8ac9f6c423 100644 --- a/tauri-wallet/src-tauri/src/main.rs +++ b/tauri-wallet/src-tauri/src/main.rs @@ -5,6 +5,7 @@ use mixnet_contract::{Gateway, MixNode}; use std::sync::Arc; +use tauri::{Menu, MenuItem}; use tokio::sync::RwLock; use ts_rs::export; use validator_client::nymd::fee_helpers::Operation; @@ -35,6 +36,12 @@ macro_rules! format_err { }; } +pub fn create_menu_items() -> Menu { + Menu::new() + .add_native_item(MenuItem::Copy) + .add_native_item(MenuItem::Paste) +} + fn main() { tauri::Builder::default() .manage(Arc::new(RwLock::new(State::default()))) @@ -51,16 +58,14 @@ fn main() { unbond_gateway, delegate_to_mixnode, undelegate_from_mixnode, - delegate_to_gateway, - undelegate_from_gateway, send, create_new_account, get_fee, get_state_params, update_state_params, get_reverse_mix_delegations_paged, - get_reverse_gateway_delegations_paged, ]) + .menu(create_menu_items()) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/tauri-wallet/src-tauri/src/operations/admin.rs b/tauri-wallet/src-tauri/src/operations/admin.rs index 2d3ad52ae7..71ac69af8a 100644 --- a/tauri-wallet/src-tauri/src/operations/admin.rs +++ b/tauri-wallet/src-tauri/src/operations/admin.rs @@ -16,11 +16,8 @@ pub struct TauriStateParams { minimum_mixnode_bond: String, minimum_gateway_bond: String, mixnode_bond_reward_rate: String, - gateway_bond_reward_rate: String, mixnode_delegation_reward_rate: String, - gateway_delegation_reward_rate: String, mixnode_active_set_size: u32, - gateway_active_set_size: u32, } impl From for TauriStateParams { @@ -30,11 +27,8 @@ impl From for TauriStateParams { minimum_mixnode_bond: p.minimum_mixnode_bond.to_string(), minimum_gateway_bond: p.minimum_gateway_bond.to_string(), mixnode_bond_reward_rate: p.mixnode_bond_reward_rate.to_string(), - gateway_bond_reward_rate: p.gateway_bond_reward_rate.to_string(), mixnode_delegation_reward_rate: p.mixnode_delegation_reward_rate.to_string(), - gateway_delegation_reward_rate: p.gateway_delegation_reward_rate.to_string(), mixnode_active_set_size: p.mixnode_active_set_size, - gateway_active_set_size: p.gateway_active_set_size, } } } @@ -48,11 +42,8 @@ impl TryFrom for StateParams { minimum_mixnode_bond: Uint128::try_from(p.minimum_mixnode_bond.as_str())?, minimum_gateway_bond: Uint128::try_from(p.minimum_gateway_bond.as_str())?, mixnode_bond_reward_rate: Decimal::from_str(p.mixnode_bond_reward_rate.as_str())?, - gateway_bond_reward_rate: Decimal::from_str(p.gateway_bond_reward_rate.as_str())?, mixnode_delegation_reward_rate: Decimal::from_str(p.mixnode_delegation_reward_rate.as_str())?, - gateway_delegation_reward_rate: Decimal::from_str(p.gateway_delegation_reward_rate.as_str())?, mixnode_active_set_size: p.mixnode_active_set_size, - gateway_active_set_size: p.gateway_active_set_size, }) } } diff --git a/tauri-wallet/src-tauri/src/operations/delegate.rs b/tauri-wallet/src-tauri/src/operations/delegate.rs index bba966ebec..a9c9a75269 100644 --- a/tauri-wallet/src-tauri/src/operations/delegate.rs +++ b/tauri-wallet/src-tauri/src/operations/delegate.rs @@ -2,9 +2,7 @@ use crate::coin::Coin; use crate::format_err; use crate::state::State; use cosmwasm_std::Coin as CosmWasmCoin; -use mixnet_contract::{ - Addr, PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse, -}; +use mixnet_contract::{Addr, PagedReverseMixDelegationsResponse}; use serde::{Deserialize, Serialize}; use std::convert::TryInto; use std::sync::Arc; @@ -57,45 +55,6 @@ pub async fn undelegate_from_mixnode( } } -#[tauri::command] -pub async fn delegate_to_gateway( - identity: &str, - amount: Coin, - state: tauri::State<'_, Arc>>, -) -> Result { - let r_state = state.read().await; - let bond: CosmWasmCoin = match amount.try_into() { - Ok(b) => b, - Err(e) => return Err(format_err!(e)), - }; - let client = r_state.client()?; - match client.delegate_to_gateway(identity, &bond).await { - Ok(_result) => Ok(DelegationResult { - source_address: client.address().to_string(), - target_address: identity.to_string(), - amount: Some(bond.into()), - }), - Err(e) => Err(format_err!(e)), - } -} - -#[tauri::command] -pub async fn undelegate_from_gateway( - identity: &str, - state: tauri::State<'_, Arc>>, -) -> Result { - let r_state = state.read().await; - let client = r_state.client()?; - match client.remove_gateway_delegation(identity).await { - Ok(_result) => Ok(DelegationResult { - source_address: client.address().to_string(), - target_address: identity.to_string(), - amount: None, - }), - Err(e) => Err(format_err!(e)), - } -} - #[tauri::command] pub async fn get_reverse_mix_delegations_paged( state: tauri::State<'_, Arc>>, @@ -104,16 +63,6 @@ pub async fn get_reverse_mix_delegations_paged( let client = r_state.client()?; client .get_reverse_mix_delegations_paged(Addr::unchecked(client.address().as_ref()), None, None) - .await.map_err(|err| format_err!(err)) -} - -#[tauri::command] -pub async fn get_reverse_gateway_delegations_paged( - state: tauri::State<'_, Arc>>, -) -> Result { - let r_state = state.read().await; - let client = r_state.client()?; - client - .get_reverse_gateway_delegations_paged(Addr::unchecked(client.address().as_ref()), None, None) - .await.map_err(|err| format_err!(err)) + .await + .map_err(|err| format_err!(err)) } diff --git a/tauri-wallet/src/components/Confirmation.tsx b/tauri-wallet/src/components/Confirmation.tsx index 593eed90af..e227021d0b 100644 --- a/tauri-wallet/src/components/Confirmation.tsx +++ b/tauri-wallet/src/components/Confirmation.tsx @@ -33,7 +33,7 @@ export const Confirmation = ({ {error === null ? ( SuccessMessage ) : ( - + {error.name} {failureMessage} - {error.message} diff --git a/tauri-wallet/src/components/CopyToClipboard.tsx b/tauri-wallet/src/components/CopyToClipboard.tsx index c1c6da79d2..9e4cd4ae71 100644 --- a/tauri-wallet/src/components/CopyToClipboard.tsx +++ b/tauri-wallet/src/components/CopyToClipboard.tsx @@ -40,6 +40,7 @@ export const CopyToClipboard = ({ text }: { text: string }) => { size="small" variant={copied ? 'text' : 'outlined'} aria-label="save" + data-testid="copy-button" onClick={() => handleCopy({ text, cb: updateCopyStatus })} endIcon={copied && } style={copied ? { background: green[500], color: 'white' } : {}} diff --git a/tauri-wallet/src/components/Error.tsx b/tauri-wallet/src/components/Error.tsx index 0537674d8b..d1947bac31 100644 --- a/tauri-wallet/src/components/Error.tsx +++ b/tauri-wallet/src/components/Error.tsx @@ -6,11 +6,11 @@ import { Button } from '@material-ui/core' export const ErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => { return (
- + {error.name} {error.message} - + Stack trace {error.stack} diff --git a/tauri-wallet/src/components/Nav.tsx b/tauri-wallet/src/components/Nav.tsx index 3e870e4edd..4af636f53f 100644 --- a/tauri-wallet/src/components/Nav.tsx +++ b/tauri-wallet/src/components/Nav.tsx @@ -131,7 +131,7 @@ export const Nav = () => { )} - + { noPadding Action={ - + @@ -43,7 +43,7 @@ export const BalanceCard = () => { {getBalance.error} ) : ( - + {getBalance.balance?.printable_balance} )} @@ -71,6 +71,7 @@ export const AddressCard = () => { title="Address" subheader="Wallet payments address" noPadding + data-testid="wallet-address-header" Action={ @@ -106,7 +107,7 @@ export const AddressCard = () => { } > - {truncate(clientDetails?.client_address!, 35)} diff --git a/tauri-wallet/src/components/NoClientError.tsx b/tauri-wallet/src/components/NoClientError.tsx index 9e1022babb..cf65ae0904 100644 --- a/tauri-wallet/src/components/NoClientError.tsx +++ b/tauri-wallet/src/components/NoClientError.tsx @@ -5,7 +5,7 @@ import { Alert, AlertTitle } from '@material-ui/lab' export const NoClientError = () => { return ( - No client detected + No client detected Have you signed in? Try to go back to{' '} the main page and try again diff --git a/tauri-wallet/src/components/NodeTypeSelector.tsx b/tauri-wallet/src/components/NodeTypeSelector.tsx index b949eb00d3..e36432a637 100644 --- a/tauri-wallet/src/components/NodeTypeSelector.tsx +++ b/tauri-wallet/src/components/NodeTypeSelector.tsx @@ -34,11 +34,13 @@ export const NodeTypeSelector = ({ value={EnumNodeType.mixnode} control={} label="Mixnode" + data-testid="mix-node" disabled={disabled} /> } + data-testid="gate-way" label="Gateway" disabled={disabled} /> diff --git a/tauri-wallet/src/components/NymCard.tsx b/tauri-wallet/src/components/NymCard.tsx index c77fe38359..162610b15b 100644 --- a/tauri-wallet/src/components/NymCard.tsx +++ b/tauri-wallet/src/components/NymCard.tsx @@ -13,6 +13,7 @@ export const NymCard: React.FC<{ { size="small" color="primary" type="submit" + data-testid="refresh-button" onClick={fetchBalance} disabled={isLoading} disableElevation @@ -31,12 +32,13 @@ export const Balance = () => { return ( - + {error && ( } style={{ padding: theme.spacing(2) }} > @@ -46,6 +48,7 @@ export const Balance = () => { {!error && ( } > diff --git a/tauri-wallet/src/routes/bond/BondForm.tsx b/tauri-wallet/src/routes/bond/BondForm.tsx index 8d1152bed9..ea689aa7db 100644 --- a/tauri-wallet/src/routes/bond/BondForm.tsx +++ b/tauri-wallet/src/routes/bond/BondForm.tsx @@ -142,7 +142,7 @@ export const BondForm = ({ {fees && ( - + {`A fee of ${ watchNodeType === EnumNodeType.mixnode ? fees.mixnode.amount @@ -369,6 +369,7 @@ export const BondForm = ({ color="primary" type="submit" size="large" + data-testid="submit-button" disableElevation onClick={handleSubmit(onSubmit)} endIcon={isSubmitting && } diff --git a/tauri-wallet/src/routes/bond/index.tsx b/tauri-wallet/src/routes/bond/index.tsx index 1c06f9051e..0e89ae070f 100644 --- a/tauri-wallet/src/routes/bond/index.tsx +++ b/tauri-wallet/src/routes/bond/index.tsx @@ -43,7 +43,7 @@ export const Bond = () => { {ownership?.hasOwnership && ( { getBalance.fetchBalance() setStatus(EnumRequestStatus.initial) }} + data-testid="unBond" > Unbond @@ -93,10 +94,10 @@ export const Bond = () => { Successfully bonded node + Successfully bonded node } Error={ - + An error occurred with the request: {message} } diff --git a/tauri-wallet/src/routes/delegate/DelegateForm.tsx b/tauri-wallet/src/routes/delegate/DelegateForm.tsx index 50fb7a4929..0a32c08395 100644 --- a/tauri-wallet/src/routes/delegate/DelegateForm.tsx +++ b/tauri-wallet/src/routes/delegate/DelegateForm.tsx @@ -97,7 +97,7 @@ export const DelegateForm = ({ /> - + {`A fee of ${ watchNodeType === EnumNodeType.mixnode ? fees.mixnode.amount @@ -153,6 +153,7 @@ export const DelegateForm = ({
- {data.to_address} + {data.to_address}
@@ -70,7 +70,7 @@ export const SendConfirmation = ({
- {data.amount.amount + ' punks'} + {data.amount.amount + ' punks'}
diff --git a/tauri-wallet/src/routes/send/SendError.tsx b/tauri-wallet/src/routes/send/SendError.tsx index 2fcb9ce5be..f90c9b9df5 100644 --- a/tauri-wallet/src/routes/send/SendError.tsx +++ b/tauri-wallet/src/routes/send/SendError.tsx @@ -37,7 +37,7 @@ export const SendError = ({ message }: { message?: string }) => { variant="outlined" style={{ width: '100%', padding: theme.spacing(2) }} > - + An error occured during the request {message} diff --git a/tauri-wallet/src/routes/send/SendReview.tsx b/tauri-wallet/src/routes/send/SendReview.tsx index e9d0e23095..b51edc1626 100644 --- a/tauri-wallet/src/routes/send/SendReview.tsx +++ b/tauri-wallet/src/routes/send/SendReview.tsx @@ -44,7 +44,7 @@ export const SendReview = () => { ) : ( - + @@ -86,7 +86,7 @@ export const SendReviewField = ({ {title} - {subtitle} + {subtitle} ) } diff --git a/tauri-wallet/src/routes/send/SendWizard.tsx b/tauri-wallet/src/routes/send/SendWizard.tsx index ee03bab9aa..2f41946157 100644 --- a/tauri-wallet/src/routes/send/SendWizard.tsx +++ b/tauri-wallet/src/routes/send/SendWizard.tsx @@ -148,6 +148,7 @@ export const SendWizard = () => { disableElevation style={{ marginRight: theme.spacing(1) }} onClick={handlePreviousStep} + data-testid="back-button" > Back @@ -156,6 +157,7 @@ export const SendWizard = () => { variant={activeStep > 0 ? 'contained' : 'text'} color={activeStep > 0 ? 'primary' : 'default'} disableElevation + data-testid="button" onClick={ activeStep === 0 ? handleNextStep diff --git a/tauri-wallet/src/routes/sign-in.tsx b/tauri-wallet/src/routes/sign-in.tsx index d80a81060f..0cbac9f2ac 100644 --- a/tauri-wallet/src/routes/sign-in.tsx +++ b/tauri-wallet/src/routes/sign-in.tsx @@ -100,7 +100,7 @@ const SignInContent = ({ return ( <> - Sign in + Sign in
@@ -239,7 +239,7 @@ const CreateAccountContent = ({ showSignIn }: { showSignIn: () => void }) => { /> Wallet setup complete - + Please store your mnemonic in a safe place. You'll need it to access your wallet @@ -257,7 +257,7 @@ const CreateAccountContent = ({ showSignIn }: { showSignIn: () => void }) => { - {accountDetails.mnemonic} + {accountDetails.mnemonic}
@@ -273,7 +273,7 @@ const CreateAccountContent = ({ showSignIn }: { showSignIn: () => void }) => { - {accountDetails.client_address} + {accountDetails.client_address} @@ -282,7 +282,7 @@ const CreateAccountContent = ({ showSignIn }: { showSignIn: () => void }) => { {error && ( - {error} + {error} )} @@ -293,6 +293,7 @@ const CreateAccountContent = ({ showSignIn }: { showSignIn: () => void }) => { variant="contained" color="primary" type="submit" + data-testid="create-button" disableElevation style={{ marginBottom: theme.spacing(1) }} disabled={isLoading} @@ -304,6 +305,7 @@ const CreateAccountContent = ({ showSignIn }: { showSignIn: () => void }) => { fullWidth variant="text" onClick={showSignIn} + data-testid="sign-in-button" startIcon={} > Sign in diff --git a/tauri-wallet/src/routes/unbond/index.tsx b/tauri-wallet/src/routes/unbond/index.tsx index 9ae5ed6f01..2edca71138 100644 --- a/tauri-wallet/src/routes/unbond/index.tsx +++ b/tauri-wallet/src/routes/unbond/index.tsx @@ -29,8 +29,10 @@ export const Unbond = () => { {ownership?.hasOwnership && ( { setIsLoading(true) @@ -48,7 +50,7 @@ export const Unbond = () => { )} {!ownership.hasOwnership && ( - + You don't currently have a bonded node )} diff --git a/tauri-wallet/src/routes/undelegate/UndelegateForm.tsx b/tauri-wallet/src/routes/undelegate/UndelegateForm.tsx index cd41145aa6..4be7bacf45 100644 --- a/tauri-wallet/src/routes/undelegate/UndelegateForm.tsx +++ b/tauri-wallet/src/routes/undelegate/UndelegateForm.tsx @@ -84,7 +84,7 @@ export const UndelegateForm = ({ /> - + {`A fee of ${ watchNodeType === EnumNodeType.mixnode ? fees.mixnode.amount @@ -140,6 +140,7 @@ export const UndelegateForm = ({ variant="contained" color="primary" type="submit" + data-testid="submit-button" disableElevation disabled={isSubmitting} endIcon={isSubmitting && } diff --git a/tauri-wallet/src/routes/undelegate/index.tsx b/tauri-wallet/src/routes/undelegate/index.tsx index 456285d980..98b6319b08 100644 --- a/tauri-wallet/src/routes/undelegate/index.tsx +++ b/tauri-wallet/src/routes/undelegate/index.tsx @@ -102,14 +102,14 @@ export const Undelegate = () => { + An error occurred with the request: {message} } Success={ {' '} - Undelegation complete + Undelegation complete {message} } @@ -125,6 +125,7 @@ export const Undelegate = () => { }} >